using System; using System.Threading; using System.Threading.Tasks; namespace Aging.ResourceContracts { /// 与现有 OwnerType 数值对齐:Production=0, Maintenance=1。 public enum OwnerTypeV3 { Production = 0, Maintenance = 1 } /// MVP 相位:Free 可用 / Active 持有 / RecoveryRequired 过期待回收(INV-03)。 public enum LeasePhase { Free = 0, Active = 1, RecoveryRequired = 2 } /// 每资源一张租约凭证;栅栏=(AuthorityId, Epoch, ResourceKey, LeaseId, Generation)。 public sealed class LeaseGrant { public string AuthorityId { get; } public string ResourceKey { get; } public string LeaseId { get; } public string OwnerId { get; } public OwnerTypeV3 OwnerType { get; } public long Epoch { get; } public long Generation { get; } public long ExpiresUtcMs { get; } public LeaseGrant(string authorityId, string resourceKey, string leaseId, string ownerId, OwnerTypeV3 ownerType, long epoch, long generation, long expiresUtcMs) { AuthorityId = authorityId; ResourceKey = resourceKey; LeaseId = leaseId; OwnerId = ownerId; OwnerType = ownerType; Epoch = epoch; Generation = generation; ExpiresUtcMs = expiresUtcMs; } } public sealed class AcquireRequest { public string OwnerId { get; set; } = ""; public OwnerTypeV3 OwnerType { get; set; } /// boot_id + pid,同机进程区分。 public string ProcessInstanceId { get; set; } = ""; public string MachineName { get; set; } = Environment.MachineName; public int HostProcessId { get; set; } = System.Diagnostics.Process.GetCurrentProcess().Id; /// 申请理由(维护会话填操作员与原因,进 lease_history)。 public string Reason { get; set; } = ""; /// Ordinals 升序、去重后申请(组申请 = 单事务全有全无)。 public string[] ResourceKeys { get; set; } = new string[0]; public int WaitTimeoutMs { get; set; } = 1000; public int TtlSeconds { get; set; } = 30; } public enum AcquireResultCode { Acquired, Reused, ConflictHeld, RecoveryBlocked, Timeout } public sealed class ConflictInfo { public string OwnerId { get; set; } = ""; public OwnerTypeV3 OwnerType { get; set; } public string MachineName { get; set; } = ""; public int HostProcessId { get; set; } public string Reason { get; set; } = ""; public long ExpiresUtcMs { get; set; } } public sealed class AcquireOutcome { public AcquireResultCode Code { get; set; } public LeaseGrant[] Grants { get; set; } = new LeaseGrant[0]; public ConflictInfo? Holder { get; set; } /// RecoveryBlocked 时指向 recovery_checkpoint 的键。 public string? RecoveryCheckpointKey { get; set; } } /// 租约协调器:仲裁域唯一入口。实现方:DbLeaseStore。 public interface ILeaseCoordinator { /// 权威域当前 epoch(重启后递增,旧 Grant 自动失效)。 long CurrentEpoch { get; } AcquireOutcome Acquire(AcquireRequest request); /// 同 LeaseId+Generation 续期;返回 false=已被回收/超越(本地须熔断)。 bool Renew(LeaseGrant grant, int extendSeconds); bool Release(LeaseGrant grant, string note); ConflictInfo? ProbeConflict(string resourceKey); LeasePhase PhaseOf(string resourceKey); int SweepExpired(); /// RecoveryRequired → Free:宿主完成读回探测后登记证据并放行。 bool ApproveRecovery(string resourceKey, string readbackJson, string approvedBy); /// 测试用:强制提升 epoch,使所有活跃 Grant 失效。 void BumpEpochForTest(string reason); } }