Appearance
Getting Started
Prerequisites
- .NET 10.0 or later
- PostgreSQL (for Hangfire storage and job metadata)
- A Gryd.IO-based application
Installation
Meta-package (recommended)
bash
dotnet add package GrydJobsThis 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 controllersConfiguration
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
- Learn about Job Types (fire-and-forget, delayed, recurring)
- Configure Retry Policies & Dead Letter Queue
- Set up Multi-Tenancy isolation
- Explore the API Reference