TickerQ Documentation

repository·main·Indexed 25 days ago

https://github.com/arcenox-co/tickerq

A high-performance, source-generated job scheduler for .NET with AOT compatibility, supporting time-based and cron scheduling. Features include persistence via EF Core or Redis, a real-time SignalR dashboard, and a Node.js SDK (@tickerq/sdk v1.0.0) for connecting applications to TickerQ Hub for distributed job scheduling.

Tokens
18K
Snippets
57
Records
115
Agent score
85%

What's inside TickerQ

  1. Migrate Authentication to Production

    main

    The auth.config.ts file is for development/testing only. For production environments, you must replace the hardcoded logic with a secure backend implementation.

    Required Production Steps:

    1. Remove hardcoded credentials: Implement proper backend validation.
    2. Use secure authentication: Implement JWT, OAuth, or similar protocols.
    3. Add rate limiting: Prevent brute force attacks.
    4. Use HTTPS: Encrypt all authentication traffic.
    5. Implement session management: Handle logout and token expiration.

    Security Best Practices:

    • Never commit real credentials to version control.
    • Use environment variables for sensitive configuration.
    • Implement proper password hashing.
    • Add logging for authentication attempts.
    • Consider implementing 2FA.
    // Example of a production-ready validateCredentials implementation
    export async function validateCredentials(username: string, password: string) {
      try {
        const response = await fetch('/api/auth/login', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ username, password })
        })
        
        if (response.ok) {
          const data = await response.json()
          return { isValid: true, token: data.token }
        } else {
          return { isValid: false, error: 'Invalid credentials' }
        }
      } catch (error) {
        return { isValid: false, error: 'Authentication service unavailable' }
      }
    }
  2. Configure Basic OpenTelemetry and TickerQ Instrumentation

    main

    To enable tracing, you must perform two steps:

    1. Configure OpenTelemetry to include the TickerQ ActivitySource.
    2. Call .AddOpenTelemetryInstrumentation() on your TickerQ service registration.

    Requires .NET 8.0+ and OpenTelemetry 1.15.3+.

    using TickerQ.Instrumentation.OpenTelemetry;
    using OpenTelemetry.Trace;
    
    var builder = WebApplication.CreateBuilder(args);
    
    // Configure OpenTelemetry with TickerQ ActivitySource
    builder.Services.AddOpenTelemetry()
        .WithTracing(tracing =>
        {
            tracing.AddSource("TickerQ") // Add TickerQ ActivitySource
                   .AddConsoleExporter()
                   .AddJaegerExporter();
        });
    
    // Add TickerQ with OpenTelemetry instrumentation
    builder.Services.AddTickerQ<MyTimeTicker, MyCronTicker>(options => { })
        .AddOperationalStore(ef => { })
        .AddOpenTelemetryInstrumentation(); // 👈 Enable tracing
    
    var app = builder.Build();
    app.Run();
  3. Schedule a job using ITimeTickerManager

    main

    To schedule a one-off execution, inject ITimeTickerManager<TEntity> (where TEntity is your chosen persistence entity, such as TimeTickerEntity) and call AddAsync with a new entity instance specifying the Function name and the ExecutionTime.

    public class MyService(ITimeTickerManager<TimeTickerEntity> manager)
    {
        public async Task Schedule()
        {
            await manager.AddAsync(new TimeTickerEntity
            {
                Function = "HelloWorld",
                ExecutionTime = DateTime.UtcNow.AddSeconds(10)
            });
        }
    }
  4. Mount TickerQ HTTP endpoints

    main

    The SDK requires two endpoints to be exposed for the Hub to communicate with your node:

    • POST /execute: Receives function execution requests.
    • POST /resync: Re-syncs function registry with the Hub.

    Express

    Use sdk.expressHandlers() to mount to an Express app. You can optionally provide a path prefix.

    Raw Node.js HTTP

    Use sdk.createHandler() to get a standard Node.js request handler.

    // Express
    sdk.expressHandlers().mount(app);
    // With prefix
    sdk.expressHandlers('/tickerq').mount(app);
    
    // Raw Node.js
    import { createServer } from 'node:http';
    const handler = sdk.createHandler();
    const server = createServer(handler);
    server.listen(3000);
  5. Configure TickerQ to use MongoDB

    main

    Register the MongoDB operational store during service configuration. You can either provide a connection string directly or reuse an existing IMongoClient from your Dependency Injection container.

    // Option 1: Provide connection string and database name directly
    builder.Services.AddTickerQ(options =>
    {
        options.AddOperationalStore(mongoOptions =>
        {
            mongoOptions.UseTickerQMongoClient(
                connectionString: "mongodb://localhost:27017",
                databaseName: "tickerq");
        });
    });
    
    // Option 2: Reuse an existing IMongoClient registered in DI
    services.AddSingleton<IMongoClient>(_ => new MongoClient("mongodb://localhost:27017"));
    
    builder.Services.AddTickerQ(options =>
    {
        options.AddOperationalStore(mongoOptions =>
        {
            mongoOptions.UseExistingMongoClient(databaseName: "tickerq");
        });
    });
  6. Register functions with @tickerq/sdk

    main

    Functions can be registered in three ways:

    1. With typed request: Provides type inference and example JSON for the Hub.
    2. Without request: For tasks that don't require input data.
    3. With primitive request: For simple inputs like a single string or number.

    Use .withRequest() to define the payload shape and .handle() to define the execution logic.

    // Typed request
    sdk.function('ProcessOrder', {
        priority: TickerTaskPriority.High,
        maxConcurrency: 3,
        requestType: 'OrderRequest',
    })
        .withRequest({ orderId: 0, customerId: '', items: [''], total: 0 })
        .handle(async (ctx, signal) => {
            ctx.request.orderId;    // number
            ctx.request.customerId; // string
        });
    
    // Without request
    sdk.function('DatabaseCleanup', {
        cronExpression: '0 0 3 * * *',
        priority: TickerTaskPriority.LongRunning,
    })
        .handle(async (ctx, signal) => {
            console.log(`Running cleanup for ${ctx.functionName}`);
        });
    
    // Primitive request
    sdk.function('ResizeImage')
        .withRequest('default-url')
        .handle(async (ctx, signal) => {
            console.log(ctx.request); // string
        });
  7. Register TickerQ services in .NET

    main

    To integrate TickerQ into your application, register the services using AddTickerQ() in your service collection and enable the middleware using UseTickerQ() in your application pipeline.

    var builder = WebApplication.CreateBuilder(args);
    
    builder.Services.AddTickerQ();
    
    var app = builder.Build();
    app.UseTickerQ();
    app.Run();