--- applyTo: "Fuchs_DataService/**" --- # PeriodicHostedService Instructions ## Overview `PeriodicHostedService` (`Fuchs_DataService/PeriodicHostedService.cs`) is a `BackgroundService` that runs multiple independent jobs, each on its own `PeriodicTimer`. It is started and stopped by the Topshelf `FdsService` (see `topshelf.instructions.md`). ## Job Definition Each job is a `PeriodicJobDefinition` record: ```csharp public sealed record PeriodicJobDefinition( string Name, TimeSpan Interval, Func Execute); ``` ## Registering Jobs Jobs are created in `FdsService` constructor and passed to `PeriodicHostedService`: ```csharp var interval = TimeSpan.FromMinutes(FdsConfig.ExecutionFrequency_Minutes); var jobs = new[] { new PeriodicJobDefinition("MfrSync", interval, async ct => { await mfr.UpdateIfNecessary_async(debug); await mfr.UpdateRequested_async(debug); await mfr.GetInvoiceFiles_async(debug); }), // Add more jobs with different schedules here: // new PeriodicJobDefinition("HourlyJob", TimeSpan.FromHours(1), async ct => { ... }) }; ``` ## Schedules - Each job runs on its **own independent `PeriodicTimer`** — schedules do not interfere. - Frequencies are configured in `appsettings.json` under the `Fds` section (e.g. `Fds:ExecutionFrequency_Minutes`). - Add new config keys for additional job intervals as needed. ## Error Handling - Each job's `Execute` delegate is wrapped in a `try/catch` inside `RunJobAsync`. - `OperationCanceledException` propagates normally (signals shutdown). - All other exceptions are caught, logged via `ILogger`, and the job continues on its next tick. ## Cancellation - `PeriodicHostedService` respects the `CancellationToken` passed to `StartAsync`. - `FdsService.Stop()` cancels the token, then awaits `StopAsync(CancellationToken.None)`. ## Adding a New Job 1. Optionally add a new frequency key to `appsettings.json` and read it via `FdsConfig`. 2. Add a new `PeriodicJobDefinition` to the `jobs` array in `FdsService`. 3. No changes to `PeriodicHostedService` itself are needed.