Phase 887: registry RPC method resolve + targeted export pull mixin (v0.8.854)

Non-breaking refactor: resolveGuildGossipRpcMethodId and
fetchTargetedGuildGossipRpcPullByConfig for audit/digest pulls without manual
rpcMethod; platform-targeted-export-rpc-pull-mixin shared pull helper;
validatePlatformGuildGossipRpcHandlers for handler manifest checks. Default
gossip v1 unchanged; fleet v2 cutover still deferred.
This commit is contained in:
Raven Scott
2026-06-04 18:43:51 -04:00
parent 0d77618210
commit de549d66a0
7 changed files with 90 additions and 22 deletions
+2
View File
@@ -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 887 (v0.8.854):** Registry RPC method resolve + targeted export pull mixin + handler manifest validation. Bundle: `npm run test:ci-phase887`.
**Phase 886 (v0.8.853):** Registry-driven handler map + `bindGuildGossipRpcHandlers()` + wire bind mixin extract. Bundle: `npm run test:ci-phase886`.
**Phase 885 (v0.8.852):** Targeted pull orchestrator + registry dispatch + audit/digest responders extract. Bundle: `npm run test:ci-phase885`.
+22 -1
View File
@@ -12,7 +12,7 @@ const {
const { pickFirstGuildRpcResponse } = require('./gossip-rpc-validators')
const { buildGuildGossipRpcPullOpts } = require('./gossip-rpc-pull-config')
const { buildTargetedGuildGossipRpcFetchPayload } = require('./gossip-rpc-payload')
const { lookupGuildGossipRpcPullRegistryEntryByConfig } = require('./gossip-rpc-registry')
const { lookupGuildGossipRpcPullRegistryEntryByConfig, resolveGuildGossipRpcMethodId } = require('./gossip-rpc-registry')
/** Shared peer resolve + wire prep for guild gossip RPC fanout (Phase 880). */
async function prepareGuildGossipRpcFanoutRequest (platform, opts = {}) {
@@ -155,11 +155,32 @@ async function fetchGuildGossipRpcPullByConfig (platform, configKey, overrides =
return fetchGuildGossipRpcPullHit(platform, opts)
}
/** Targeted pullHit via registry config + RPC method resolve (Phase 887). */
async function fetchTargetedGuildGossipRpcPullByConfig (
platform,
configKey,
resourceIdField,
opts = {},
nextRequestId
) {
const entry = lookupGuildGossipRpcPullRegistryEntryByConfig(configKey)
if (!entry || entry.pullKind !== 'pullHit') return null
const rpcMethod = resolveGuildGossipRpcMethodId(entry.methodKey)
if (rpcMethod == null) return null
return fetchTargetedGuildGossipRpcPullHit(platform, configKey, {
resourceIdField,
rpcMethod,
opts,
nextRequestId
})
}
module.exports = {
prepareGuildGossipRpcFanoutRequest,
fetchGuildGossipRpcPullHit,
fetchGuildGossipRpcFromHostHit,
fetchGuildGossipRpcPullMerged,
fetchTargetedGuildGossipRpcPullHit,
fetchTargetedGuildGossipRpcPullByConfig,
fetchGuildGossipRpcPullByConfig
}
+20 -1
View File
@@ -89,6 +89,7 @@ function validateGuildGossipRpcRegistryAlignment () {
throw new Error(`pull config key missing from registry: ${configKey}`)
}
}
validateGuildGossipRpcMethodIds()
return true
}
@@ -115,6 +116,22 @@ function lookupGuildGossipRpcPullRegistryEntryByConfig (configKey) {
return guildGossipRpcPullRegistry.find((entry) => entry.configKey === configKey) || null
}
/** Resolve protomux-rpc method id from registry method key (Phase 887). */
function resolveGuildGossipRpcMethodId (methodKey) {
const sharedScope = require('pearcord-shared')
const rpcMethod = sharedScope.RPC?.[methodKey]
return typeof rpcMethod === 'number' ? rpcMethod : null
}
function validateGuildGossipRpcMethodIds () {
for (const entry of guildGossipRpcPullRegistry) {
if (resolveGuildGossipRpcMethodId(entry.methodKey) == null) {
throw new Error(`registry methodKey missing RPC id: ${entry.methodKey}`)
}
}
return true
}
module.exports = {
guildGossipRpcPullRegistry,
listGuildGossipRpcPullConfigKeys,
@@ -123,5 +140,7 @@ module.exports = {
validateGuildGossipRpcRegistryAlignment,
buildGuildGossipRpcRegistrySnapshot,
lookupGuildGossipRpcPullRegistryEntry,
lookupGuildGossipRpcPullRegistryEntryByConfig
lookupGuildGossipRpcPullRegistryEntryByConfig,
resolveGuildGossipRpcMethodId,
validateGuildGossipRpcMethodIds
}
+17 -2
View File
@@ -1,9 +1,10 @@
'use strict'
const { matchesGuildRpcTargetMember } = require('./gossip-rpc-validators')
const { listGuildGossipRpcHandlerMethods } = require('./gossip-rpc-registry')
/** True when payload guild/targetMember matches platform responder context (Phase 885). */
function assertGuildRpcTargetResponder (payload, platform) {
const { matchesGuildRpcTargetMember } = require('./gossip-rpc-validators')
return matchesGuildRpcTargetMember(
payload,
platform.guild?.guild?.id,
@@ -21,4 +22,18 @@ function buildGuildRpcDeliveryResponseEnvelope (row, platform, payload) {
}
}
module.exports = { assertGuildRpcTargetResponder, buildGuildRpcDeliveryResponseEnvelope }
/** Assert platform exposes all registry handler methods (Phase 887). */
function validatePlatformGuildGossipRpcHandlers (platform) {
for (const method of listGuildGossipRpcHandlerMethods()) {
if (typeof platform[method] !== 'function') {
throw new Error(`missing guild gossip rpc handler ${method}`)
}
}
return true
}
module.exports = {
assertGuildRpcTargetResponder,
buildGuildRpcDeliveryResponseEnvelope,
validatePlatformGuildGossipRpcHandlers
}
@@ -1,20 +1,14 @@
'use strict'
const { id } = require('../../../platform-class-imports')
const sharedScope = require('../../../platform-pearcord-shared-imports')
const { fetchTargetedGuildGossipRpcPullHit } = require('../../../gossip-rpc-pull')
const { platformAuditArchiveRpcRespondersMixin } = require('./platform-audit-archive-rpc-responders-mixin')
const { platformTargetedExportRpcPullMixin } = require('./platform-targeted-export-rpc-pull-mixin')
const platformAuditArchiveRpcMixin = {
...platformAuditArchiveRpcRespondersMixin,
...platformTargetedExportRpcPullMixin,
async _tryFetchAuditExportArchiveFromMeshRpc (archiveId, opts = {}) {
return fetchTargetedGuildGossipRpcPullHit(this, 'auditExportArchive', {
resourceIdField: { archiveId },
rpcMethod: sharedScope.RPC.AUDIT_EXPORT_ARCHIVE_REQUEST,
opts,
nextRequestId: () => id()
})
return this._fetchTargetedExportFromMeshRpc('auditExportArchive', { archiveId }, opts)
}
}
@@ -1,22 +1,20 @@
'use strict'
const { id } = require('../../../platform-class-imports')
const sharedScope = require('../../../platform-pearcord-shared-imports')
const { fetchTargetedGuildGossipRpcPullHit } = require('../../../gossip-rpc-pull')
const {
platformAutomationDigestSnapshotRpcRespondersMixin
} = require('./platform-automation-digest-snapshot-rpc-responders-mixin')
const { platformTargetedExportRpcPullMixin } = require('./platform-targeted-export-rpc-pull-mixin')
const platformAutomationDigestSnapshotRpcMixin = {
...platformAutomationDigestSnapshotRpcRespondersMixin,
...platformTargetedExportRpcPullMixin,
async _tryFetchAutomationDigestSnapshotFromMeshRpc (snapshotId, opts = {}) {
return fetchTargetedGuildGossipRpcPullHit(this, 'automationDigestSnapshot', {
resourceIdField: { snapshotId },
rpcMethod: sharedScope.RPC.AUTOMATION_DIGEST_EXPORT_SNAPSHOT_REQUEST,
opts,
nextRequestId: () => id()
})
return this._fetchTargetedExportFromMeshRpc(
'automationDigestSnapshot',
{ snapshotId },
opts
)
}
}
@@ -0,0 +1,19 @@
'use strict'
const { id } = require('../../../platform-class-imports')
const { fetchTargetedGuildGossipRpcPullByConfig } = require('../../../gossip-rpc-pull')
/** Shared targeted export RPC mesh pull helper (Phase 887). */
const platformTargetedExportRpcPullMixin = {
async _fetchTargetedExportFromMeshRpc (configKey, resourceIdField, opts = {}) {
return fetchTargetedGuildGossipRpcPullByConfig(
this,
configKey,
resourceIdField,
opts,
() => id()
)
}
}
module.exports = { platformTargetedExportRpcPullMixin }