Expose mesh bounded retry timing in guild sync health rail.
Track per-guild mesh retry attempt metadata and publish countdown fields in view.guildSyncHealthRail so UI can present bounded-mode retry guidance without parsing logs. Co-authored-by: Cursor <[email protected]>
This commit is contained in:
@@ -10,6 +10,7 @@ Application facade: one `PearcordPlatform` class that wires identity, database,
|
||||
**Phase 410 hardening (v0.8.641):** Added cached pin snapshots in `view()` (`_pinListCacheKey/_pinListCacheGen` + `_invalidatePinListCache`) and broadened reaction snapshot cache reuse beyond light polls to reduce duplicate startup list scans.
|
||||
**Phase 410 hardening (v0.8.643):** `view()` now emits cache-path span metadata for `pin.list`, `reaction.list`, and `discovery.list` (`cacheHit`, `source`), coalesces concurrent discovery listing fetches behind `_discoveryListPending`, and reports aggregate cache counters in `view.listCacheMetrics`.
|
||||
**Phase 410 hardening (v0.8.643):** `view()` now supports explicit detail levels (`minimal`/`light`/`full`/`diagnostic`) through `opts.detail`, keeps legacy `opts.light` compatibility, and surfaces the resolved mode as `viewDetailLevel` in payload diagnostics.
|
||||
**Phase 410 hardening (v0.8.643):** `guildSyncHealthRail` now carries bounded-retry metadata (`retryAttempt`, `retryDelayMs`, `retryMaxAttempts`, `nextRetryAt`, `retryCountdownMs`) so UI can show live “mesh bounded mode” retry countdown/tooltip state during background join retries.
|
||||
|
||||
**Phase 659 (v0.8.638):** DM scheduled messages slice — `sendMessage` parses `/schedule` and `/sendlater` in DM mode; queue APIs `createDmScheduledMessage`, `listDmScheduledMessages`, `cancelDmScheduledMessage`, `sendNowDmScheduledMessage`, plus due runner `runDueDmScheduledMessages()` and local timer flush. See [DM_SCHEDULED_MESSAGES.md](../../docs/DM_SCHEDULED_MESSAGES.md).
|
||||
|
||||
|
||||
@@ -499,6 +499,7 @@ class PearcordPlatform extends EventEmitter {
|
||||
this._lastReplicationCompact = null
|
||||
this._memberPageBurstTimestamps = []
|
||||
this._guildMeshBoundedByGuild = new Map()
|
||||
this._guildMeshPeerRetryMetaByGuild = new Map()
|
||||
this._lastPartitionHeal = null
|
||||
this._lastPartitionHealByGuild = new Map()
|
||||
this._partitionHealInProgressByGuild = new Set()
|
||||
@@ -513,7 +514,10 @@ class PearcordPlatform extends EventEmitter {
|
||||
_setGuildMeshBounded (guildId, bounded) {
|
||||
if (!guildId) return
|
||||
if (bounded) this._guildMeshBoundedByGuild.set(guildId, true)
|
||||
else this._guildMeshBoundedByGuild.delete(guildId)
|
||||
else {
|
||||
this._guildMeshBoundedByGuild.delete(guildId)
|
||||
this._guildMeshPeerRetryMetaByGuild.delete(guildId)
|
||||
}
|
||||
}
|
||||
|
||||
_getPartitionHealCooldownUntil (guildId) {
|
||||
@@ -639,7 +643,15 @@ class PearcordPlatform extends EventEmitter {
|
||||
meshBounded: bounded,
|
||||
partitionHealInProgress: healing,
|
||||
syncProgressPct: Number(h?.syncProgressPct) || 0,
|
||||
peers: Number(h?.peers) || 0
|
||||
peers: Number(h?.peers) || 0,
|
||||
retryAttempt: Number(this._guildMeshPeerRetryMetaByGuild.get(id)?.attempt) || 0,
|
||||
retryDelayMs: Number(this._guildMeshPeerRetryMetaByGuild.get(id)?.delayMs) || 0,
|
||||
retryMaxAttempts: Number(this._guildMeshPeerRetryMetaByGuild.get(id)?.maxAttempts) || 0,
|
||||
nextRetryAt: Number(this._guildMeshPeerRetryMetaByGuild.get(id)?.nextRetryAt) || 0,
|
||||
retryCountdownMs: Math.max(
|
||||
0,
|
||||
(Number(this._guildMeshPeerRetryMetaByGuild.get(id)?.nextRetryAt) || 0) - Date.now()
|
||||
)
|
||||
}
|
||||
}
|
||||
return out
|
||||
@@ -12937,6 +12949,8 @@ class PearcordPlatform extends EventEmitter {
|
||||
clearTimeout(this._guildMeshPeerRetryTimer)
|
||||
this._guildMeshPeerRetryTimer = null
|
||||
}
|
||||
const activeGuildId = this.guild?.guild?.id
|
||||
if (activeGuildId) this._guildMeshPeerRetryMetaByGuild.delete(activeGuildId)
|
||||
this._guildMeshPeerRetryAttempts = 0
|
||||
}
|
||||
|
||||
@@ -12944,6 +12958,12 @@ class PearcordPlatform extends EventEmitter {
|
||||
if (this._guildMeshPeerRetryTimer) return
|
||||
if ((this.guild?.peers?.size ?? 0) > 0) return
|
||||
this._guildMeshPeerRetryAttempts = 0
|
||||
this._guildMeshPeerRetryMetaByGuild.set(guildId, {
|
||||
attempt: 0,
|
||||
delayMs: 3000,
|
||||
nextRetryAt: Date.now() + 3000,
|
||||
maxAttempts: Number(process.env.PEARCORD_GUILD_MESH_PEER_RETRY_MAX) || 8
|
||||
})
|
||||
const attempt = () => {
|
||||
if (!this.guild?.guild || this.guild.guild.id !== guildId) {
|
||||
this._clearGuildMeshPeerRetry()
|
||||
@@ -12957,6 +12977,7 @@ class PearcordPlatform extends EventEmitter {
|
||||
this._guildMeshPeerRetryAttempts = (this._guildMeshPeerRetryAttempts || 0) + 1
|
||||
const maxAttempts = Number(process.env.PEARCORD_GUILD_MESH_PEER_RETRY_MAX) || 8
|
||||
if (this._guildMeshPeerRetryAttempts > maxAttempts) {
|
||||
this._guildMeshPeerRetryMetaByGuild.delete(guildId)
|
||||
this._clearGuildMeshPeerRetry()
|
||||
return
|
||||
}
|
||||
@@ -13010,6 +13031,12 @@ class PearcordPlatform extends EventEmitter {
|
||||
)
|
||||
delayMs = retryDelays[delayIdx] || 3000
|
||||
}
|
||||
this._guildMeshPeerRetryMetaByGuild.set(guildId, {
|
||||
attempt: this._guildMeshPeerRetryAttempts,
|
||||
delayMs,
|
||||
nextRetryAt: Date.now() + delayMs,
|
||||
maxAttempts
|
||||
})
|
||||
this._guildMeshPeerRetryTimer = setTimeout(attempt, delayMs)
|
||||
}
|
||||
this._guildMeshPeerRetryTimer = setTimeout(attempt, 3000)
|
||||
|
||||
Reference in New Issue
Block a user