Harden view-list caching diagnostics and coalescing.

Add cache-hit/source metadata for pin, reaction, and discovery list spans, coalesce in-flight discovery list fetches, and batch view lookups to reduce redundant reads during render bursts.

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
Raven Scott
2026-06-02 10:41:09 -04:00
co-authored by Cursor
parent 73075b6bd6
commit fe5c3d087a
2 changed files with 125 additions and 12 deletions
+1
View File
@@ -8,6 +8,7 @@ Application facade: one `PearcordPlatform` class that wires identity, database,
**Phase 661 (v0.8.640):** Added dependency guard scripts: `test:deps` compares `require('pearcord-*')` usage vs `package.json` declarations, `test:imports` smoke-resolves imported `pearcord-*` modules, and `ci:deps` fails when undeclared imports are introduced.
**Phase 410 hardening (v0.8.641):** Added cached pin snapshots in `view()` (`_pinListCacheKey/_pinListCacheGen` + `_invalidatePinListCache`) and broadened reaction snapshot cache reuse beyond light polls to reduce duplicate startup list scans.
**Phase 410 hardening (v0.8.643):** `view()` now emits cache-path span metadata for `pin.list`, `reaction.list`, and `discovery.list` (`cacheHit`, `source`), coalesces concurrent discovery listing fetches behind `_discoveryListPending`, and reports aggregate cache counters in `view.listCacheMetrics`.
**Phase 659 (v0.8.638):** DM scheduled messages slice — `sendMessage` parses `/schedule` and `/sendlater` in DM mode; queue APIs `createDmScheduledMessage`, `listDmScheduledMessages`, `cancelDmScheduledMessage`, `sendNowDmScheduledMessage`, plus due runner `runDueDmScheduledMessages()` and local timer flush. See [DM_SCHEDULED_MESSAGES.md](../../docs/DM_SCHEDULED_MESSAGES.md).
+124 -12
View File
@@ -488,10 +488,14 @@ class PearcordPlatform extends EventEmitter {
this._reactionListCache = null
this._reactionListCacheGen = 0
this._reactionListPending = null
this._reactionListMetrics = { cacheHit: 0, pendingHit: 0, miss: 0 }
this._pinListCacheKey = ''
this._pinListCache = null
this._pinListCacheGen = 0
this._pinListPending = null
this._pinListMetrics = { cacheHit: 0, pendingHit: 0, miss: 0 }
this._discoveryListPending = null
this._discoveryListMetrics = { cacheHit: 0, pendingHit: 0, miss: 0 }
this._lastReplicationCompact = null
this._memberPageBurstTimestamps = []
this._guildMeshBoundedByGuild = new Map()
@@ -20068,6 +20072,26 @@ class PearcordPlatform extends EventEmitter {
) {
reactions = this._reactionListCache.reactions
const cachedRows = Array.isArray(this._reactionListCache.rows) ? this._reactionListCache.rows : []
this._reactionListMetrics.cacheHit += 1
const listSpan = this.log.time('reaction.list', {
spanKind: 'reaction.list',
channelId: this.activeChannelId,
guildId: reactionGuildId,
light
})
listSpan.end({
spanKind: 'reaction.list',
channelId: this.activeChannelId,
guildId: reactionGuildId,
rowCount: cachedRows.length,
messageCount: Object.keys(reactions).length,
activeChannelId: this.activeChannelId,
guildCount: (this.guilds || []).length,
cached: true,
cacheHit: true,
source: 'cache',
light
})
this.log.debug('reaction.list cache hit', {
spanKind: 'reaction.list',
channelId: this.activeChannelId,
@@ -20083,6 +20107,7 @@ class PearcordPlatform extends EventEmitter {
const pending = this._reactionListPending
if (pending && pending.cacheKey === cacheKey) {
const rowCount = Array.isArray(pending.rows) ? pending.rows.length : null
this._reactionListMetrics.pendingHit += 1
this.log.debug('reaction.list pending cache hit', {
spanKind: 'reaction.list',
channelId: this.activeChannelId,
@@ -20097,10 +20122,32 @@ class PearcordPlatform extends EventEmitter {
try {
const out = await pending.promise
reactions = out.reactions || {}
const pendingRows = Array.isArray(out.rows) ? out.rows : []
const listSpan = this.log.time('reaction.list', {
spanKind: 'reaction.list',
channelId: this.activeChannelId,
guildId: reactionGuildId,
light
})
listSpan.end({
spanKind: 'reaction.list',
channelId: this.activeChannelId,
guildId: reactionGuildId,
rowCount: pendingRows.length,
messageCount: Object.keys(reactions).length,
activeChannelId: this.activeChannelId,
guildCount: (this.guilds || []).length,
cached: true,
cacheHit: true,
pending: true,
source: 'pending',
light
})
} catch {
reactions = {}
}
} else {
this._reactionListMetrics.miss += 1
const listSpan = this.log.time('reaction.list', {
spanKind: 'reaction.list',
channelId: this.activeChannelId,
@@ -20127,6 +20174,8 @@ class PearcordPlatform extends EventEmitter {
activeChannelId: this.activeChannelId,
guildCount: (this.guilds || []).length,
cached: false,
cacheHit: false,
source: 'fresh',
light
})
} catch (err) {
@@ -20163,13 +20212,15 @@ class PearcordPlatform extends EventEmitter {
activeChannelOverwrites = await this._channelOverwrites(this.activeChannelId)
}
let pins = []
let usersById =
guild && members.length ? await this._usersById(members) : {}
const mentionNames = new Set()
if (user) {
mentionNames.add(user.username)
if (user.displayName) mentionNames.add(user.displayName)
}
for (const mem of members) {
const u = await this.db.get(COLLECTIONS.USERS, { id: mem.userId })
const u = usersById[mem.userId]
if (u?.username) mentionNames.add(u.username)
if (u?.displayName) mentionNames.add(u.displayName)
if (mem.nickname) mentionNames.add(mem.nickname)
@@ -20179,6 +20230,23 @@ class PearcordPlatform extends EventEmitter {
const pinCacheKey = `${pinGuildId}:${this.activeChannelId || ''}:${this._pinListCacheGen || 0}`
if (this._pinListCacheKey === pinCacheKey && Array.isArray(this._pinListCache?.pins)) {
pins = this._pinListCache.pins
this._pinListMetrics.cacheHit += 1
const listSpan = this.log.time('pin.list', {
spanKind: 'search.pins',
channelId: this.activeChannelId,
guildId: pinGuildId
})
listSpan.end({
spanKind: 'search.pins',
channelId: this.activeChannelId,
guildId: pinGuildId,
guildCount: (this.guilds || []).length,
pinCount: pins.length,
activeChannelId: this.activeChannelId,
cached: true,
cacheHit: true,
source: 'cache'
})
this.log.debug('pin.list cache hit', {
spanKind: 'search.pins',
channelId: this.activeChannelId,
@@ -20191,6 +20259,7 @@ class PearcordPlatform extends EventEmitter {
} else {
const pending = this._pinListPending
if (pending && pending.cacheKey === pinCacheKey) {
this._pinListMetrics.pendingHit += 1
this.log.debug('pin.list pending cache hit', {
spanKind: 'search.pins',
channelId: this.activeChannelId,
@@ -20203,10 +20272,28 @@ class PearcordPlatform extends EventEmitter {
})
try {
pins = await pending.promise
const listSpan = this.log.time('pin.list', {
spanKind: 'search.pins',
channelId: this.activeChannelId,
guildId: pinGuildId
})
listSpan.end({
spanKind: 'search.pins',
channelId: this.activeChannelId,
guildId: pinGuildId,
guildCount: (this.guilds || []).length,
pinCount: pins.length,
activeChannelId: this.activeChannelId,
cached: true,
cacheHit: true,
pending: true,
source: 'pending'
})
} catch {
pins = []
}
} else {
this._pinListMetrics.miss += 1
const loader = this._channelPins(this.activeChannelId, pinGuildId)
this._pinListPending = { cacheKey: pinCacheKey, promise: loader, pins: null }
try {
@@ -20229,17 +20316,22 @@ class PearcordPlatform extends EventEmitter {
if (ma?.count) mentionAlerts[ma.channelId] = ma.count
}
if (guild) {
for (const ch of channels) {
const settingsChannels = channels.filter((ch) => {
if (
ch.type !== 'text' &&
ch.type !== 'thread' &&
ch.type !== 'forum' &&
ch.type !== 'announcement'
) {
continue
return false
}
const s = await this.getChannelSettings(ch.id, guild.id)
channelSettings[ch.id] = s
return true
})
const settingsRows = await Promise.all(
settingsChannels.map(async (ch) => [ch.id, await this.getChannelSettings(ch.id, guild.id)])
)
for (const [channelId, s] of settingsRows) {
channelSettings[channelId] = s
}
}
}
@@ -20272,8 +20364,6 @@ class PearcordPlatform extends EventEmitter {
if (rows.length) attachmentsByMessage[m.id] = rows
}
}
let usersById =
guild && members.length ? await this._usersById(members) : {}
if (user?.id) usersById = { ...usersById, [user.id]: user }
if (this.mode === 'dm') {
usersById = {
@@ -20298,7 +20388,7 @@ class PearcordPlatform extends EventEmitter {
const memberNameById = {}
if (guild) {
for (const mem of members) {
const u = await this.db.get(COLLECTIONS.USERS, { id: mem.userId })
const u = usersById[mem.userId]
memberNameById[mem.userId] = mem.nickname || u?.displayName || u?.username || mem.userId.slice(0, 8)
}
}
@@ -20416,6 +20506,7 @@ class PearcordPlatform extends EventEmitter {
this._cachedPublicListings &&
now - (this._cachedPublicListingsAt || 0) < cacheMs
if (cacheFresh) {
this._discoveryListMetrics.cacheHit += 1
publicListings = this._cachedPublicListings
if (!light) {
const filter = this._discoveryFilter
@@ -20435,14 +20526,29 @@ class PearcordPlatform extends EventEmitter {
minMembers: Number(filter?.minMembers || 0),
peerCount: this.discovery?.peers?.size ?? 0,
activeChannelId: this.activeChannelId,
guildCount: (this.guilds || []).length
guildCount: (this.guilds || []).length,
cacheHit: true
})
}
} else {
try {
const resolveListings = async () => {
if (this._discoveryListPending?.promise) {
this._discoveryListMetrics.pendingHit += 1
return this._discoveryListPending.promise
}
this._discoveryListMetrics.miss += 1
const loader = this.discovery.listPublicListings()
this._discoveryListPending = { promise: loader }
try {
return await loader
} finally {
this._discoveryListPending = null
}
}
if (!light) {
const listSpan = this.log.time('discovery.list', { spanKind: 'discovery.list' })
publicListings = await this.discovery.listPublicListings()
publicListings = await resolveListings()
const filter = this._discoveryFilter
const filteredCount = this.discovery
? this.discovery.filterPublicListings(publicListings, filter).length
@@ -20459,10 +20565,11 @@ class PearcordPlatform extends EventEmitter {
minMembers: Number(filter?.minMembers || 0),
peerCount: this.discovery?.peers?.size ?? 0,
activeChannelId: this.activeChannelId,
guildCount: (this.guilds || []).length
guildCount: (this.guilds || []).length,
cacheHit: false
})
} else {
publicListings = await this.discovery.listPublicListings()
publicListings = await resolveListings()
}
this._cachedPublicListings = publicListings
this._cachedPublicListingsAt = now
@@ -21130,6 +21237,11 @@ class PearcordPlatform extends EventEmitter {
publicListings,
filteredPublicListings,
discoveryFilter: { ...this._discoveryFilter },
listCacheMetrics: {
reactions: { ...this._reactionListMetrics },
pins: { ...this._pinListMetrics },
discovery: { ...this._discoveryListMetrics }
},
discoveryAllTags,
discoveryStats,
linkEmbedsByMessage,