Skip to content

Getting Started

Prerequisites

  • .NET 10.0 or later
  • PostgreSQL (for Hangfire storage and job metadata)
  • A Gryd.IO-based application

Installation

bash
dotnet add package GrydJobs

This includes Core, Application, Infrastructure (Hangfire + EF Core), and API layers.

Individual packages

bash
dotnet add package GrydJobs.Core            # Abstractions only
dotnet add package GrydJobs.Application     # CQRS layer
dotnet add package GrydJobs.Infrastructure  # Hangfire + EF Core
dotnet add package GrydJobs.API             # REST controllers

Configuration

Minimal setup

csharp
// Program.cs
builder.Services.AddGrydJobs(options =>
{
    options.ConnectionString = builder.Configuration
        .GetConnectionString("Jobs")!;
});

var app = builder.Build();
app.UseGrydJobs();

if (app.Environment.IsDevelopment())
{
    await app.ApplyGrydJobsMigrationsAsync();
}

app.MapControllers();
app.Run();

Full configuration

csharp
builder.Services.AddGrydJobs(options =>
{
    // Required: PostgreSQL connection string
    options.ConnectionString = builder.Configuration
        .GetConnectionString("Jobs")!;

    // Queues (default: ["default"])
    options.Queues = ["default", "critical", "low", "notifications"];

    // Worker count per server (default: Environment.ProcessorCount * 2)
    options.WorkerCount = 20;

    // Auto-discover and register IRecurringJob implementations (default: true)
    options.AutoRegisterRecurringJobs = true;

    // Assemblies to scan for IRecurringJob implementations
    options.JobAssemblies = [typeof(MyJob).Assembly];

    // Dead letter queue cleanup (default: 30 days, null to disable)
    options.DeadLetterRetentionDays = 30;

    // Retry policies
    options.RetryPolicies
        .Register<SendEmailJob>(maxRetries: 5, delay: TimeSpan.FromSeconds(30))
        .Register<ImportDataJob>(maxRetries: 10, delay: TimeSpan.FromMinutes(2));

    // Default retry policy (for jobs without a specific policy)
    options.DefaultRetryPolicy = new RetryPolicyOptions
    {
        MaxRetries = 3,
        InitialDelay = TimeSpan.FromSeconds(10),
        BackoffType = BackoffType.Exponential
    };
});

// Health checks (optional)
builder.Services.AddGrydJobsHealthChecks();

var app = builder.Build();

// Middleware pipeline
app.UseGrydJobs();
app.UseGrydJobsDashboard(); // Dashboard at /grydjobs/dashboard

if (app.Environment.IsDevelopment())
{
    await app.ApplyGrydJobsMigrationsAsync();
}

app.MapControllers();
app.MapHealthChecks("/health");
app.Run();

appsettings.json

json
{
  "ConnectionStrings": {
    "Jobs": "Host=localhost;Port=5432;Database=gryd_jobs;Username=postgres;Password=postgres"
  }
}

Creating Your First Job

1. Define the job arguments

csharp
public record SendWelcomeEmailArgs(
    string UserId,
    string Email,
    string UserName);

2. Implement the job

csharp
using GrydJobs.Core.Abstractions;

public class SendWelcomeEmailJob : IJob<SendWelcomeEmailArgs>
{
    private readonly IEmailSender _emailSender;
    private readonly ILogger<SendWelcomeEmailJob> _logger;

    public SendWelcomeEmailJob(
        IEmailSender emailSender,
        ILogger<SendWelcomeEmailJob> logger)
    {
        _emailSender = emailSender;
        _logger = logger;
    }

    public async Task ExecuteAsync(
        SendWelcomeEmailArgs args,
        JobExecutionContext context,
        CancellationToken cancellationToken)
    {
        _logger.LogInformation(
            "Sending welcome email to {Email} (Job: {JobId})",
            args.Email, context.JobId);

        await _emailSender.SendTemplateAsync(
            args.Email,
            "welcome",
            new { Name = args.UserName },
            cancellationToken);
    }
}

3. Enqueue the job

csharp
public class UserService
{
    private readonly IJobScheduler _scheduler;

    public UserService(IJobScheduler scheduler)
    {
        _scheduler = scheduler;
    }

    public async Task RegisterUserAsync(CreateUserRequest request)
    {
        var user = await CreateUser(request);

        // Fire-and-forget: runs immediately in the background
        await _scheduler.EnqueueAsync<SendWelcomeEmailJob, SendWelcomeEmailArgs>(
            new SendWelcomeEmailArgs(user.Id, user.Email, user.Name));
    }
}

Next Steps

Released under the MIT License.