fix(nodes): locate agents behind a proxy and retry missing countries [CI]
ci/woodpecker/push/web-build Pipeline was successful
ci/woodpecker/push/verify Pipeline was successful
ci/woodpecker/push/dev-image Pipeline was successful

This commit is contained in:
justme committed 2026-10-18 00:06:39 +08:00
1 parent 1145a53004
commit 0d532caf08
13 files changed
+93 -15

No files matched your search

@@ -115,10 +115,15 @@ public sealed class MoShiroNodeEventSink : INodeEventSink
await _events.AddAsync(id, "agent_offline", nodeEvent.AtMs, null, ct);
break;
case NodeEventKind.Hello when nodeEvent.Hello is { } hello:
await ApplyHelloAsync(id, hello, ct);
await ApplyHelloAsync(id, hello, nodeEvent.RemoteIp, ct);
break;
case NodeEventKind.Heartbeat when nodeEvent.Extra is { } extra:
await _nodes.SetVersionAsync(id.Value, NodeKinds.Agent, nodeEvent.Node.NodeVersion, ct);
if (_nodes.ShouldRetryGeo(id.Value) && await _agents.GetAsync(id, ct) is { } unlocated)
{
_nodes.ObserveAgentInBackground(id.Value, GeoHostOf(unlocated, nodeEvent.RemoteIp), null);
}
try
{
AgentRuntimeState state = _runtime.Get(id);
@@ -145,6 +150,12 @@ public sealed class MoShiroNodeEventSink : INodeEventSink
}
}
/// <summary>查国家和运营商用哪个地址:对外地址优先,其次 IPv6 地址,都没有(NAT 后面、或者没有上报公网地址)才用这条连接的来源地址。</summary>
private static string? GeoHostOf(AgentRecord? agent, string? remoteIp) =>
!string.IsNullOrEmpty(agent?.PublicHost) ? agent.PublicHost
: !string.IsNullOrEmpty(agent?.Ipv6Host) ? agent.Ipv6Host
: remoteIp;
/// <summary>Probe 自己连上来了:hello 里带着它的系统、架构和构建信息;上线下线只推给 SSE,不记事件。</summary>
private async ValueTask OnProbeEventAsync(NodeId id, NodeEvent nodeEvent, CancellationToken ct)
{
@@ -213,7 +224,7 @@ public sealed class MoShiroNodeEventSink : INodeEventSink
}
}
private async ValueTask ApplyHelloAsync(NodeId id, HelloParams hello, CancellationToken ct)
private async ValueTask ApplyHelloAsync(NodeId id, HelloParams hello, string? remoteIp, CancellationToken ct)
{
var kinds = new List<string>();
foreach (string capability in hello.Capabilities)
@@ -278,7 +289,7 @@ public sealed class MoShiroNodeEventSink : INodeEventSink
// 端口、证书指纹或对外地址变了,Probe 需要新的列表
AgentRecord? after = await _agents.GetAsync(id, ct);
_nodes.ObserveAgentInBackground(id.Value, after?.PublicHost, meta.Platform);
_nodes.ObserveAgentInBackground(id.Value, GeoHostOf(after, remoteIp), meta.Platform);
await _releases.OfferToNodeAsync(id, ct);
await _schedule.SendToNodeAsync(id, ct);
if (before is not null && after is not null