From b544d5cccd76735e034c8055918a50927b437474 Mon Sep 17 00:00:00 2001
From: wenxiangchao <wenxiangchao@ihengxin.com.cn>
Date: 星期二, 10 十一月 2026 08:29:04 +0800
Subject: [PATCH] fix: 维护模式重复进入失败与按钮灰死 + Broker 并发验证用例
---
Aging.ResourceContracts/LeaseTypes.cs | 89 ++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 89 insertions(+), 0 deletions(-)
diff --git a/Aging.ResourceContracts/LeaseTypes.cs b/Aging.ResourceContracts/LeaseTypes.cs
new file mode 100644
index 0000000..39c7315
--- /dev/null
+++ b/Aging.ResourceContracts/LeaseTypes.cs
@@ -0,0 +1,89 @@
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Aging.ResourceContracts
+{
+ /// <summary>涓庣幇鏈� OwnerType 鏁板�煎榻愶細Production=0, Maintenance=1銆�</summary>
+ public enum OwnerTypeV3 { Production = 0, Maintenance = 1 }
+
+ /// <summary>MVP 鐩镐綅锛欶ree 鍙敤 / Active 鎸佹湁 / RecoveryRequired 杩囨湡寰呭洖鏀讹紙INV-03锛夈��</summary>
+ public enum LeasePhase { Free = 0, Active = 1, RecoveryRequired = 2 }
+
+ /// <summary>姣忚祫婧愪竴寮犵绾﹀嚟璇侊紱鏍呮爮=(AuthorityId, Epoch, ResourceKey, LeaseId, Generation)銆�</summary>
+ 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; }
+ /// <summary>boot_id + pid锛屽悓鏈鸿繘绋嬪尯鍒嗐��</summary>
+ public string ProcessInstanceId { get; set; } = "";
+ public string MachineName { get; set; } = Environment.MachineName;
+ public int HostProcessId { get; set; } = System.Diagnostics.Process.GetCurrentProcess().Id;
+ /// <summary>鐢宠鐞嗙敱锛堢淮鎶や細璇濆~鎿嶄綔鍛樹笌鍘熷洜锛岃繘 lease_history锛夈��</summary>
+ public string Reason { get; set; } = "";
+ /// <summary>Ordinals 鍗囧簭銆佸幓閲嶅悗鐢宠锛堢粍鐢宠 = 鍗曚簨鍔″叏鏈夊叏鏃狅級銆�</summary>
+ 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; }
+ /// <summary>RecoveryBlocked 鏃舵寚鍚� recovery_checkpoint 鐨勯敭銆�</summary>
+ public string? RecoveryCheckpointKey { get; set; }
+ }
+
+ /// <summary>绉熺害鍗忚皟鍣細浠茶鍩熷敮涓�鍏ュ彛銆傚疄鐜版柟锛欴bLeaseStore銆�</summary>
+ public interface ILeaseCoordinator
+ {
+ /// <summary>鏉冨▉鍩熷綋鍓� epoch锛堥噸鍚悗閫掑锛屾棫 Grant 鑷姩澶辨晥锛夈��</summary>
+ long CurrentEpoch { get; }
+
+ AcquireOutcome Acquire(AcquireRequest request);
+ /// <summary>鍚� LeaseId+Generation 缁湡锛涜繑鍥� false=宸茶鍥炴敹/瓒呰秺锛堟湰鍦伴』鐔旀柇锛夈��</summary>
+ bool Renew(LeaseGrant grant, int extendSeconds);
+ bool Release(LeaseGrant grant, string note);
+ ConflictInfo? ProbeConflict(string resourceKey);
+ LeasePhase PhaseOf(string resourceKey);
+ int SweepExpired();
+ /// <summary>RecoveryRequired 鈫� Free锛氬涓诲畬鎴愯鍥炴帰娴嬪悗鐧昏璇佹嵁骞舵斁琛屻��</summary>
+ bool ApproveRecovery(string resourceKey, string readbackJson, string approvedBy);
+ /// <summary>娴嬭瘯鐢細寮哄埗鎻愬崌 epoch锛屼娇鎵�鏈夋椿璺� Grant 澶辨晥銆�</summary>
+ void BumpEpochForTest(string reason);
+ }
+}
--
Gitblit v1.9.1