agent: unify listening and dialing with directed mutual measurements

Replace Probe with Agent across node runtime, Fleet contracts, backend state, API and storage. Report incoming sessions and outgoing link health through each Agent uplink, and retain directed link controls and retry.

Update protocol fixtures and end-to-end coverage for the unified model; accept requested cancellation during the Fleet timeout test cleanup.
This commit is contained in:
justme committed 2026-10-21 11:55:36 +08:00
1 parent d5ebf29e57
commit ad5efc62ff
206 files changed
+4202 -4964

No files matched your search

@@ -11,7 +11,7 @@ namespace Fleet.Server;
/// 一个节点的 WebSocket 会话:挑战 → 签名认证 → hello → 状态推送 / 收件箱 / 产品 RPC。
/// 收到的消息按顺序处理,所以产品的处理函数不能等待“向同一个节点发起的请求”,否则会死锁。
/// </summary>
internal sealed partial class NodeConnection : IDisposable
internal sealed partial class NodeConnection : IAsyncDisposable
{
private static readonly TimeSpan s_authTimeout = TimeSpan.FromSeconds(15);
private static readonly TimeSpan s_presenceRefresh = TimeSpan.FromSeconds(60);
@@ -31,6 +31,7 @@ internal sealed partial class NodeConnection : IDisposable
private NodeRecord? _node;
private NodeSessionInfo? _session;
private string? _closeReason;
private bool _disposed;
private bool _helloDone;
private int _violations;
@@ -137,10 +138,19 @@ internal sealed partial class NodeConnection : IDisposable
}
}
public void Dispose()
public async ValueTask DisposeAsync()
{
_cipher?.Dispose();
_lifetime.Dispose();
_sendLock.Dispose();
await _sendLock.WaitAsync();
try
{
_disposed = true;
_cipher?.Dispose();
_lifetime.Dispose();
}
finally
{
// API callers may already be waiting to send; let them observe _disposed.
_sendLock.Release();
}
}
}