Table of Contents

Events, jobs and scheduling

Publish in-process events, run work on a thread pool, and schedule recurring jobs with cron.

What you'll build

A host that uses three core services from SquidStd.Services.Core: the IEventBus (publish/subscribe), the IJobSystem (thread-pool work), and the ICronScheduler (cron-based recurring jobs).

Prerequisites

  • .NET 10 SDK
  • dotnet add package SquidStd.Services.Core

The core services are explicit: enable the event bus, job system and timer wheel with RegisterCoreServices(), and add the cron scheduler on top with RegisterSchedulerServices():


var eventBus = bootstrap.Resolve<IEventBus>();
await eventBus.PublishAsync(new PingEvent("hello"), CancellationToken.None);

Steps

1. Publish and handle an event

Implement IAsyncEventListener<T>, register it, and publish an IEvent. Every registered listener is awaited.


var eventBus = bootstrap.Resolve<IEventBus>();
await eventBus.PublishAsync(new PingEvent("hello"), CancellationToken.None);

2. Run work on the job system

IJobSystem.ScheduleAsync runs an Action on a worker thread and returns a Task that completes when it finishes.


var jobs = bootstrap.Resolve<IJobSystem>();
await jobs.ScheduleAsync(() => Console.WriteLine("job ran on a worker thread"));

3. Schedule a cron job

ICronScheduler.Schedule takes a name, a 5-field cron expression (UTC), and an async handler invoked on each occurrence.


var cron = bootstrap.Resolve<ICronScheduler>();
cron.Schedule(
    "heartbeat",
    "*/5 * * * *",
    _ =>
    {
        Console.WriteLine("cron tick");

        return Task.CompletedTask;
    }
);

Run it

dotnet run --project samples/SquidStd.Samples.EventsJobsScheduling

You'll see received: hello, job ran on a worker thread, and, if you let it run across a 5-minute boundary, cron tick.

How it works

The event bus and the job system come from RegisterCoreServices() - the bus dispatches to sync and async listeners, the job system is a fixed-size worker-thread pool. The cron scheduler is driven by the timer wheel (registered by RegisterSchedulerServices).

The timer wheel is advanced by a driver. RegisterSchedulerServices() uses TimerWheelPumpService, a periodic background pump. Apps that need a frame-rate loop can instead call RegisterEventLoop(), which advances the wheel and drains the main-thread dispatcher on a dedicated thread - see Scheduler → Event loop. The two are mutually exclusive: register exactly one.

See also