Phase 654: runMeshResilienceSoak journey with CI skip path.
3-peer live soak or single-host heal + replication lag assert when PEARCORD_SKIP_MESH_ROUNDTRIP=1. Co-authored-by: Cursor <[email protected]>
This commit is contained in:
@@ -1942,6 +1942,11 @@ class HeadlessSession {
|
||||
return runFanout(scenarioPath, opts)
|
||||
}
|
||||
|
||||
async runMeshResilienceSoak (scenarioPath, opts = {}) {
|
||||
const { runMeshResilienceSoak: runSoak } = require('./mesh')
|
||||
return runSoak(scenarioPath, opts)
|
||||
}
|
||||
|
||||
/** Journey: simulate remote hub post ingest on discovery mesh. */
|
||||
async runFederationHubIngestJourney () {
|
||||
if (!this.platform) throw new Error('headless not started')
|
||||
|
||||
@@ -315,6 +315,62 @@ async function runMeshChurnScaleSoakJourney (scenarioPath, opts = {}) {
|
||||
/**
|
||||
* Production federation live: 3-peer mesh + 8 fanout message tokens (CI-safe).
|
||||
*/
|
||||
/**
|
||||
* Phase 654: partition heal + replication diagnostics lag assert.
|
||||
* Full 3-peer live mesh unless `PEARCORD_SKIP_MESH_ROUNDTRIP=1`.
|
||||
*/
|
||||
async function runMeshResilienceSoak (scenarioPath, opts = {}) {
|
||||
const maxLagMs = Math.max(0, Number(opts.maxReplicationLagMs) || 120000)
|
||||
if (process.env.PEARCORD_SKIP_MESH_ROUNDTRIP === '1') {
|
||||
const base = path.join(os.tmpdir(), `pearcord-agentctl-resilience-${Date.now()}`)
|
||||
const host = new HeadlessSession({ storagePath: path.join(base, 'host') })
|
||||
if (opts.sessions) opts.sessions.push(host)
|
||||
await host.start()
|
||||
try {
|
||||
if (scenarioPath && fs.existsSync(scenarioPath)) {
|
||||
await host.runScenario(scenarioPath)
|
||||
} else {
|
||||
await host.registerUser({ username: 'resilience_host', displayName: 'Resilience' })
|
||||
await host.createGuild({ name: 'Mesh Resilience' })
|
||||
}
|
||||
const gid = host.platform.guild?.guild?.id
|
||||
if (!gid) throw new Error('mesh resilience: no guild')
|
||||
const heal = await host.runPartitionHealJourney(gid)
|
||||
const meshDiag = host.platform.exportMeshReplicationDiagnostics(gid)
|
||||
const lag = Number(meshDiag?.maxReplicationLagMs) || 0
|
||||
if (lag > maxLagMs) {
|
||||
throw new Error(`mesh resilience: replication lag ${lag}ms > ${maxLagMs}ms`)
|
||||
}
|
||||
return {
|
||||
peerCount: 1,
|
||||
guildId: gid,
|
||||
heal,
|
||||
meshDiag,
|
||||
soak: heal?.heal?.throttled ? 'heal-throttled' : 'ok',
|
||||
maxReplicationLagMs: lag,
|
||||
gossipLanes: meshDiag?.gossipLaneCounts || null,
|
||||
ciSkipMesh: true
|
||||
}
|
||||
} finally {
|
||||
await host.close()
|
||||
}
|
||||
}
|
||||
const live = await runPartitionHeal3PeerLiveJourney(scenarioPath, opts)
|
||||
const lag = Number(live.meshDiag?.maxReplicationLagMs) || 0
|
||||
if (lag > maxLagMs) {
|
||||
throw new Error(`mesh resilience: replication lag ${lag}ms > ${maxLagMs}ms`)
|
||||
}
|
||||
if (!live.heal?.heal && live.heal?.throttled) {
|
||||
return { ...live, soak: 'heal-throttled' }
|
||||
}
|
||||
return {
|
||||
...live,
|
||||
soak: 'ok',
|
||||
maxReplicationLagMs: lag,
|
||||
gossipLanes: live.meshDiag?.gossipLaneCounts || null
|
||||
}
|
||||
}
|
||||
|
||||
async function runMesh8PeerFanoutJourney (scenarioPath, opts = {}) {
|
||||
const triple = await connectGuildMeshTripleGroup(scenarioPath, {
|
||||
...opts,
|
||||
@@ -339,5 +395,6 @@ module.exports = {
|
||||
connectGuildMeshTripleGroup,
|
||||
runPartitionHeal3PeerLiveJourney,
|
||||
runMeshChurnScaleSoakJourney,
|
||||
runMeshResilienceSoak,
|
||||
runMesh8PeerFanoutJourney
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user