feat(mesh): peer retry on guild create and wire/outbox hardening (v0.8.747)
Schedule mesh peer retry when create finishes with no peers; gossip outbox and wire mixin tweaks for join reliability during guild loading. Co-authored-by: Cursor <[email protected]>
This commit is contained in:
@@ -2,6 +2,8 @@
|
||||
|
||||
Application facade: one `PearcordPlatform` class that wires identity, database, guild mesh, DMs, invites, voice, discovery, bots, and dozens of feature modules for the Pearcord desktop sidecar and companion. **Mixin sources:** [`mixins/README.md`](mixins/README.md) — `domain/`, `json-export/`, `runtime/{core,mesh,guild-sync,search-discovery,partition-heal,view,voice-dm,features}/`. Architecture: [PLATFORM_MIXINS.md](../../docs/PLATFORM_MIXINS.md). Regenerate after manifest edits: `cd apps/pearcord && npm run regenerate:platform-mixins`. OTA prestage recursively verifies symbols under `mixins/` — [RELEASE.md](../../docs/RELEASE.md#prestage-sync-file-deps).
|
||||
|
||||
**Phase 780 (v0.8.747):** Guild mesh loading sync — peer retry on `createGuild` with 0 peers; `guild-loading` structural push path (worker + ui-flow). Bundle: `npm run test:ci-phase780`.
|
||||
|
||||
**Phase 779 (v0.8.746):** Effective permissions deep link `memberId` + `effectivePermFocusMemberId`; inspector cross-link to channel perms. Bundle: `npm run test:ci-phase779`.
|
||||
|
||||
**Phase 778 (v0.8.745):** Effective permissions deep link role focus — `navigateDeepLink` returns `effectivePermFocusRoleId` from `?effective=1&roleId=`. Bundle: `npm run test:ci-phase778`.
|
||||
|
||||
@@ -630,6 +630,16 @@ async createGuild ({ name, publicListing = true, templateId = null } = {}) {
|
||||
bounded: true,
|
||||
joinMeshCapMs: createCaps[0]
|
||||
})
|
||||
this._scheduleProfileGossipBurst()
|
||||
if ((this.guild.peers?.size ?? 0) === 0) {
|
||||
this._scheduleGuildMeshPeerRetry(result.guild.id)
|
||||
} else {
|
||||
this._maybeEvictStaleGuildMeshPeers(result.guild.id, 'guild-create')
|
||||
}
|
||||
this._startGuildMeshStalePeerSweep(result.guild.id)
|
||||
if (user.id === result.guild.ownerId) {
|
||||
void this._getGuildReplicator(result.guild.id).catch(() => {})
|
||||
}
|
||||
await this._initGuildVoice(result.guild.id)
|
||||
this.messages = new PearcordMessage({ authorId: user.id, db: this.db })
|
||||
await this.messages.ready()
|
||||
|
||||
@@ -1,8 +1,23 @@
|
||||
'use strict'
|
||||
|
||||
const { ensureGuildWireChannels } = require('pearcord-guild/mesh')
|
||||
const { wireReady } = require('pearcord-drive/mux-wire')
|
||||
const swarmScope = require('../../../platform-swarm-manager-imports')
|
||||
|
||||
const platformGuildGossipOutboxMixin = {
|
||||
async _ensureGuildGossipWireReady (timeoutMs) {
|
||||
if (!this.guild?._channels) return false
|
||||
ensureGuildWireChannels(this.guild)
|
||||
const wireMs =
|
||||
timeoutMs ??
|
||||
(Number(process.env.PEARCORD_GUILD_WIRE_READY_MS) || 4000)
|
||||
const sessions = [...this.guild._channels.values()]
|
||||
if (!sessions.length) return false
|
||||
const results = await Promise.all(
|
||||
sessions.map((session) => wireReady(session, wireMs).catch(() => false))
|
||||
)
|
||||
return results.some(Boolean)
|
||||
},
|
||||
async _guildGossipOrQueue (label, sendFn) {
|
||||
if (!this.guild || typeof sendFn !== 'function') return null
|
||||
const peers = this.guild.peers?.size ?? 0
|
||||
|
||||
@@ -343,7 +343,6 @@ _wireGuild (guildInstance) {
|
||||
40,
|
||||
Math.min(800, Date.now() - joinedAt)
|
||||
)
|
||||
void this._flushGuildGossipOutbox({ reason: 'peer-join' }).catch(() => {})
|
||||
if (gid && peerId) {
|
||||
this._trackGuildTopicPeer(gid, peerId, 'join')
|
||||
this._touchGuildMeshPeerSeen(gid, peerId, 'peer-join')
|
||||
@@ -366,9 +365,6 @@ _wireGuild (guildInstance) {
|
||||
meshPeerCount: this.guild?.peers?.size ?? 0
|
||||
})
|
||||
if (peerId) this._scheduleMemberEnsureFromMeshPeer(peerId, gid)
|
||||
if (this.guild?.guild?.ownerId === this.identity?.user?.id) {
|
||||
this._schedulePeerMemberIdentifyRequest(gid, peerId)
|
||||
}
|
||||
}
|
||||
const conn = peerId ? this.guild?.peers?.get(peerId) : null
|
||||
if (gid && conn) {
|
||||
@@ -384,24 +380,31 @@ _wireGuild (guildInstance) {
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
void (async () => {
|
||||
await this._ensureGuildGossipWireReady().catch(() => false)
|
||||
await this._flushGuildGossipOutbox({ reason: 'peer-join' }).catch(() => {})
|
||||
if (gid && peerId && this.guild?.guild?.ownerId === this.identity?.user?.id) {
|
||||
this._schedulePeerMemberIdentifyRequest(gid, peerId)
|
||||
}
|
||||
this._scheduleProfileGossipBurst()
|
||||
if (this.guild?.guild?.ownerId === this.identity?.user?.id) {
|
||||
this._guildSyncPushHalted.delete(this.guild.guild.id)
|
||||
this._scheduleGuildSyncPushBurst([250, 1000, 2500, 5000])
|
||||
} else {
|
||||
const joinGuildId = this.guild?.guild?.id
|
||||
const joinUserId = this.identity?.user?.id
|
||||
if (joinGuildId && joinUserId) {
|
||||
await this._gossipMemberJoinForUser(joinGuildId, joinUserId).catch(() => {})
|
||||
void this._nudgeGuildMemberJoinGossip(joinGuildId, joinUserId)
|
||||
}
|
||||
this._requestGuildSyncFromHost()
|
||||
this._scheduleGuildSyncRequestBurst([400, 1500, 3500])
|
||||
}
|
||||
this.emit('member')
|
||||
this.emit('presence')
|
||||
})().catch(() => {})
|
||||
}
|
||||
if (type !== 'join') return
|
||||
this._scheduleProfileGossipBurst()
|
||||
if (this.guild?.guild?.ownerId === this.identity?.user?.id) {
|
||||
this._guildSyncPushHalted.delete(this.guild.guild.id)
|
||||
this._scheduleGuildSyncPushBurst([250, 1000, 2500, 5000])
|
||||
} else {
|
||||
const joinGuildId = this.guild?.guild?.id
|
||||
const joinUserId = this.identity?.user?.id
|
||||
if (joinGuildId && joinUserId) {
|
||||
void this._gossipMemberJoinForUser(joinGuildId, joinUserId).catch(() => {})
|
||||
void this._nudgeGuildMemberJoinGossip(joinGuildId, joinUserId)
|
||||
}
|
||||
this._requestGuildSyncFromHost()
|
||||
this._scheduleGuildSyncRequestBurst([400, 1500, 3500])
|
||||
}
|
||||
this.emit('member')
|
||||
this.emit('presence')
|
||||
})
|
||||
guildInstance.on('attachment', (p) => {
|
||||
this.attachments?.ingestGossip(p).catch(() => {})
|
||||
|
||||
Reference in New Issue
Block a user