feat(phase967): guild mesh churn stats extract + peer join/leave keys (v0.8.934)

Non-breaking refactor — Phase 967 of the Guild Mesh Production Hardening Track.

New module:
- guild-mesh-churn-stats-build.js: centralises all churn event payload construction.
  Exports key registries (meshChurnLogBaseFieldKeys, meshChurnPeerJoinLeaveFieldKeys,
  meshChurnStaleEvictFieldKeys, meshChurnPushPeerSlotFieldKeys, meshChurnGossipFlushFieldKeys),
  corresponding listers, and five snapshot builders (buildMeshChurnPeerJoinSnapshot,
  buildMeshChurnPeerLeaveSnapshot, buildMeshChurnStaleEvictSnapshot,
  buildMeshChurnPushPeerSlotSnapshot, buildMeshChurnGossipFlushSnapshot).

Call-site wiring (zero behavior change):
- platform-guild-wire-mixin.js: peer-join and peer-leave logs delegate to builders
- platform-guild-mesh-peer-mixin.js: stale-peer-evict log delegates to builder
- platform-guild-gossip-outbox-mixin.js: gossip-outbox-flush logs delegate to builder
- platform-guild-sync-export-mixin.js: push-peer-slot log delegates to builder

All public APIs, event payloads, and observable behavior are identical to before.

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
Raven Scott
2026-06-05 03:29:22 -04:00
co-authored by Cursor
parent 6107484c45
commit f818f54f06
6 changed files with 121 additions and 12 deletions
+6
View File
@@ -178,6 +178,12 @@ Application facade: one `PearcordPlatform` class that wires identity, database,
**Phase 881 (v0.8.848):** Split `gossip-rpc-pull.js` into peer/session/validators/orchestrators/view-snapshot modules; barrel export unchanged. Bundle: `npm run test:ci-phase881`.
**Phase 967 (v0.8.934):** Guild mesh churn stats extract + peer join/leave keys (non-breaking). Bundle: `npm run test:ci-phase967`.
| Module | Role |
|--------|------|
| `guild-mesh-churn-stats-build.js` | Churn event field key registries and payload builders for peer-join, peer-leave, stale-evict, push-peer-slot, and gossip-flush events |
**Phase 966 (v0.8.933):** Guild mesh offline recovery stats extract + recovery keys (non-breaking). Bundle: `npm run test:ci-phase966`.
| Module | Role |
+93
View File
@@ -0,0 +1,93 @@
'use strict'
const meshChurnLogBaseFieldKeys = ['action', 'guildId', 'meshPeerCount', 'pushPeerSlot', 'pushHalted', 'pendingGossipCount']
const meshChurnPeerJoinLeaveFieldKeys = ['guildId', 'peerId', 'meshPeerCount']
const meshChurnStaleEvictFieldKeys = ['guildId', 'evicted', 'peerRetryAttempt', 'lastPeerSeenAt', 'meshPeerCount']
const meshChurnPushPeerSlotFieldKeys = ['guildId', 'pushPeerSlot', 'meshPeerCount']
const meshChurnGossipFlushFieldKeys = ['guildId', 'flushed', 'remaining', 'reason']
function listMeshChurnLogBaseFieldKeys () {
return meshChurnLogBaseFieldKeys.slice()
}
function listMeshChurnPeerJoinLeaveFieldKeys () {
return meshChurnPeerJoinLeaveFieldKeys.slice()
}
function listMeshChurnStaleEvictFieldKeys () {
return meshChurnStaleEvictFieldKeys.slice()
}
function listMeshChurnPushPeerSlotFieldKeys () {
return meshChurnPushPeerSlotFieldKeys.slice()
}
function listMeshChurnGossipFlushFieldKeys () {
return meshChurnGossipFlushFieldKeys.slice()
}
function buildMeshChurnPeerJoinSnapshot (inputs = {}) {
const { guildId, peerId, meshPeerCount } = inputs
return {
guildId: guildId ?? null,
peerId: peerId ?? null,
meshPeerCount: meshPeerCount ?? 0
}
}
function buildMeshChurnPeerLeaveSnapshot (inputs = {}) {
const { guildId, peerId, meshPeerCount } = inputs
return {
guildId: guildId ?? null,
peerId: peerId ?? null,
meshPeerCount: meshPeerCount ?? 0
}
}
function buildMeshChurnStaleEvictSnapshot (inputs = {}) {
const { guildId, evicted, peerRetryAttempt, lastPeerSeenAt, meshPeerCount } = inputs
return {
guildId: guildId ?? null,
evicted: Number(evicted) || 0,
peerRetryAttempt: Number(peerRetryAttempt) || 0,
lastPeerSeenAt: lastPeerSeenAt ?? null,
meshPeerCount: meshPeerCount ?? 0
}
}
function buildMeshChurnPushPeerSlotSnapshot (inputs = {}) {
const { guildId, pushPeerSlot, meshPeerCount } = inputs
return {
guildId: guildId ?? null,
pushPeerSlot: pushPeerSlot ?? null,
meshPeerCount: meshPeerCount ?? 0
}
}
function buildMeshChurnGossipFlushSnapshot (inputs = {}) {
const { guildId, flushed, remaining, reason } = inputs
return {
guildId: guildId ?? null,
flushed: Number(flushed) || 0,
remaining: Number(remaining) || 0,
reason: reason ?? null
}
}
module.exports = {
meshChurnLogBaseFieldKeys,
meshChurnPeerJoinLeaveFieldKeys,
meshChurnStaleEvictFieldKeys,
meshChurnPushPeerSlotFieldKeys,
meshChurnGossipFlushFieldKeys,
listMeshChurnLogBaseFieldKeys,
listMeshChurnPeerJoinLeaveFieldKeys,
listMeshChurnStaleEvictFieldKeys,
listMeshChurnPushPeerSlotFieldKeys,
listMeshChurnGossipFlushFieldKeys,
buildMeshChurnPeerJoinSnapshot,
buildMeshChurnPeerLeaveSnapshot,
buildMeshChurnStaleEvictSnapshot,
buildMeshChurnPushPeerSlotSnapshot,
buildMeshChurnGossipFlushSnapshot
}
@@ -1,5 +1,6 @@
'use strict'
const { buildMeshChurnGossipFlushSnapshot } = require('../../../guild-mesh-churn-stats-build')
const { ensureGuildWireChannels } = require('pearcord-guild/mesh')
const { wireReady } = require('pearcord-drive/mux-wire')
const swarmScope = require('../../../platform-swarm-manager-imports')
@@ -66,19 +67,19 @@ const platformGuildGossipOutboxMixin = {
reason: opts.reason || null,
laneCounts
})
this._logMeshChurn('gossip-outbox-flush', {
this._logMeshChurn('gossip-outbox-flush', buildMeshChurnGossipFlushSnapshot({
guildId,
flushed,
remaining: Number(out?.remaining) || this._guildGossipOutbox.size,
reason: opts.reason || null
})
}))
} else if (guildId && before > 0 && opts.reason === 'peer-join') {
this._logMeshChurn('gossip-outbox-flush', {
this._logMeshChurn('gossip-outbox-flush', buildMeshChurnGossipFlushSnapshot({
guildId,
flushed: 0,
remaining: before,
reason: 'peer-join-empty'
})
}))
}
return out
},
@@ -1,5 +1,7 @@
'use strict'
const { buildMeshChurnPushPeerSlotSnapshot } = require('../../../guild-mesh-churn-stats-build')
const {
fs, path, b4a, EventEmitter,
swarmScope, dmScope, appEventsScope, automationScope,
@@ -1495,11 +1497,11 @@ async _pushGuildSyncToMesh (opts = {}) {
this._guildSyncPushPeerSlot
)
if (peerCount > 1 && this._guildSyncPushPeerSlot !== prevSlot) {
this._logMeshChurn('push-peer-slot', {
this._logMeshChurn('push-peer-slot', buildMeshChurnPushPeerSlotSnapshot({
guildId,
pushPeerSlot: this._guildSyncPushPeerSlot,
meshPeerCount: peerCount
})
}))
}
const prevHealth = this.getGuildSyncHealth(guildId)
await this._refreshGuildSyncTailWatermark(guildId, opts.priorityChannelId || opts.channelId)
@@ -1,5 +1,10 @@
'use strict'
const {
buildMeshChurnPeerLeaveSnapshot,
buildMeshChurnPeerJoinSnapshot
} = require('../../../guild-mesh-churn-stats-build')
const {
fs, path, b4a, EventEmitter,
swarmScope, dmScope, appEventsScope, automationScope,
@@ -431,11 +436,11 @@ _wireGuild (guildInstance) {
this._forgetGuildMeshPeerSeen(gid, peerId)
}
if (gid) {
this._logMeshChurn('peer-leave', {
this._logMeshChurn('peer-leave', buildMeshChurnPeerLeaveSnapshot({
guildId: gid,
peerId: peerId || null,
meshPeerCount: peers
})
}))
this._patchGuildSyncHealth({
guildId: gid,
peers,
@@ -488,11 +493,11 @@ _wireGuild (guildInstance) {
peerRetryAttempt: this._getGuildMeshPeerRetryAttempt(gid)
})
this._maybeEvictStaleGuildMeshPeers(gid, 'peer-join-sweep')
this._logMeshChurn('peer-join', {
this._logMeshChurn('peer-join', buildMeshChurnPeerJoinSnapshot({
guildId: gid,
peerId: peerId || null,
meshPeerCount: this.guild?.peers?.size ?? 0
})
}))
if (peerId) this._scheduleMemberEnsureFromMeshPeer(peerId, gid)
const meshPeerCount = this.guild?.peers?.size ?? 0
if (hadZeroPeer && meshPeerCount > 0) {
@@ -1,5 +1,7 @@
'use strict'
const { buildMeshChurnStaleEvictSnapshot } = require('../../../guild-mesh-churn-stats-build')
const localScope = require('../../../platform-index-local-imports')
const swarmScope = require('../../../platform-swarm-manager-imports')
@@ -161,13 +163,13 @@ const platformGuildMeshPeerMixin = {
stalePeersEvictedLast: out.evicted,
lastStalePeerEvictAt: now
})
this._logMeshChurn('stale-peer-evict', {
this._logMeshChurn('stale-peer-evict', buildMeshChurnStaleEvictSnapshot({
guildId: gid,
evicted: out.evicted,
peerRetryAttempt,
lastPeerSeenAt: maxSeen || out.lastPeerSeenAt,
meshPeerCount: peers
})
}))
if (peers === 0) this._scheduleGuildMeshPeerRetry(gid)
}
return out