feat(attachments): extend stage/read spans and unlink on delete

attachment.stage reports stagedCount and remainingStagingCapacity;
attachment.read includes activeChannelId; attachment.unlink runs before
message removal when attachments were linked.

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
Raven Scott
2026-05-24 14:19:58 -04:00
co-authored by Cursor
parent 1d418de396
commit 6a97f814ee
2 changed files with 38 additions and 1 deletions
+2
View File
@@ -183,6 +183,8 @@ Expose a single `EventEmitter` API the UI drives over IPC (`apps/pearcord/index.
**v0.8.499 (Phase 536):** Compliance/audit spans extend — `audit.append`/`audit.export`/`compliance.snapshot` end metadata (`spanKind`, `activeChannelId`). UI compliance panel compositor wrappers, audit row `lastAuditRowId` + roving `tabindex`, clipboard compliance busy flags. Bundle: `npm run test:phase536-compliance`. See [COMPLIANCE.md](../../docs/COMPLIANCE.md), [AUDIT_LOG.md](../../docs/AUDIT_LOG.md). **v0.8.499 (Phase 536):** Compliance/audit spans extend — `audit.append`/`audit.export`/`compliance.snapshot` end metadata (`spanKind`, `activeChannelId`). UI compliance panel compositor wrappers, audit row `lastAuditRowId` + roving `tabindex`, clipboard compliance busy flags. Bundle: `npm run test:phase536-compliance`. See [COMPLIANCE.md](../../docs/COMPLIANCE.md), [AUDIT_LOG.md](../../docs/AUDIT_LOG.md).
**v0.8.519 (Phase 556):** Attachment spans extend — `attachment.stage` `stagedCount`/`remainingStagingCapacity`; `attachment.read` `activeChannelId`; `attachment.unlink` on delete. UI split attachment panels; `#attachment-panel-live`. Bundle: `npm run test:phase556-attachments`. See [ATTACHMENTS.md](../../docs/ATTACHMENTS.md).
**v0.8.518 (Phase 555):** Reaction spans extend — `reaction.toggle` `messageReactionCount`/`activeChannelId`; `reaction.list` `rowCount`/`messageCount`; `reaction.clear` on delete via `clearReactionsForMessage`. UI split reaction pills/quick-react/picker chrome/live panels; `#reaction-panel-live`. Bundle: `npm run test:phase555-reactions`. See [REACTIONS.md](../../docs/REACTIONS.md). **v0.8.518 (Phase 555):** Reaction spans extend — `reaction.toggle` `messageReactionCount`/`activeChannelId`; `reaction.list` `rowCount`/`messageCount`; `reaction.clear` on delete via `clearReactionsForMessage`. UI split reaction pills/quick-react/picker chrome/live panels; `#reaction-panel-live`. Bundle: `npm run test:phase555-reactions`. See [REACTIONS.md](../../docs/REACTIONS.md).
**v0.8.517 (Phase 554):** Messaging spans extend — `message.send` `channelMessageCount`/`remainingCharCapacity`; `message.edit` `editAgeMs`; `message.delete` `meshFanout`. UI split messaging panels; `#messaging-panel-live`. Bundle: `npm run test:phase554-messaging`. See [MESSAGING.md](../../docs/MESSAGING.md). **v0.8.517 (Phase 554):** Messaging spans extend — `message.send` `channelMessageCount`/`remainingCharCapacity`; `message.edit` `editAgeMs`; `message.delete` `meshFanout`. UI split messaging panels; `#messaging-panel-live`. Bundle: `npm run test:phase554-messaging`. See [MESSAGING.md](../../docs/MESSAGING.md).
+36 -1
View File
@@ -5295,6 +5295,9 @@ class PearcordPlatform extends EventEmitter {
authorId: user.id authorId: user.id
}) })
const rowMime = row?.mimeType || resolvedMime const rowMime = row?.mimeType || resolvedMime
const stagedCount = this.attachments?.countStagedForChannel
? await this.attachments.countStagedForChannel(this.activeChannelId)
: 0
span.end({ span.end({
spanKind: 'attachment.stage', spanKind: 'attachment.stage',
attachmentId: row?.id, attachmentId: row?.id,
@@ -5304,7 +5307,10 @@ class PearcordPlatform extends EventEmitter {
mimeType: rowMime, mimeType: rowMime,
byteLength, byteLength,
filenameLen: String(filename || '').length, filenameLen: String(filename || '').length,
isImage: String(rowMime || '').startsWith('image/') isImage: String(rowMime || '').startsWith('image/'),
stagedCount,
remainingStagingCapacity: Math.max(0, 10 - stagedCount),
activeChannelId: this.activeChannelId
}) })
return row return row
} catch (err) { } catch (err) {
@@ -12927,6 +12933,7 @@ class PearcordPlatform extends EventEmitter {
reactionCount = rows.filter((r) => r.messageId === messageId).length reactionCount = rows.filter((r) => r.messageId === messageId).length
} }
let clearedReactionCount = 0 let clearedReactionCount = 0
let unlinkedAttachmentCount = 0
if (this.messages?.clearReactionsForMessage && reactionCount > 0) { if (this.messages?.clearReactionsForMessage && reactionCount > 0) {
const clearSpan = this.log.time('reaction.clear', { const clearSpan = this.log.time('reaction.clear', {
spanKind: 'reaction.clear', spanKind: 'reaction.clear',
@@ -12954,6 +12961,33 @@ class PearcordPlatform extends EventEmitter {
clearSpan.fail(err) clearSpan.fail(err)
} }
} }
if (hadAttachments && this.attachments?.unlinkMessage) {
const unlinkSpan = this.log.time('attachment.unlink', {
spanKind: 'attachment.unlink',
messageId,
guildId,
channelId
})
try {
unlinkedAttachmentCount = await this.attachments.unlinkMessage(messageId)
unlinkSpan.end({
spanKind: 'attachment.unlink',
messageId,
guildId,
channelId,
unlinkedCount: unlinkedAttachmentCount,
activeChannelId: this.activeChannelId
})
} catch (err) {
this.log.error('attachment.unlink error', {
messageId,
guildId,
channelId,
error: err?.message || String(err)
})
unlinkSpan.fail(err)
}
}
await this.messages.remove(messageId) await this.messages.remove(messageId)
const payload = { const payload = {
id: messageId, id: messageId,
@@ -12970,6 +13004,7 @@ class PearcordPlatform extends EventEmitter {
channelId, channelId,
contentLength, contentLength,
hadAttachments, hadAttachments,
unlinkedAttachmentCount,
hadReactions: reactionCount > 0, hadReactions: reactionCount > 0,
reactionCount, reactionCount,
wasOwn: existing?.authorId === this.identity?.user?.id, wasOwn: existing?.authorId === this.identity?.user?.id,