FileWatcher Task mit SSIS Bordmitteln

19. Januar 2011

Ein typisches Problem in einem produktiven Integration Services Umfeld ist das Erkennen der Fertigstellung eines vollständigen Satzes von Input-Dateien aus Quellsystemen. SSIS soll normalerweise erst starten, wenn der vollständige Satz an Quelldateien vorliegt. Üblicherweise wird der SSIS-Start produktiv jedoch zu festgelegten Zeiten ausgeführt.

Hat das Quellsystem den vollständigen Satz an Input-Dateien noch nicht erzeugt, ist der gesamte ETL-Vorgang eventuell wertlos. Ist das Quellsystem dagegen schon längere Zeit fertig, wird womöglich in der Produktion wertvolle Zeit verschenkt.

Ein Lösungsansatz liegt darin, dass das Quellsystem eine Ready-Datei als Indikator für die Bereitstellung aller Quelldateien erzeugt. SSIS muss jetzt nur noch in regelmäßigen Abständen nach dieser Datei suchen, jedoch nicht ewig warten. Es soll möglich sein, eine Uhrzeit als späteste Startzeit zu setzen. Und das geht so:

  1. Anlegen von zwei String Variablen PackageStartTime und ReadyFilePath. Diese werden beim Paketstart als Parameter gesetzt.
  2. Im Paket wird ein ForLoop Container FLC WaitForReadyFile sowie eine Boolean Variable Wait angelegt, die als EvalExpression ausgewertet wird. Im ForLoop Container wird eine Script Task SCR CheckReadyFile platziert, die u.a. diese Variable setzt.
  3. In der Script Task werden PackageStartTime, ReadyFilePath sowie die aktuelle Uhrzeit ausgewertet. Ist die Ready-Datei noch nicht vorhanden und die späteste Startzeit noch nicht erreicht, bleibt User::Wait auf False und die Loop fährt fort. Der Code verwendet dazu Thread.Sleep(). Ausschnitt:
       1: try

       2: {

       3:     // PackageStartTime (Format 00:00) in dHour und dMin aufspalten

       4:     // ...

       5:     // Späteste erlaubte Startzeit

       6:     DateTime dtMax = DateTime.Today.AddHours(dHour).AddMinutes(dMin);

       7:     // Existiert die Ready-Datei schon ?

       8:     Boolean bReadyFileExists = 

       9:         File.Exists(Dts.Variables["ReadyFilePath"].Value.ToString());

      10:     // Späteste Startzeit erreicht?

      11:     if (DateTime.Now >= dtMax)

      12:     {

      13:         Dts.Variables["Wait"].Value = false;

      14:     }

      15:     // Späteste Startzeit noch nicht erreicht, existiert Ready File schon?

      16:     else if (bReadyFileExists)

      17:     {

      18:         Dts.Variables["Wait"].Value = false;

      19:     }

      20:     // Keine der Abbruchbedingungen erfüllt. Weiter warten.

      21:     else

      22:     {

      23:         Thread.Sleep(WAITING_MINUTES * 60 * 1000);

      24:     }

      25: }

      26: catch(Exception ex)

      27: {

      28:     // Ein Fehler ist aufgetreten. Fehlerhandling + Sofort weiterlaufen

      29:     // ...

      30:     Dts.Variables["Wait"].Value = false;

      31: }

      32:  

  4. Im Anschluss an den ForLoop Container können dann die weiteren Paketobjekte angefügt werden. Das Paket sieht jetzt beispielsweise so aus: Package
  5. Am Ende der Paketausführung nicht vergessen die Ready-Datei wieder zu löschen falls immer der gleiche Name dafür verwendet wird.
  6. Beim Starten des Paketes mit dem SSIS Execute Package Utility können die angesprochenen Paketvariablen mit der Option /SET gesetzt werden.

Ergebnis: Nach dem Starten des Paketes verbleibt die Ausführung so lange in der ForLoop bis die späteste Startzeit erreicht ist oder die Ready-Datei bereitgestellt wurde. Danach wird die weitere Verarbeitung fortgesetzt.

Fazit: Bereits mit SSIS-Bordmitteln lässt sich eine produktionsfähige Filewatcher-Funktionalität aufbauen. Custom Components wie z.B. Konesans Filewatcher Task sind hierzu nicht unbedingt erforderlich. Damit gestaltet sich die Produktivnahme besonders einfach und flexibel.