Skip to content

Latest commit

 

History

History
667 lines (478 loc) · 15.9 KB

File metadata and controls

667 lines (478 loc) · 15.9 KB

XpressWork API Reference

Complete reference for all public types, methods, and properties in XpressWork.

Table of Contents


ServiceCollectionExtensions

Extension methods for registering XpressWork services.

AddXpressWork<TContext, TScopeFactory>

Registers all XpressWork services with a custom context type and scope factory.

public static IServiceCollection AddXpressWork<TContext, TScopeFactory>(
    this IServiceCollection services,
    Action<XpressWorkOptions>? configureOptions = null)
    where TScopeFactory : class, IBackgroundWorkScopeFactory<TContext>

Type Parameters:

  • TContext - The context type to capture and restore
  • TScopeFactory - Your implementation of IBackgroundWorkScopeFactory<TContext>

Parameters:

  • services - The service collection
  • configureOptions - Optional action to configure XpressWorkOptions

Example:

services.AddXpressWork<MyAppContext, MyAppScopeFactory>(options =>
{
    options.MaxQueueLength = 1000;
    options.DrainOnShutdown = true;
});

AddXpressWork

Registers XpressWork services without custom context (uses object? as context type).

public static IServiceCollection AddXpressWork(
    this IServiceCollection services,
    Action<XpressWorkOptions>? configureOptions = null)

Example:

services.AddXpressWork();

AddXpressWorkScheduling<TContext>

Registers the background work scheduler for rate-controlled work submission.

public static IServiceCollection AddXpressWorkScheduling<TContext>(
    this IServiceCollection services)

Type Parameters:

  • TContext - The context type (must match your AddXpressWork call)

Example:

services.AddXpressWork<MyAppContext, MyAppScopeFactory>();
services.AddXpressWorkScheduling<MyAppContext>();  // Add scheduling support

Note: Call after AddXpressWork as scheduling depends on the queue being registered.


AddWorkHandler<TWorkArguments, THandler>

Registers a work handler for a specific work arguments type.

public static IServiceCollection AddWorkHandler<TWorkArguments, THandler>(
    this IServiceCollection services)
    where THandler : class, IWorkHandler<TWorkArguments>

Example:

services.AddWorkHandler<SendEmailArgs, SendEmailHandler>();
services.AddWorkHandler<SendEmailArgs, LogEmailHandler>();  // Multiple handlers OK

AddBackgroundActionWorkHandler

Registers the built-in handler for delegate-based work.

public static IServiceCollection AddBackgroundActionWorkHandler(
    this IServiceCollection services)

Example:

services.AddBackgroundActionWorkHandler();

IBackgroundWorkSubmitter<TContext>

Scoped service for submitting work to the background queue.

Lifetime: Scoped

Enqueue

Enqueues work arguments for background processing.

ValueTask<TaskCompletionSource> Enqueue(
    object workArguments,
    bool awaited = true,
    CancellationToken cancellationToken = default)

Parameters:

  • workArguments - The work to process (must not contain scoped services)
  • awaited - If true, queue waits for this item before processing next
  • cancellationToken - Cancellation token for the enqueue operation

Returns: A TaskCompletionSource to track completion

Example:

var completion = await _submitter.Enqueue(new SendEmailArgs { To = "test@example.com" });
await completion.Task;  // Wait for completion

Invoke

Immediately executes work, bypassing the queue.

Task Invoke(
    object workArguments,
    CancellationToken cancellationToken = default)

Example:

await _submitter.Invoke(new UrgentWorkArgs { ... });

IBackgroundWorkQueue<TContext>

Singleton hosted service that processes work items.

Lifetime: Singleton (IHostedService)

Properties

Property Type Description
QueueLength int Number of items waiting in the queue

Methods

Enqueue

Enqueues work with explicit context.

ValueTask<TaskCompletionSource> Enqueue(
    object workArguments,
    TContext? context = default,
    bool awaited = true,
    CancellationToken cancellationToken = default)

Invoke

Immediately executes work with explicit context.

Task Invoke(
    object workArguments,
    TContext? context = default,
    CancellationToken cancellationToken = default)

Note: Prefer using IBackgroundWorkSubmitter<TContext> instead of IBackgroundWorkQueue<TContext> directly, as the submitter handles context capture automatically.


IBackgroundWorkScheduler<TContext>

Singleton hosted service for rate-controlled work submission.

Lifetime: Singleton (IHostedService)

Methods

Debounce<T>

Schedules work using debounce semantics - executes after a period of inactivity.

ValueTask Debounce<T>(
    TimeSpan interval,
    Guid key,
    T workArgument,
    TContext? context = default,
    bool awaited = true,
    bool preserveDispatcher = false,
    CancellationToken cancellationToken = default)

Parameters:

  • interval - The debounce interval. Work executes only after this duration passes with no new calls.
  • key - A unique key to identify this debounced work. Multiple calls with the same key reset the timer.
  • workArgument - The work arguments to enqueue when the debounce period expires.
  • context - Optional context. If not provided, context may be captured from current scope.
  • awaited - If true, the queue processor will await this item's completion.
  • preserveDispatcher - If true, preserves the dispatcher entry after execution.
  • cancellationToken - A cancellation token.

Example:

// Save only after 500ms of inactivity
await scheduler.Debounce(
    TimeSpan.FromMilliseconds(500),
    userId,
    new SavePreferencesArgs { UserId = userId });

Throttle<T>

Schedules work using throttle semantics - executes at most once per interval.

ValueTask Throttle<T>(
    TimeSpan interval,
    Guid key,
    T workArgument,
    TContext? context = default,
    bool awaited = true,
    bool preserveDispatcher = false,
    CancellationToken cancellationToken = default)

Parameters:

  • interval - The throttle interval. After execution, subsequent calls are delayed until this interval expires.
  • key - A unique key to identify this throttled work stream.
  • workArgument - The work arguments.
  • context - Optional context.
  • awaited - If true, the queue processor will await this item's completion.
  • preserveDispatcher - If true, preserves the dispatcher entry after execution.
  • cancellationToken - A cancellation token.

Example:

// Process at most once per second
await scheduler.Throttle(
    TimeSpan.FromSeconds(1),
    sensorId,
    new ProcessSensorArgs { SensorId = sensorId, Value = reading });

RunOnceThenDebounce<T>

Executes work immediately on first call, then applies debounce semantics.

ValueTask RunOnceThenDebounce<T>(
    TimeSpan interval,
    Guid key,
    T workArgument,
    TContext? context = default,
    bool awaited = true,
    CancellationToken cancellationToken = default)

Example:

// First call executes immediately, subsequent calls debounce
await scheduler.RunOnceThenDebounce(
    TimeSpan.FromMilliseconds(500),
    entityId,
    new SaveEntityArgs { EntityId = entityId });

RunOnceThenThrottle<T>

Executes work immediately on first call, then applies throttle semantics.

ValueTask RunOnceThenThrottle<T>(
    TimeSpan interval,
    Guid key,
    T workArgument,
    TContext? context = default,
    bool awaited = true,
    CancellationToken cancellationToken = default)

Cancel<T>

Cancels a pending scheduled work item by key.

(Func<IEnumerable<object>?, Task>? action, List<object>? accumulatedParameters) Cancel<T>(
    Guid key,
    bool preserveDispatcher = false)

Parameters:

  • key - The unique key identifying the scheduled work.
  • preserveDispatcher - If true, preserves the dispatcher entry for future scheduling.

Returns: A tuple containing the cancelled action and any accumulated parameters. Both are null if no pending work was found.

Example:

var (action, params) = scheduler.Cancel<SavePreferencesArgs>(userId);
if (action != null)
{
    Console.WriteLine("Cancelled pending save operation");
}

Cancel (with Type)

Cancels a pending scheduled work item by key and argument type.

(Func<IEnumerable<object>?, Task>? action, List<object>? accumulatedParameters) Cancel(
    Guid key,
    Type argumentType,
    bool preserveDispatcher = false)

FlushAsync

Immediately flushes all pending scheduled work to the queue.

Task FlushAsync(CancellationToken cancellationToken = default)

Remarks:

  • Enqueues all pending debounced and throttled work immediately.
  • Waits for all enqueued work to complete.
  • May execute multiple flushing rounds if handlers enqueue new rate-controlled work.
  • Automatically called during graceful shutdown.

Example:

// Force all pending work to execute now
await scheduler.FlushAsync();

Clear

Clears all pending scheduled work without executing it.

void Clear()

Remarks:

  • All pending work is discarded.
  • Use when you want to cancel all scheduled work without execution.

IBackgroundWorkScopeFactory<TContext>

Singleton service for capturing context and creating worker scopes.

Lifetime: Singleton

CaptureScopeContext

Captures context from a scoped provider.

TContext CaptureScopeContext(IServiceProvider scopedProvider)

Parameters:

  • scopedProvider - The scoped service provider (e.g., from HTTP request)

Returns: The captured context data


CreateScope

Creates a new scope without context.

AsyncServiceScope CreateScope()

CreateScope(TContext)

Creates a new scope with rehydrated context.

AsyncServiceScope CreateScope(TContext context)

Parameters:

  • context - The context to rehydrate

Returns: A new scope with context available via IBackgroundWorkContextAccessor<TContext>


RehydrateBackgroundScope

Populates context in a worker scope.

void RehydrateBackgroundScope(IServiceProvider scopedProvider, TContext context)

BackgroundWorkScopeFactoryBase<TContext>

Abstract base class for implementing scope factories.

Constructor

protected BackgroundWorkScopeFactoryBase(
    ILogger<BackgroundWorkScopeFactoryBase<TContext>> logger,
    IServiceScopeFactory serviceScopeFactory)

Abstract Methods

Override these in your implementation:

public abstract TContext CaptureScopeContext(IServiceProvider scopedProvider);

public abstract void RehydrateBackgroundScope(IServiceProvider scopedProvider, TContext context);

Example Implementation:

public class MyAppScopeFactory : BackgroundWorkScopeFactoryBase<MyAppContext>
{
    public MyAppScopeFactory(
        ILogger<BackgroundWorkScopeFactoryBase<MyAppContext>> logger,
        IServiceScopeFactory serviceScopeFactory)
        : base(logger, serviceScopeFactory) { }

    public override MyAppContext CaptureScopeContext(IServiceProvider scopedProvider)
    {
        var http = scopedProvider.GetService<IHttpContextAccessor>()?.HttpContext;
        return new MyAppContext
        {
            UserId = http?.User.FindFirst(ClaimTypes.NameIdentifier)?.Value
        };
    }

    public override void RehydrateBackgroundScope(IServiceProvider scopedProvider, MyAppContext context)
    {
        scopedProvider.GetRequiredService<IBackgroundWorkContextAccessor<MyAppContext>>().Context = context;
    }
}

IBackgroundWorkContextAccessor<TContext>

Scoped accessor for the current context.

Lifetime: Scoped

Properties

Property Type Description
Context TContext? The current context, or null if not set

Example:

public class MyHandler : IWorkHandler<MyArgs>
{
    private readonly IBackgroundWorkContextAccessor<MyAppContext> _accessor;

    public MyHandler(IBackgroundWorkContextAccessor<MyAppContext> accessor)
    {
        _accessor = accessor;
    }

    public Task DoWork(MyArgs args, CancellationToken ct)
    {
        var userId = _accessor.Context?.UserId;
        // ...
    }
}

IWorkHandler<TWorkArguments>

Interface for work handlers.

Lifetime: Scoped

Properties

Property Type Description
Order int Execution order (lower runs first)

Methods

DoWork

Processes the work arguments.

Task DoWork(TWorkArguments workArguments, CancellationToken cancellationToken = default)

IHasOrderProperty

Marker interface for ordered execution.

Properties

Property Type Description
Order int Execution order (lower runs first)

BackgroundActionWorkArguments

Work arguments for delegate-based work.

Constructor

public BackgroundActionWorkArguments(
    Func<IServiceProvider, CancellationToken, Task> Action,
    string Name,
    string? SpanId = null)

Parameters:

  • Action - The delegate to execute (receives worker scope provider)
  • Name - Display name for logging
  • SpanId - Optional span ID for tracing

Properties

Property Type Description
Action Func<IServiceProvider, CancellationToken, Task> The work delegate
Name string Display name
SpanId string? Optional tracing span ID

Example:

await _submitter.Enqueue(new BackgroundActionWorkArguments(
    async (sp, ct) =>
    {
        var service = sp.GetRequiredService<IMyService>();
        await service.DoWorkAsync(ct);
    },
    Name: "ProcessData",
    SpanId: Activity.Current?.SpanId.ToString()));

XpressWorkOptions

Configuration options for XpressWork.

Properties

Property Type Default Description
MaxQueueLength int 0 Max queue size (0 = unbounded)
DrainOnShutdown bool false Process remaining items on shutdown
HandlerErrorMode HandlerErrorMode StopOnFirst Error handling policy
EnableDiagnostics bool false Enable verbose logging
ShutdownTimeout TimeSpan 30s Max wait time for graceful shutdown

HandlerErrorMode Enum

Value Description
StopOnFirst Stop handler chain on first exception
ContinueOnError Execute all handlers, aggregate exceptions

Example:

services.AddXpressWork<MyContext, MyScopeFactory>(options =>
{
    options.MaxQueueLength = 1000;
    options.DrainOnShutdown = true;
    options.HandlerErrorMode = HandlerErrorMode.ContinueOnError;
    options.EnableDiagnostics = true;
    options.ShutdownTimeout = TimeSpan.FromMinutes(1);
});

See Also