diff --git a/src/content/docs/Immediate.Jobs/api-reference.md b/src/content/docs/Immediate.Jobs/api-reference.md index 445adc8..d23734c 100644 --- a/src/content/docs/Immediate.Jobs/api-reference.md +++ b/src/content/docs/Immediate.Jobs/api-reference.md @@ -26,6 +26,11 @@ sealed class JobAttribute : Attribute enum OverlapPolicy { Skip, Queue, Concurrent } enum BackoffStrategy { Fixed, Exponential, ExponentialJitter } +enum JobState +{ + AwaitingContinuation, AwaitingParameters, Scheduled, Pending, Active, + Succeeded, Failed, Cancelled, Skipped +} sealed class QueueDefinitionAttribute : Attribute { @@ -128,8 +133,9 @@ ValueTask AddToBatchAsync( `ContinuationTrigger.Success` waits for every parent to succeed. `Failure` waits for every parent to become terminal and then runs when at least one failed. `Complete` waits for every parent to become terminal regardless of outcome. A `BatchHandle` is a single parent whose state becomes -`Failed` when any item in the completed batch failed; cancellation alone does not satisfy -`Failure`. +`Failed` when any item in the completed batch failed; cancellation or skipped branches alone do +not satisfy `Failure`. When a `Success` or `Failure` condition cannot be satisfied, the child and +any ineligible descendants become terminal `Skipped` records. | `ContinuationOptions` | Batch membership | Effect on the current job's existing continuations | | ------------------------------- | ---------------- | ---------------------------------------------------------------- | @@ -220,11 +226,19 @@ interface IJobBatchMonitor string batchId, BatchMemberQuery query, CancellationToken token = default); ValueTask GetGraphAsync(string batchId, CancellationToken token = default); } + +sealed record BatchStatus( + string Id, BatchState State, + int Total, int Succeeded, int Failed, int Cancelled, int Skipped, int Remaining, + DateTimeOffset CreatedAt, DateTimeOffset? StartedAt, DateTimeOffset? CompletedAt, + double FractionSettled +); ``` `BatchMemberQuery` and `JobBatchQuery` contain optional state, `Skip`, and `Take = 100`. `JobStatus`, `BatchStatus`, `BatchMemberStatus`, `BatchGraph`, `BatchGraphNode` and -`BatchGraphEdge` are immutable monitoring records. +`BatchGraphEdge` are immutable monitoring records. `FractionSettled` includes every terminal +outcome, including `Skipped`. ## Dashboard @@ -281,8 +295,8 @@ each `ScheduledJobCapture` contains `Id`, `Payload`, `RunAt`, and `GroupId`. it exposes `Services`, `Storage`, `TimeProvider`, and `Batches`. Operations are `DrainAsync`, both `AdvanceTimeAndDrainAsync` overloads, `QueryJobsAsync`, both `GetJobAsync` overloads, both `AssertEnqueuedAsync` overloads, `AssertBatchCommittedAtomicallyAsync`, -`AssertContinuationReleasedAfterAsync`, `AssertCascadeCancelledAsync`, and -`RunThroughPipelineAsync`. +`AssertContinuationReleasedAfterAsync`, `AssertCascadeSkippedAsync`, its compatibility alias +`AssertCascadeCancelledAsync`, and `RunThroughPipelineAsync`. ## Custom storage contracts @@ -290,9 +304,11 @@ it exposes `Services`, `Storage`, `TimeProvider`, and `Batches`. Operations are | ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | | `IJobStorage` | Initialize; enqueue; lease/acquire/renew; persist execution telemetry; complete/fail; query/status; retry/delete/purge; heartbeat and health. | | `IRecurringJobStorage` | Upsert/remove/pause/resume schedules; identify due rows; uniquely materialize each occurrence; reconcile obsolete code-defined schedules. | -| `IJobGraphStorage` | Atomically enqueue batches/edges; settle and release/cascade dependencies; add mid-run members; monitor/cancel/delete/purge graphs. | +| `IJobGraphStorage` | Atomically enqueue batches/edges; settle and release/skip dependencies; add mid-run members; monitor/cancel/delete/purge graphs. | | `IJobStorageReplica` | Restore durable records and mirror explicit acquisitions for the single-server wrapper. | `StorageCapabilities` flags are `Queue`, `Recurring` and `Graph`; call `storage.GetCapabilities()` to detect the optional interfaces. Low-level `JobRecord`, acquisition, definition and graph persistence records are provider contracts, not application scheduling APIs. +`IJobStorage.RetryAsync` accepts `Failed` and `Scheduled`: a scheduled invocation is moved to +`Pending` immediately while retaining its attempt count and latest failure details. diff --git a/src/content/docs/Immediate.Jobs/batches-and-continuations.md b/src/content/docs/Immediate.Jobs/batches-and-continuations.md index 8859aed..9622ea6 100644 --- a/src/content/docs/Immediate.Jobs/batches-and-continuations.md +++ b/src/content/docs/Immediate.Jobs/batches-and-continuations.md @@ -102,15 +102,18 @@ handles from unrelated open batches are rejected. `ScheduleAfterAsync(BatchHandl the entire prior batch. `batches.Begin(previousBatch, trigger)` creates a follow-up batch whose root members all depend on it. -| `ContinuationTrigger` | Child is released when… | -| --------------------- | ---------------------------------------------------------------------------- | -| `Success` | all parents succeed; otherwise the child is cascade-cancelled. | -| `Failure` | all parents are terminal and at least one failed; otherwise it is cancelled. | -| `Complete` | all parents reach any terminal state. | +| `ContinuationTrigger` | Condition and unmatched outcome | +| --------------------- | ------------------------------------------------------------------------------------ | +| `Success` | Released when every parent succeeds; skipped when a parent settles unsuccessfully. | +| `Failure` | Released after every parent settles if at least one failed; otherwise skipped. | +| `Complete` | Released after every parent reaches any terminal state; it has no unmatched outcome. | For a continuation attached to a `BatchHandle`, the batch is one parent. It becomes `Failed` after all of its items finish when **any item failed**, so a `Failure` continuation is released in that -case. Cancelled items alone make the batch `Cancelled` and do not satisfy `Failure`. +case. Explicitly cancelled items alone make the batch `Cancelled`, while skipped branches do not +fail the batch. Neither outcome satisfies `Failure`. Conditional branches that are not selected +become terminal `Skipped` records, and skipping propagates through descendants whose own triggers +cannot be satisfied. ## Expanding a running workflow @@ -159,5 +162,7 @@ except for detached scheduling, the current job must belong to a batch. `IJOB001 -Monitor a graph through `IJobBatchMonitor.GetStatusAsync`, `QueryMembersAsync` and `GetGraphAsync`, -or use the dashboard's workflow view and batch cancel/delete operations. +Monitor a graph through `IJobBatchMonitor.GetStatusAsync`, `QueryMembersAsync` and `GetGraphAsync`. +`BatchStatus` counts succeeded, failed, cancelled and skipped members separately; a batch can +succeed when every executed member succeeded even if conditional branches were skipped. The +dashboard exposes the same progress and workflow states alongside batch cancel/delete operations. diff --git a/src/content/docs/Immediate.Jobs/configuring-storage-providers.md b/src/content/docs/Immediate.Jobs/configuring-storage-providers.md index 1f7c03d..9244b36 100644 --- a/src/content/docs/Immediate.Jobs/configuring-storage-providers.md +++ b/src/content/docs/Immediate.Jobs/configuring-storage-providers.md @@ -122,6 +122,7 @@ support graph workflows or fair queues. Storage initialization is idempotent provider startup, not a substitute for controlled production schema evolution. Keep migrations/bootstrap and provider packages at the same preview revision as -the core package. +the core package. The batch table now includes a non-null `SkippedCount` column; existing SQL +schemas created before that field need an application-owned migration that defaults it to zero. diff --git a/src/content/docs/Immediate.Jobs/creating-jobs.md b/src/content/docs/Immediate.Jobs/creating-jobs.md index 4ff5bf9..d0eeedc 100644 --- a/src/content/docs/Immediate.Jobs/creating-jobs.md +++ b/src/content/docs/Immediate.Jobs/creating-jobs.md @@ -35,9 +35,12 @@ rejected. Interfaces, abstract types, open generics, pointers, delegates, ref-li unsupported `System` types are also rejected. Prefer records or classes with a public constructor whose parameters match their public members. -Constructor availability is not currently an analyzer error, so a type that receives metadata but -cannot be constructed by `System.Text.Json` can still fail when a worker deserializes it. Generated -metadata is used for both serialization and Native AOT; no reflection fallback is needed. +Public `init` properties that are not constructor parameters are also supported, including +optional and `required` properties; generated metadata initializes them through an object +initializer. Constructor availability is not currently an analyzer error, so a type that receives +metadata but cannot be constructed by `System.Text.Json` can still fail when a worker deserializes +it. Generated metadata is used for both serialization and Native AOT; no reflection fallback is +needed. A payloadless job receives `EmptyJobRequest`: diff --git a/src/content/docs/Immediate.Jobs/dashboard-and-monitoring.md b/src/content/docs/Immediate.Jobs/dashboard-and-monitoring.md index 431902b..fc95799 100644 --- a/src/content/docs/Immediate.Jobs/dashboard-and-monitoring.md +++ b/src/content/docs/Immediate.Jobs/dashboard-and-monitoring.md @@ -44,8 +44,9 @@ Without `RequireAuthorization`, every dashboard endpoint is development-only and other environments. Treat the dashboard as an administrative surface: it exposes payloads, errors, identifiers and mutations. A named policy applies to UI assets and APIs together. -The UI shows queue/state totals, recent history, jobs and details, recurring schedules, scheduler -servers, batches and workflow graphs. Graph views appear only for graph-capable storage. +The UI shows queue/state totals, including skipped work, recent history, jobs and details, +recurring schedules, scheduler servers, batches and workflow graphs. Graph views appear only for +graph-capable storage. ## Dashboard UI @@ -53,6 +54,8 @@ servers, batches and workflow graphs. Graph views appear only for graph-capable The Jobs view lists recent executions and their current state. Select a job to inspect its invocation, execution metadata, payload, errors and any application-defined telemetry links. +Failed jobs offer **Retry**; scheduled first attempts and delayed retries offer **Run now**, which +moves the existing invocation to `Pending` without changing its attempt or failure history.
` when a test already has a record/payload and needs to execute its generated invoker through the real DI/behavior pipeline.