feat(platform): Phase 878 gossip RPC pull helpers + view diagnostics (v0.8.845)
Non-breaking mesh hardening: pickFirstGuildRpcResponse with shared validation predicates for audit/digest RPC pulls; buildGuildGossipRpcDiagnosticsSnapshot on platform view; unify pull-path viaRpc via markRpcResponse across mesh view and fetch helpers. Default gossip v1 unchanged; fleet v2 cutover deferred. Tests: test:ci-phase878 (boot gate, unit, view snapshot, method maps, live digest RPC). Docs: PLATFORM_ROADMAP, PROTOMUX_RPC_MIGRATION, AUTOMATED_TESTING, release notes.
This commit is contained in:
@@ -92,6 +92,8 @@ Application facade: one `PearcordPlatform` class that wires identity, database,
|
||||
|
||||
**Phase 822 (v0.8.789):** Triple-peer topology via `guild-mesh-topology` + `getMeshStabilityStats`. Bundle: `npm run test:ci-phase822`.
|
||||
|
||||
**Phase 878 (v0.8.845):** Gossip RPC pull response helpers (`pickFirstGuildRpcResponse`, validation predicates) + view diagnostics (`buildGuildGossipRpcDiagnosticsSnapshot`). Bundle: `npm run test:ci-phase878`.
|
||||
|
||||
**Phase 877 (v0.8.844):** View snapshot RPC wire diagnostics via `buildRpcWireViewSnapshot()`; guild sync/member page handlers use shared `markRpcResponse`. Bundle: `npm run test:ci-phase877`.
|
||||
|
||||
**Phase 876 (v0.8.843):** Shared `gossip-rpc-pull.js` + `gossip-rpc-handler-map.js` dedupe for all guild gossip RPC pull paths (zero behavior change). Bundle: `npm run test:ci-phase876`.
|
||||
|
||||
+29
-1
@@ -90,6 +90,20 @@ function markRpcResponse (res) {
|
||||
return res
|
||||
}
|
||||
|
||||
/** First matching guild gossip RPC pull response (Phase 878). */
|
||||
function pickFirstGuildRpcResponse (responses, predicate) {
|
||||
if (!Array.isArray(responses) || typeof predicate !== 'function') return null
|
||||
return responses.find((r) => r && predicate(r)) || null
|
||||
}
|
||||
|
||||
function isValidAuditExportArchiveRpcResponse (r) {
|
||||
return Array.isArray(r?.entries) && r.entries.length > 0
|
||||
}
|
||||
|
||||
function isValidAutomationDigestSnapshotRpcResponse (r) {
|
||||
return typeof r?.body === 'string' && r.body.length > 0
|
||||
}
|
||||
|
||||
/** Dev/settings snapshot of protomux-rpc opt-in flags (Phase 877). */
|
||||
function buildRpcWireViewSnapshot () {
|
||||
const {
|
||||
@@ -108,6 +122,16 @@ function buildRpcWireViewSnapshot () {
|
||||
}
|
||||
}
|
||||
|
||||
/** Guild gossip RPC handler diagnostics for platform view (Phase 878). */
|
||||
function buildGuildGossipRpcDiagnosticsSnapshot () {
|
||||
const { listGuildGossipRpcRequestMethodKeys } = require('./gossip-rpc-handler-map')
|
||||
const methods = listGuildGossipRpcRequestMethodKeys()
|
||||
return {
|
||||
guildGossipRpcHandlerCount: methods.length,
|
||||
guildGossipRpcRequestMethods: methods
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
meshPeerIdHex,
|
||||
guildRpcTimeoutsMs,
|
||||
@@ -117,5 +141,9 @@ module.exports = {
|
||||
requestGuildGossipRpcFromPeers,
|
||||
matchesGuildRpcTargetMember,
|
||||
markRpcResponse,
|
||||
buildRpcWireViewSnapshot
|
||||
pickFirstGuildRpcResponse,
|
||||
isValidAuditExportArchiveRpcResponse,
|
||||
isValidAutomationDigestSnapshotRpcResponse,
|
||||
buildRpcWireViewSnapshot,
|
||||
buildGuildGossipRpcDiagnosticsSnapshot
|
||||
}
|
||||
|
||||
@@ -9,7 +9,9 @@ const {
|
||||
guildRpcTimeoutsMs,
|
||||
resolveGuildGossipRpcPeerIds,
|
||||
prepareGuildGossipRpcSession,
|
||||
requestGuildGossipRpcFromPeers
|
||||
requestGuildGossipRpcFromPeers,
|
||||
pickFirstGuildRpcResponse,
|
||||
isValidAuditExportArchiveRpcResponse
|
||||
} = require('../../../gossip-rpc-pull')
|
||||
|
||||
const platformAuditArchiveRpcMixin = {
|
||||
@@ -69,7 +71,7 @@ const platformAuditArchiveRpcMixin = {
|
||||
rpcMs,
|
||||
wireMs
|
||||
})
|
||||
const hit = responses.find((r) => r && Array.isArray(r.entries) && r.entries.length)
|
||||
const hit = pickFirstGuildRpcResponse(responses, isValidAuditExportArchiveRpcResponse)
|
||||
return hit || null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ const {
|
||||
buildActivityFeed, enrichActivityWithAttachments, IPC_CONTRACT_VERSION, Hyperswarm,
|
||||
id, now, guildTopic
|
||||
} = require('../../../platform-class-imports')
|
||||
const { markRpcResponse } = require('../../../gossip-rpc-pull')
|
||||
|
||||
|
||||
/** Phase 756 — audit log & automation digest export */
|
||||
@@ -482,15 +483,14 @@ async _fetchAutomationDigestSnapshotFromMeshOnce (snapshotId, opts = {}) {
|
||||
const rpcSnap = await this._tryFetchAutomationDigestSnapshotFromMeshRpc(snapshotId, opts)
|
||||
if (rpcSnap?.body?.length) {
|
||||
await this.deliveryReceipts.ingestAutomationDigestExportSnapshot(rpcSnap).catch(() => {})
|
||||
return {
|
||||
return markRpcResponse({
|
||||
snapshotId: rpcSnap.id || snapshotId,
|
||||
format: rpcSnap.format,
|
||||
body: rpcSnap.body,
|
||||
summaryLines: rpcSnap.summaryLines,
|
||||
exportedAt: rpcSnap.exportedAt,
|
||||
fetchAttempt: (Number(opts.attempt) || 0) + 1,
|
||||
viaRpc: true
|
||||
}
|
||||
fetchAttempt: (Number(opts.attempt) || 0) + 1
|
||||
})
|
||||
}
|
||||
}
|
||||
const timeoutMs = Math.min(12000, Math.max(800, Number(opts.timeoutMs) || 3500))
|
||||
@@ -593,11 +593,10 @@ async _fetchAuditExportArchiveFromMeshOnce (archiveId, opts = {}) {
|
||||
if (rpcArch?.entries?.length) {
|
||||
await this.deliveryReceipts.ingestAuditExportArchive(rpcArch).catch(() => {})
|
||||
const out = await this.exportAuditExportArchive(rpcArch.id || archiveId, opts)
|
||||
return {
|
||||
return markRpcResponse({
|
||||
...out,
|
||||
fetchAttempt: (Number(opts.attempt) || 0) + 1,
|
||||
viaRpc: true
|
||||
}
|
||||
fetchAttempt: (Number(opts.attempt) || 0) + 1
|
||||
})
|
||||
}
|
||||
}
|
||||
const timeoutMs = Math.min(12000, Math.max(800, Number(opts.timeoutMs) || 3500))
|
||||
|
||||
@@ -8,7 +8,9 @@ const {
|
||||
guildRpcTimeoutsMs,
|
||||
resolveGuildGossipRpcPeerIds,
|
||||
prepareGuildGossipRpcSession,
|
||||
requestGuildGossipRpcFromPeers
|
||||
requestGuildGossipRpcFromPeers,
|
||||
pickFirstGuildRpcResponse,
|
||||
isValidAutomationDigestSnapshotRpcResponse
|
||||
} = require('../../../gossip-rpc-pull')
|
||||
|
||||
const platformAutomationDigestSnapshotRpcMixin = {
|
||||
@@ -70,7 +72,7 @@ const platformAutomationDigestSnapshotRpcMixin = {
|
||||
rpcMs,
|
||||
wireMs
|
||||
})
|
||||
const hit = responses.find((r) => r && typeof r.body === 'string' && r.body.length)
|
||||
const hit = pickFirstGuildRpcResponse(responses, isValidAutomationDigestSnapshotRpcResponse)
|
||||
return hit || null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,8 @@ const sharedScope = require('../../../platform-pearcord-shared-imports')
|
||||
const {
|
||||
guildRpcTimeoutsMs,
|
||||
resolveGuildGossipRpcHostPeerId,
|
||||
prepareGuildGossipRpcSession
|
||||
prepareGuildGossipRpcSession,
|
||||
markRpcResponse
|
||||
} = require('../../../gossip-rpc-pull')
|
||||
|
||||
const platformMeshViewMixin = {
|
||||
@@ -37,13 +38,12 @@ const platformMeshViewMixin = {
|
||||
)
|
||||
if (!page?.guildId) return null
|
||||
const added = await this._ingestMemberPage(page)
|
||||
return {
|
||||
return markRpcResponse({
|
||||
requested: true,
|
||||
viaRpc: true,
|
||||
offset: page.offset,
|
||||
memberCount: page.members?.length || 0,
|
||||
added
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
async _tryGuildSyncRequestRpc (channelId) {
|
||||
@@ -79,12 +79,11 @@ const platformMeshViewMixin = {
|
||||
)
|
||||
if (!bundle?.guildId) return null
|
||||
await this._ingestGuildSync(bundle)
|
||||
return {
|
||||
return markRpcResponse({
|
||||
requested: true,
|
||||
viaRpc: true,
|
||||
peerCount: 1,
|
||||
hostPublicKey: hostPk
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
_fanoutGuildSyncRequestBroadcast (channelId) {
|
||||
|
||||
@@ -28,7 +28,7 @@ const {
|
||||
id, now, guildTopic
|
||||
} = require('../../../platform-class-imports')
|
||||
const { buildSettingsHubView } = require('pearcord-shared/settings-taxonomy')
|
||||
const { buildRpcWireViewSnapshot } = require('../../../gossip-rpc-pull')
|
||||
const { buildRpcWireViewSnapshot, buildGuildGossipRpcDiagnosticsSnapshot } = require('../../../gossip-rpc-pull')
|
||||
|
||||
|
||||
/** Phase 756 — IPC view snapshot */
|
||||
@@ -2906,7 +2906,8 @@ async view (opts = {}) {
|
||||
: null,
|
||||
readReceiptSyncRows: await this._readReceiptSyncRowsForView(this.guild?.guild?.id),
|
||||
sparseAckSyncRows: this._sparseAckSyncRowsForView(this.guild?.guild?.id),
|
||||
...buildRpcWireViewSnapshot()
|
||||
...buildRpcWireViewSnapshot(),
|
||||
...buildGuildGossipRpcDiagnosticsSnapshot()
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
Reference in New Issue
Block a user