mirror of
https://github.com/okieselbach/AutopilotMonitor.git
synced 2026-10-24 12:42:38 +00:00
298a182fbb
BackupJobStatus, RestoreRowPreviewResponse and RestoreRowCommitResponse were the last response payloads the
portal typed by hand: the C# classes existed in Shared but were not marked [WireContract], so the manifest
never carried them. The attribute pulls them and their enums (BackupJobKind/State, BackupOutcome,
RestoreRowDiffKind, RestoreRowCommitOutcome) into shared-manifests.json and both generated wire-type files;
the three backup pages import those and lib/api.ts drops eleven hand-written mirrors. Attribute only: no
runtime behaviour changes, no backend deploy needed.
Still hand-written in lib/api.ts, with reason: BackupManifest/BackupTableEntry (a blob passed through by
GET global/backups/{id}), BackupTriggerResponse (the 202 body of global/backups/trigger is an anonymous
object outside the typed regime) and the RestoreRow request body.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
88 lines
3.6 KiB
C#
88 lines
3.6 KiB
C#
using System;
|
|
|
|
namespace AutopilotMonitor.Shared.Models.Backup
|
|
{
|
|
/// <summary>
|
|
/// Per-job state machine for asynchronous backup + restore work. Persisted as
|
|
/// <see cref="BackupJobStatusEntity"/> in <c>BackupJobs</c> (PartitionKey="BackupJobs",
|
|
/// RowKey={jobId}). The domain DTO carries strongly-typed enums; the Repository
|
|
/// layer maps from/to the string-typed Azure Table columns (Azure Tables has no
|
|
/// EDM enum). Unknown strings on read MUST throw — silent fallback is a regression
|
|
/// risk after enum refactorings.
|
|
/// </summary>
|
|
[WireContract]
|
|
public sealed class BackupJobStatus
|
|
{
|
|
public string JobId { get; set; } = string.Empty;
|
|
public BackupJobKind Kind { get; set; }
|
|
public BackupJobState State { get; set; }
|
|
|
|
/// <summary>UPN for manual triggers; <c>"Timer"</c> never reaches this DTO — Timer skips the queue.</summary>
|
|
public string RequestedBy { get; set; } = string.Empty;
|
|
|
|
public DateTime QueuedAtUtc { get; set; }
|
|
public DateTime? StartedAtUtc { get; set; }
|
|
public DateTime? CompletedAtUtc { get; set; }
|
|
|
|
/// <summary>Updated by the renewal-loop and per-phase progress writes; drives the watchdog.</summary>
|
|
public DateTime LastHeartbeatUtc { get; set; }
|
|
|
|
/// <summary>
|
|
/// For Kind=Backup: the worker-generated id of the manifest this job produced
|
|
/// (null until the worker has acquired the lease and stamped it). UI uses this
|
|
/// to deep-link from a completed job to its manifest detail page.
|
|
/// </summary>
|
|
public string? BackupId { get; set; }
|
|
|
|
/// <summary>For Kind=RestoreTable: the manifest id the operator is restoring FROM.</summary>
|
|
public string? SourceBackupId { get; set; }
|
|
|
|
/// <summary>For Kind=RestoreTable: the table being restored.</summary>
|
|
public string? TableName { get; set; }
|
|
|
|
/// <summary>For Kind=RestoreTable: <c>upsert-only</c> | <c>replace-all</c>.</summary>
|
|
public string? Strategy { get; set; }
|
|
|
|
/// <summary>Free-form JSON for in-flight worker progress (phase, counters). Informational only — recovery does not depend on it.</summary>
|
|
public string? Progress { get; set; }
|
|
|
|
public string? Error { get; set; }
|
|
|
|
/// <summary>
|
|
/// For Kind=Backup with State=Completed: <c>Success</c> | <c>Partial</c>.
|
|
/// Null for any other (Kind, State) combination.
|
|
/// </summary>
|
|
public BackupOutcome? BackupOutcome { get; set; }
|
|
}
|
|
|
|
public enum BackupJobKind
|
|
{
|
|
Backup,
|
|
RestoreTable,
|
|
}
|
|
|
|
/// <summary>
|
|
/// Six-state job machine. Terminal states (Completed / Failed / Skipped / BlockedTerminal)
|
|
/// short-circuit the worker's duplicate-detection on reappearance: message is dropped, no
|
|
/// re-run. Failed vs BlockedTerminal vs Skipped is intentional so operator-action follow-up
|
|
/// can be distinguished (logs / re-trigger / nothing-to-do).
|
|
/// </summary>
|
|
public enum BackupJobState
|
|
{
|
|
Queued,
|
|
Running,
|
|
|
|
/// <summary>Manifest written (Backup) or restore phase succeeded (RestoreTable).</summary>
|
|
Completed,
|
|
|
|
/// <summary>Unexpected abort: storage 5xx / network / bug. After 5 retries → poison-move sets this.</summary>
|
|
Failed,
|
|
|
|
/// <summary>Maintenance-lease held by another job — no work performed. Operator retriggers when the parallel job is done.</summary>
|
|
Skipped,
|
|
|
|
/// <summary>Deterministic domain error: manifest missing, SHA mismatch, auth-table block, confirmation-token typo. Not retryable.</summary>
|
|
BlockedTerminal,
|
|
}
|
|
}
|