diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 6346714..4546a0d 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1,9 +1,6 @@
name: CI
on:
- push:
- branches:
- - "**"
pull_request:
branches:
- "**"
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 0ee3a5c..2a77d19 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -10,7 +10,7 @@
-
+
@@ -19,4 +19,4 @@
-
\ No newline at end of file
+
diff --git a/README.md b/README.md
index 4fb2f26..8455f2d 100644
--- a/README.md
+++ b/README.md
@@ -69,28 +69,37 @@ dotnet add package Sheddueller.Testing
Register `AddSheddueller(...)` in processes that only submit work or manage schedules. Register `AddShedduellerWorker(...)` in processes that should also execute jobs.
+`WorkerOptions` below is an application options type; the callback can read any service registered with DI.
+
```csharp
-using Npgsql;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Options;
using Sheddueller;
using Sheddueller.Postgres;
-var dataSource = NpgsqlDataSource.Create(
- builder.Configuration.GetConnectionString("Sheddueller")
- ?? throw new InvalidOperationException("Missing Sheddueller connection string."));
-
-builder.Services.AddSingleton(dataSource);
+builder.Services.Configure(
+ builder.Configuration.GetSection("Worker"));
builder.Services.AddTransient();
builder.Services.AddShedduellerWorker(sheddueller => sheddueller
- .UsePostgres(postgres =>
- {
- postgres.DataSource = dataSource;
- postgres.SchemaName = "sheddueller";
- })
- .ConfigureOptions(options =>
+ .UsePostgres(
+ serviceProvider =>
+ {
+ var configuration = serviceProvider.GetRequiredService();
+ return configuration.GetConnectionString("Sheddueller")
+ ?? throw new InvalidOperationException("Connection string 'ConnectionStrings:Sheddueller' is required.");
+ },
+ (serviceProvider, postgres) =>
+ {
+ var configuration = serviceProvider.GetRequiredService();
+ postgres.SchemaName = configuration["Sheddueller:Postgres:SchemaName"] ?? "sheddueller";
+ })
+ .ConfigureOptions((serviceProvider, options) =>
{
+ var worker = serviceProvider.GetRequiredService>().Value;
options.NodeId = Environment.MachineName;
- options.MaxConcurrentExecutionsPerNode = 8;
+ options.MaxConcurrentExecutionsPerNode = worker.MaxConcurrentExecutions;
options.DefaultRetryPolicy = new RetryPolicy(
MaxAttempts: 3,
BackoffKind: RetryBackoffKind.Exponential,
@@ -102,11 +111,13 @@ builder.Services.AddShedduellerWorker(sheddueller => sheddueller
Schema migrations are explicit:
```csharp
-await app.Services.GetRequiredService().ApplyAsync();
+await app.ApplyShedduellerPostgresMigrationsAsync();
```
Run migrations during deployment or before starting workers against a new schema. Normal startup validates the configured provider; it does not silently create the schema.
+Use `UsePostgres(postgres => postgres.DataSource = dataSource)` when an application needs to share or own a prebuilt `NpgsqlDataSource`; in that mode, the application also owns disposal.
+
## Enqueue Jobs
Job methods return `Task` or `ValueTask` and receive the scheduler-owned `CancellationToken`. Use `Job.Context` when a handler needs durable logs, progress events, the job id, or the attempt number.
@@ -164,7 +175,7 @@ builder.Services.AddShedduellerDashboard(options =>
});
app.UseAntiforgery();
-((IApplicationBuilder)app).MapShedduellerDashboard("/sheddueller");
+app.MapShedduellerDashboard("/sheddueller");
```
The dashboard uses the configured Sheddueller provider and can be hosted by a worker process or a client-only web process.
diff --git a/docs/.gitkeep b/docs/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/samples/Sheddueller.SampleHost/Program.cs b/samples/Sheddueller.SampleHost/Program.cs
index 9687f39..f30c2eb 100644
--- a/samples/Sheddueller.SampleHost/Program.cs
+++ b/samples/Sheddueller.SampleHost/Program.cs
@@ -1,5 +1,3 @@
-using Npgsql;
-
using Sheddueller;
using Sheddueller.Inspection.Jobs;
using Sheddueller.Postgres;
@@ -9,21 +7,22 @@
var builder = WebApplication.CreateBuilder(args);
-var connectionString = builder.Configuration.GetConnectionString("Sheddueller")
- ?? throw new InvalidOperationException("Connection string 'ConnectionStrings:Sheddueller' is required.");
-var schemaName = builder.Configuration["Sheddueller:Postgres:SchemaName"] ?? "sheddueller";
-await using var dataSource = NpgsqlDataSource.Create(connectionString);
-
-builder.Services.AddSingleton(dataSource);
builder.Services.AddSingleton();
builder.Services.AddTransient();
builder.Services.AddShedduellerWorker(sheddueller => sheddueller
- .UsePostgres(options =>
- {
- options.DataSource = dataSource;
- options.SchemaName = schemaName;
- })
+ .UsePostgres(
+ serviceProvider =>
+ {
+ var configuration = serviceProvider.GetRequiredService();
+ return configuration.GetConnectionString("Sheddueller")
+ ?? throw new InvalidOperationException("Connection string 'ConnectionStrings:Sheddueller' is required.");
+ },
+ (serviceProvider, options) =>
+ {
+ var configuration = serviceProvider.GetRequiredService();
+ options.SchemaName = configuration["Sheddueller:Postgres:SchemaName"] ?? "sheddueller";
+ })
.ConfigureOptions(options =>
{
options.NodeId = "sample-host";
@@ -37,7 +36,7 @@
var app = builder.Build();
-await app.Services.GetRequiredService().ApplyAsync();
+await app.ApplyShedduellerPostgresMigrationsAsync();
app.UseAntiforgery();
@@ -170,7 +169,7 @@
return RedirectWithMessage($"Queued cancelable delayed job {jobId:D} for {notBeforeUtc:O}.");
});
-((IApplicationBuilder)app).MapShedduellerDashboard("/sheddueller");
+app.MapShedduellerDashboard("/sheddueller");
await app.RunAsync();
diff --git a/samples/Sheddueller.SampleHost/Sheddueller.SampleHost.csproj b/samples/Sheddueller.SampleHost/Sheddueller.SampleHost.csproj
index 20b8cb6..1955927 100644
--- a/samples/Sheddueller.SampleHost/Sheddueller.SampleHost.csproj
+++ b/samples/Sheddueller.SampleHost/Sheddueller.SampleHost.csproj
@@ -10,8 +10,4 @@
-
-
-
-
diff --git a/samples/Sheddueller.SampleHost/appsettings.Development.json b/samples/Sheddueller.SampleHost/appsettings.Development.json
index 34f00ef..c39a972 100644
--- a/samples/Sheddueller.SampleHost/appsettings.Development.json
+++ b/samples/Sheddueller.SampleHost/appsettings.Development.json
@@ -1,4 +1,5 @@
{
+ "DetailedErrors": true,
"Logging": {
"LogLevel": {
"Default": "Debug",
diff --git a/src/Sheddueller.Dashboard/Components/DashboardApp.razor b/src/Sheddueller.Dashboard/Components/DashboardApp.razor
index 17f11a6..1175756 100644
--- a/src/Sheddueller.Dashboard/Components/DashboardApp.razor
+++ b/src/Sheddueller.Dashboard/Components/DashboardApp.razor
@@ -1,4 +1,5 @@
@inject NavigationManager Navigation
+@inject Microsoft.Extensions.Options.IOptions DashboardOptions
@@ -13,7 +14,14 @@
-
+