# Report Scheduler

Let's say your web app allows users to schedule reports to email off. These items are configurable and the user can add or remove them at any time.

* The front-end web app saves a database record back with all the information needed to run the specific report and it's parameters.
* Then the [Scheduler](/core-modules/event-sources/scheduled-logic/scheduler.md) reads the table for those database records every few minutes and updates, removes, reschedules any changed items.
* You get a simple callback when it's time to execute the event task

### Demo Scheduler

The demo below hooks up everything but actually generating reports, and [emailing](/core-modules/alert-managers/email.md) them off.&#x20;

* The `RunType` argument could easily contain what reports to generate.
* The `RunArgs` could easily contain additional user information like who it's being sent to, a database ID of the job to lookup, etc. &#x20;

{% code lineNumbers="true" %}

```csharp
PerigeeApplication.ApplicationNoInit("Demo Scheduler", (c) =>
{
   
    //Declare a new memory source, remember to use a single instance of memory/file based sources or locking can occur
    using var MemSource = new MemoryScheduledSource("memSource.json", c.CTS.Token);

    //Add scheduled items.
    //If this was something like a DatabaseScheduledSource, we obviously would control these records from the database, not here.
    MemSource.AddIfNotExists(GenericScheduledItem<ushort>.MemoryItem(0, "A scheduler, 15sec", "A", "a;b;c", "*/15 * * * * *", TimeZoneInfo.Local));
    MemSource.AddIfNotExists(GenericScheduledItem<ushort>.MemoryItem(1, "B scheduler, 45sec", "B", "b;c;d", "45 * * * * *", TimeZoneInfo.Local));

    //Add a scheduler with the MemorySource, a single callback is given for anything required to run (multi-threaded)
    c.AddScheduler("Main", MemSource, (ct, l, item) => { 
        if (item.GetRunType() == "A")
        {
            l.LogInformation("Running A with {args}", item.GetRunArgs());
        }
        else if (item.GetRunType() == "B")
        {
            l.LogInformation("Running B with {args}", item.GetRunArgs());
        }

    });

});
```

{% endcode %}

{% hint style="info" %}
The demo code uses the [**`Memory Scheduler`**](#memory-source) as it does not require a remote source. Typically speaking you would tie the event task descriptions back to a database record (like the MSSQL Scheduler Source).
{% endhint %}

* <mark style="color:blue;">**Line 5**</mark> - Declare a new event source. This demo uses the memory scheduler.
* <mark style="color:blue;">**Line 9-10**</mark> - Add the two scheduled items, A, and B, to schedule and execute
* <mark style="color:blue;">**Line 13**</mark> - Add a scheduler using the source we defined, and declare the callback.
  * You're given a <mark style="color:orange;">**CancellationToken**</mark> for respecting graceful shutdown event.
  * An <mark style="color:orange;">**ILogger**</mark> for logging to the system and defined sink sources.
  * And the <mark style="color:orange;">**GenericScheduledItem\<ushort>**</mark> Which is the interfaced item that allows you to access it's definition values.
* <mark style="color:blue;">**Line 14**</mark> - You can execute or perform any tasks you need. Like generating a report with parameters.
  * You can see the call to `GetRunType()`. There's also `GetRunArgs()`, `GetLastRunDate()`, `GetName()`, etc.

##


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.perigee.software/examples-and-demos/report-scheduler.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
