feat(platform): Phase 720 vanity-url.json and effective-permission.json mesh API
Add dedicated mixins and get/clear export helpers, view meta fields, dedicated log spans on push, and partition-heal hooks for vanity URL and effective permission signed JSON exports (RPC 113 / 115). 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.
|
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.
|
||||||
|
|
||||||
|
**Phase 720 (v0.8.696):** Vanity URL JSON & effective permission export — `vanity-url-json-mixin.js`, `effective-permission-json-mixin.js`, `vanity-url.json` / `effective-permission.json` spans, `getVanityUrlExportJsonExport` / `getEffectivePermissionExportJsonExport`, deep links `?vanity-url-json=1` / `?effective-permission-json=1`. Bundle: `npm run test:ci-phase720`.
|
||||||
|
|
||||||
**Phase 719 (v0.8.695):** Read state JSON & webhook execute export — `read-state-json-mixin.js`, `webhook-json-mixin.js`, `read-state.json` / `webhook.json` spans, `pushReadStateExportToMesh`, `pushWebhookExecuteExportToMesh`, deep links `?read-state-json=1` / `?webhook-json=1`. Bundle: `npm run test:ci-phase719`.
|
**Phase 719 (v0.8.695):** Read state JSON & webhook execute export — `read-state-json-mixin.js`, `webhook-json-mixin.js`, `read-state.json` / `webhook.json` spans, `pushReadStateExportToMesh`, `pushWebhookExecuteExportToMesh`, deep links `?read-state-json=1` / `?webhook-json=1`. Bundle: `npm run test:ci-phase719`.
|
||||||
|
|
||||||
**Phase 718 (v0.8.694):** Channel follow JSON & guild widget export — `channel-follow-json-mixin.js`, `guild-widget-json-mixin.js`, `channel-follow.json` / `guild-widget.json` spans, `pushChannelFollowExportToMesh`, `pushGuildWidgetExportToMesh`, deep links `?channel-follow-json=1` / `?guild-widget-json=1`. Bundle: `npm run test:ci-phase718`.
|
**Phase 718 (v0.8.694):** Channel follow JSON & guild widget export — `channel-follow-json-mixin.js`, `guild-widget-json-mixin.js`, `channel-follow.json` / `guild-widget.json` spans, `pushChannelFollowExportToMesh`, `pushGuildWidgetExportToMesh`, deep links `?channel-follow-json=1` / `?guild-widget-json=1`. Bundle: `npm run test:ci-phase718`.
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const effectivePermissionJsonMixin = {
|
||||||
|
_effectivePermissionRegistryJsonGossipKeys: null,
|
||||||
|
_effectivePermissionJsonHealWatermark: null,
|
||||||
|
|
||||||
|
_initEffectivePermissionJsonMixinState () {
|
||||||
|
if (!this._effectivePermissionRegistryJsonGossipKeys) {
|
||||||
|
this._effectivePermissionRegistryJsonGossipKeys = new Set()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_shouldGossipEffectivePermissionRegistryJson (slice) {
|
||||||
|
this._initEffectivePermissionJsonMixinState()
|
||||||
|
if (!slice?.guildId || !slice?.signature) return true
|
||||||
|
const hash = `${slice.guildId}:${slice.exportedAt || 0}:${slice.signature}`
|
||||||
|
if (this._effectivePermissionRegistryJsonGossipKeys.has(hash)) return false
|
||||||
|
this._effectivePermissionRegistryJsonGossipKeys.add(hash)
|
||||||
|
if (this._effectivePermissionRegistryJsonGossipKeys.size > 8192) {
|
||||||
|
const first = this._effectivePermissionRegistryJsonGossipKeys.values().next().value
|
||||||
|
if (first) this._effectivePermissionRegistryJsonGossipKeys.delete(first)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
|
||||||
|
async _healEffectivePermissionJsonExportCursorOnPartition (guildId) {
|
||||||
|
const gid = guildId || this.guild?.guild?.id || null
|
||||||
|
const span = this.log.time('effective-permission.json', {
|
||||||
|
spanKind: 'effective-permission.json',
|
||||||
|
guildId: gid,
|
||||||
|
context: 'heal.effective-permission'
|
||||||
|
})
|
||||||
|
try {
|
||||||
|
if (!gid || !this.deliveryReceipts) {
|
||||||
|
span.end({ relisted: 0, skipped: true, guildEffectivePermissionJsonCount: 0 })
|
||||||
|
return { relisted: 0, skipped: true }
|
||||||
|
}
|
||||||
|
await this._initDeliveryReceipts(gid)
|
||||||
|
const rows = await this.deliveryReceipts.listEffectivePermissionExportJsonExports(64)
|
||||||
|
let relisted = 0
|
||||||
|
for (const row of rows) {
|
||||||
|
if (this._shouldGossipEffectivePermissionRegistryJson(row)) relisted++
|
||||||
|
}
|
||||||
|
const watermark = Date.now()
|
||||||
|
this._effectivePermissionJsonHealWatermark = watermark
|
||||||
|
span.end({
|
||||||
|
relisted,
|
||||||
|
watermark,
|
||||||
|
guildEffectivePermissionJsonCount: rows.length,
|
||||||
|
overwriteCount: rows[0]?.overwriteCount || 0,
|
||||||
|
bridgeKind: 'effective-permission.json'
|
||||||
|
})
|
||||||
|
return { relisted, watermark, guildEffectivePermissionJsonCount: rows.length }
|
||||||
|
} catch (err) {
|
||||||
|
this.log.error('effective-permission.json error', {
|
||||||
|
guildId: gid,
|
||||||
|
context: 'heal.effective-permission',
|
||||||
|
error: err?.message || String(err)
|
||||||
|
})
|
||||||
|
span.fail(err)
|
||||||
|
return { relisted: 0, error: err?.message || String(err) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { effectivePermissionJsonMixin }
|
||||||
@@ -1857,6 +1857,12 @@ class PearcordPlatform extends EventEmitter {
|
|||||||
const webhookJsonHeal = await this._healWebhookJsonExportCursorOnPartition(gid).catch(() => ({
|
const webhookJsonHeal = await this._healWebhookJsonExportCursorOnPartition(gid).catch(() => ({
|
||||||
relisted: 0
|
relisted: 0
|
||||||
}))
|
}))
|
||||||
|
const vanityUrlJsonMeshHeal = await this._healVanityUrlJsonExportCursorOnPartition(gid).catch(() => ({
|
||||||
|
relisted: 0
|
||||||
|
}))
|
||||||
|
const effectivePermissionJsonMeshHeal = await this._healEffectivePermissionJsonExportCursorOnPartition(gid).catch(() => ({
|
||||||
|
relisted: 0
|
||||||
|
}))
|
||||||
return {
|
return {
|
||||||
voiceApplied,
|
voiceApplied,
|
||||||
emojiSlots,
|
emojiSlots,
|
||||||
@@ -1929,7 +1935,9 @@ class PearcordPlatform extends EventEmitter {
|
|||||||
channelFollowJsonHeal,
|
channelFollowJsonHeal,
|
||||||
guildWidgetJsonHeal,
|
guildWidgetJsonHeal,
|
||||||
readStateJsonHeal,
|
readStateJsonHeal,
|
||||||
webhookJsonHeal
|
webhookJsonHeal,
|
||||||
|
vanityUrlJsonMeshHeal,
|
||||||
|
effectivePermissionJsonMeshHeal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -18750,7 +18758,13 @@ class PearcordPlatform extends EventEmitter {
|
|||||||
openBanJson: !!parsed.openBanJson,
|
openBanJson: !!parsed.openBanJson,
|
||||||
openPollJson: !!parsed.openPollJson,
|
openPollJson: !!parsed.openPollJson,
|
||||||
openPinJson: !!parsed.openPinJson,
|
openPinJson: !!parsed.openPinJson,
|
||||||
openThreadJson: !!parsed.openThreadJson
|
openThreadJson: !!parsed.openThreadJson,
|
||||||
|
openReadStateJson: !!parsed.openReadStateJson,
|
||||||
|
openWebhookJson: !!parsed.openWebhookJson,
|
||||||
|
openVanityUrlJson: !!parsed.openVanityUrlJson,
|
||||||
|
openEffectivePermissionJson: !!parsed.openEffectivePermissionJson,
|
||||||
|
openChannelFollowJson: !!parsed.openChannelFollowJson,
|
||||||
|
openGuildWidgetJson: !!parsed.openGuildWidgetJson
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -23069,10 +23083,43 @@ class PearcordPlatform extends EventEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getVanityUrlExportJsonExport () {
|
||||||
|
const gid = this.guild?.guild?.id || null
|
||||||
|
const span = this.log.time('vanity-url.json', { spanKind: 'vanity-url.json', guildId: gid, context: 'read' })
|
||||||
|
try {
|
||||||
|
if (!this.guild?.guild) { span.end({ guildVanityUrlJsonCount: 0, skipped: true }); return null }
|
||||||
|
await this._initDeliveryReceipts(this.guild.guild.id)
|
||||||
|
const row = await this.deliveryReceipts.getVanityUrlExportJsonExport()
|
||||||
|
if (!row?.signature) {
|
||||||
|
span.end({ guildVanityUrlJsonCount: row ? 1 : 0, hasSignature: false, bridgeKind: 'vanity-url.json' })
|
||||||
|
return row
|
||||||
|
}
|
||||||
|
const verified = verifyVanityUrlExportJson(exportBodyFromSlice(row) || row.jsonBody || row.jsonBody, row.signature, {
|
||||||
|
guildId: this.guild.guild.id,
|
||||||
|
relaySecret: this.guild.guild.id
|
||||||
|
})
|
||||||
|
const out = { ...row, signatureValid: verified.ok, inviteCount: row.inviteCount || 0 }
|
||||||
|
span.end({ guildVanityUrlJsonCount: 1, hasSignature: true, signatureValid: verified.ok, bridgeKind: 'vanity-url.json' })
|
||||||
|
return out
|
||||||
|
} catch (err) {
|
||||||
|
this.log.error('vanity-url.json error', { guildId: gid, context: 'read', error: err?.message || String(err) })
|
||||||
|
span.fail(err); throw err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async clearVanityUrlExportJsonExports () {
|
||||||
|
if (!this.guild?.guild) throw new Error('no guild')
|
||||||
|
if (!(await this._hasPerm(PERMISSION.MANAGE_GUILD))) throw new Error('no permission to clear vanity URL JSON exports')
|
||||||
|
await this._initDeliveryReceipts(this.guild.guild.id)
|
||||||
|
const removed = await this.deliveryReceipts.clearVanityUrlExportJsonExports()
|
||||||
|
this.emit('vanity-url-export-json-cleared', { removed })
|
||||||
|
return { removed }
|
||||||
|
}
|
||||||
|
|
||||||
async pushVanityUrlExportToMesh () {
|
async pushVanityUrlExportToMesh () {
|
||||||
const gid = this.guild?.guild?.id || null
|
const gid = this.guild?.guild?.id || null
|
||||||
const span = this.log.time('invite.json', {
|
const span = this.log.time('vanity-url.json', {
|
||||||
spanKind: 'invite.json',
|
spanKind: 'vanity-url.json',
|
||||||
guildId: gid,
|
guildId: gid,
|
||||||
context: 'mesh.vanity'
|
context: 'mesh.vanity'
|
||||||
})
|
})
|
||||||
@@ -23104,13 +23151,13 @@ class PearcordPlatform extends EventEmitter {
|
|||||||
meshPushed: true
|
meshPushed: true
|
||||||
}
|
}
|
||||||
span.end({
|
span.end({
|
||||||
guildInviteJsonCount: exported.inviteCount || 0,
|
guildVanityUrlJsonCount: exported.inviteCount || 0,
|
||||||
meshPushed: true,
|
meshPushed: true,
|
||||||
bridgeKind: 'invite.json'
|
bridgeKind: 'vanity-url.json'
|
||||||
})
|
})
|
||||||
return exported
|
return exported
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.log.error('invite.json error', {
|
this.log.error('vanity-url.json error', {
|
||||||
guildId: gid,
|
guildId: gid,
|
||||||
context: 'mesh.vanity',
|
context: 'mesh.vanity',
|
||||||
error: err?.message || String(err)
|
error: err?.message || String(err)
|
||||||
@@ -23384,10 +23431,43 @@ class PearcordPlatform extends EventEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getEffectivePermissionExportJsonExport () {
|
||||||
|
const gid = this.guild?.guild?.id || null
|
||||||
|
const span = this.log.time('effective-permission.json', { spanKind: 'effective-permission.json', guildId: gid, context: 'read' })
|
||||||
|
try {
|
||||||
|
if (!this.guild?.guild) { span.end({ guildEffectivePermissionJsonCount: 0, skipped: true }); return null }
|
||||||
|
await this._initDeliveryReceipts(this.guild.guild.id)
|
||||||
|
const row = await this.deliveryReceipts.getEffectivePermissionExportJsonExport()
|
||||||
|
if (!row?.signature) {
|
||||||
|
span.end({ guildEffectivePermissionJsonCount: row ? 1 : 0, hasSignature: false, bridgeKind: 'effective-permission.json' })
|
||||||
|
return row
|
||||||
|
}
|
||||||
|
const verified = verifyEffectivePermissionExportJson(exportBodyFromSlice(row) || row.jsonBody || row.jsonBody, row.signature, {
|
||||||
|
guildId: this.guild.guild.id,
|
||||||
|
relaySecret: this.guild.guild.id
|
||||||
|
})
|
||||||
|
const out = { ...row, signatureValid: verified.ok, overwriteCount: row.overwriteCount || 0 }
|
||||||
|
span.end({ guildEffectivePermissionJsonCount: 1, hasSignature: true, signatureValid: verified.ok, bridgeKind: 'effective-permission.json' })
|
||||||
|
return out
|
||||||
|
} catch (err) {
|
||||||
|
this.log.error('effective-permission.json error', { guildId: gid, context: 'read', error: err?.message || String(err) })
|
||||||
|
span.fail(err); throw err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async clearEffectivePermissionExportJsonExports () {
|
||||||
|
if (!this.guild?.guild) throw new Error('no guild')
|
||||||
|
if (!(await this._hasPerm(PERMISSION.MANAGE_CHANNELS))) throw new Error('no permission to clear effective permission JSON exports')
|
||||||
|
await this._initDeliveryReceipts(this.guild.guild.id)
|
||||||
|
const removed = await this.deliveryReceipts.clearEffectivePermissionExportJsonExports()
|
||||||
|
this.emit('effective-permission-export-json-cleared', { removed })
|
||||||
|
return { removed }
|
||||||
|
}
|
||||||
|
|
||||||
async pushEffectivePermissionExportToMesh () {
|
async pushEffectivePermissionExportToMesh () {
|
||||||
const gid = this.guild?.guild?.id || null
|
const gid = this.guild?.guild?.id || null
|
||||||
const span = this.log.time('permission.json', {
|
const span = this.log.time('effective-permission.json', {
|
||||||
spanKind: 'permission.json',
|
spanKind: 'effective-permission.json',
|
||||||
guildId: gid,
|
guildId: gid,
|
||||||
context: 'mesh.effective'
|
context: 'mesh.effective'
|
||||||
})
|
})
|
||||||
@@ -23419,13 +23499,13 @@ class PearcordPlatform extends EventEmitter {
|
|||||||
meshPushed: true
|
meshPushed: true
|
||||||
}
|
}
|
||||||
span.end({
|
span.end({
|
||||||
guildPermissionJsonCount: exported.overwriteCount || 0,
|
guildEffectivePermissionJsonCount: exported.overwriteCount || 0,
|
||||||
meshPushed: true,
|
meshPushed: true,
|
||||||
bridgeKind: 'permission.json'
|
bridgeKind: 'effective-permission.json'
|
||||||
})
|
})
|
||||||
return exported
|
return exported
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.log.error('permission.json error', {
|
this.log.error('effective-permission.json error', {
|
||||||
guildId: gid,
|
guildId: gid,
|
||||||
context: 'mesh.effective',
|
context: 'mesh.effective',
|
||||||
error: err?.message || String(err)
|
error: err?.message || String(err)
|
||||||
@@ -32599,10 +32679,12 @@ class PearcordPlatform extends EventEmitter {
|
|||||||
let lastOAuthInstallTokenExport = null
|
let lastOAuthInstallTokenExport = null
|
||||||
let inviteLinkJsonMeta = null
|
let inviteLinkJsonMeta = null
|
||||||
let inviteLinkJsonRows = []
|
let inviteLinkJsonRows = []
|
||||||
|
let vanityUrlExportJsonMeta = null
|
||||||
let vanityUrlExportJsonRows = []
|
let vanityUrlExportJsonRows = []
|
||||||
let lastVanityUrlExport = null
|
let lastVanityUrlExport = null
|
||||||
let roleOverrideJsonMeta = null
|
let roleOverrideJsonMeta = null
|
||||||
let roleOverrideJsonRows = []
|
let roleOverrideJsonRows = []
|
||||||
|
let effectivePermissionExportJsonMeta = null
|
||||||
let effectivePermissionExportJsonRows = []
|
let effectivePermissionExportJsonRows = []
|
||||||
let lastEffectivePermissionExport = null
|
let lastEffectivePermissionExport = null
|
||||||
let guildPermissionOverwrites = []
|
let guildPermissionOverwrites = []
|
||||||
@@ -32862,6 +32944,7 @@ class PearcordPlatform extends EventEmitter {
|
|||||||
})
|
})
|
||||||
return { ...row, signatureValid: verified.ok }
|
return { ...row, signatureValid: verified.ok }
|
||||||
})
|
})
|
||||||
|
vanityUrlExportJsonMeta = await this.getVanityUrlExportJsonExport().catch(() => null)
|
||||||
const vanityJsonHistory = await this.deliveryReceipts.listVanityUrlExportJsonExports(32)
|
const vanityJsonHistory = await this.deliveryReceipts.listVanityUrlExportJsonExports(32)
|
||||||
vanityUrlExportJsonRows = vanityJsonHistory.map((row) => {
|
vanityUrlExportJsonRows = vanityJsonHistory.map((row) => {
|
||||||
if (!row?.signature || !guild?.id) return row
|
if (!row?.signature || !guild?.id) return row
|
||||||
@@ -32882,6 +32965,7 @@ class PearcordPlatform extends EventEmitter {
|
|||||||
})
|
})
|
||||||
return { ...row, signatureValid: verified.ok }
|
return { ...row, signatureValid: verified.ok }
|
||||||
})
|
})
|
||||||
|
effectivePermissionExportJsonMeta = await this.getEffectivePermissionExportJsonExport().catch(() => null)
|
||||||
const effectiveJsonHistory =
|
const effectiveJsonHistory =
|
||||||
await this.deliveryReceipts.listEffectivePermissionExportJsonExports(32)
|
await this.deliveryReceipts.listEffectivePermissionExportJsonExports(32)
|
||||||
effectivePermissionExportJsonRows = effectiveJsonHistory.map((row) => {
|
effectivePermissionExportJsonRows = effectiveJsonHistory.map((row) => {
|
||||||
@@ -33665,12 +33749,18 @@ class PearcordPlatform extends EventEmitter {
|
|||||||
inviteLinkJsonMeta,
|
inviteLinkJsonMeta,
|
||||||
inviteLinkJsonRows,
|
inviteLinkJsonRows,
|
||||||
vanityUrlExportJsonRows,
|
vanityUrlExportJsonRows,
|
||||||
|
vanityUrlExportJsonMeta,
|
||||||
lastVanityUrlExport,
|
lastVanityUrlExport,
|
||||||
|
guildVanityUrlJsonCount:
|
||||||
|
(vanityUrlExportJsonRows || []).length + (guildInvites || []).length,
|
||||||
guildInviteJsonCount: (inviteLinkJsonRows || []).length + (guildInvites || []).length,
|
guildInviteJsonCount: (inviteLinkJsonRows || []).length + (guildInvites || []).length,
|
||||||
roleOverrideJsonMeta,
|
roleOverrideJsonMeta,
|
||||||
roleOverrideJsonRows,
|
roleOverrideJsonRows,
|
||||||
effectivePermissionExportJsonRows,
|
effectivePermissionExportJsonRows,
|
||||||
|
effectivePermissionExportJsonMeta,
|
||||||
lastEffectivePermissionExport,
|
lastEffectivePermissionExport,
|
||||||
|
guildEffectivePermissionJsonCount:
|
||||||
|
(effectivePermissionExportJsonRows || []).length + (guildPermissionOverwrites || []).length,
|
||||||
guildPermissionOverwrites,
|
guildPermissionOverwrites,
|
||||||
guildPermissionJsonCount:
|
guildPermissionJsonCount:
|
||||||
(roleOverrideJsonRows || []).length + (guildPermissionOverwrites || []).length,
|
(roleOverrideJsonRows || []).length + (guildPermissionOverwrites || []).length,
|
||||||
@@ -34450,6 +34540,8 @@ const { channelFollowJsonMixin } = require('./channel-follow-json-mixin')
|
|||||||
const { guildWidgetJsonMixin } = require('./guild-widget-json-mixin')
|
const { guildWidgetJsonMixin } = require('./guild-widget-json-mixin')
|
||||||
const { readStateJsonMixin } = require('./read-state-json-mixin')
|
const { readStateJsonMixin } = require('./read-state-json-mixin')
|
||||||
const { webhookJsonMixin } = require('./webhook-json-mixin')
|
const { webhookJsonMixin } = require('./webhook-json-mixin')
|
||||||
|
const { vanityUrlJsonMixin } = require('./vanity-url-json-mixin')
|
||||||
|
const { effectivePermissionJsonMixin } = require('./effective-permission-json-mixin')
|
||||||
Object.assign(PearcordPlatform.prototype, pollSchedulingMixin)
|
Object.assign(PearcordPlatform.prototype, pollSchedulingMixin)
|
||||||
Object.assign(PearcordPlatform.prototype, notificationsActivityMixin)
|
Object.assign(PearcordPlatform.prototype, notificationsActivityMixin)
|
||||||
Object.assign(PearcordPlatform.prototype, userSettingsMixin)
|
Object.assign(PearcordPlatform.prototype, userSettingsMixin)
|
||||||
@@ -34499,3 +34591,5 @@ Object.assign(PearcordPlatform.prototype, channelFollowJsonMixin)
|
|||||||
Object.assign(PearcordPlatform.prototype, guildWidgetJsonMixin)
|
Object.assign(PearcordPlatform.prototype, guildWidgetJsonMixin)
|
||||||
Object.assign(PearcordPlatform.prototype, readStateJsonMixin)
|
Object.assign(PearcordPlatform.prototype, readStateJsonMixin)
|
||||||
Object.assign(PearcordPlatform.prototype, webhookJsonMixin)
|
Object.assign(PearcordPlatform.prototype, webhookJsonMixin)
|
||||||
|
Object.assign(PearcordPlatform.prototype, vanityUrlJsonMixin)
|
||||||
|
Object.assign(PearcordPlatform.prototype, effectivePermissionJsonMixin)
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const vanityUrlJsonMixin = {
|
||||||
|
_vanityUrlRegistryJsonGossipKeys: null,
|
||||||
|
_vanityUrlJsonHealWatermark: null,
|
||||||
|
|
||||||
|
_initVanityUrlJsonMixinState () {
|
||||||
|
if (!this._vanityUrlRegistryJsonGossipKeys) {
|
||||||
|
this._vanityUrlRegistryJsonGossipKeys = new Set()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_shouldGossipVanityUrlRegistryJson (slice) {
|
||||||
|
this._initVanityUrlJsonMixinState()
|
||||||
|
if (!slice?.guildId || !slice?.signature) return true
|
||||||
|
const hash = `${slice.guildId}:${slice.exportedAt || 0}:${slice.signature}`
|
||||||
|
if (this._vanityUrlRegistryJsonGossipKeys.has(hash)) return false
|
||||||
|
this._vanityUrlRegistryJsonGossipKeys.add(hash)
|
||||||
|
if (this._vanityUrlRegistryJsonGossipKeys.size > 8192) {
|
||||||
|
const first = this._vanityUrlRegistryJsonGossipKeys.values().next().value
|
||||||
|
if (first) this._vanityUrlRegistryJsonGossipKeys.delete(first)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
|
||||||
|
async _healVanityUrlJsonExportCursorOnPartition (guildId) {
|
||||||
|
const gid = guildId || this.guild?.guild?.id || null
|
||||||
|
const span = this.log.time('vanity-url.json', {
|
||||||
|
spanKind: 'vanity-url.json',
|
||||||
|
guildId: gid,
|
||||||
|
context: 'heal.vanity-url'
|
||||||
|
})
|
||||||
|
try {
|
||||||
|
if (!gid || !this.deliveryReceipts) {
|
||||||
|
span.end({ relisted: 0, skipped: true, guildVanityUrlJsonCount: 0 })
|
||||||
|
return { relisted: 0, skipped: true }
|
||||||
|
}
|
||||||
|
await this._initDeliveryReceipts(gid)
|
||||||
|
const rows = await this.deliveryReceipts.listVanityUrlExportJsonExports(64)
|
||||||
|
let relisted = 0
|
||||||
|
for (const row of rows) {
|
||||||
|
if (this._shouldGossipVanityUrlRegistryJson(row)) relisted++
|
||||||
|
}
|
||||||
|
const watermark = Date.now()
|
||||||
|
this._vanityUrlJsonHealWatermark = watermark
|
||||||
|
span.end({
|
||||||
|
relisted,
|
||||||
|
watermark,
|
||||||
|
guildVanityUrlJsonCount: rows.length,
|
||||||
|
inviteCount: rows[0]?.inviteCount || 0,
|
||||||
|
bridgeKind: 'vanity-url.json'
|
||||||
|
})
|
||||||
|
return { relisted, watermark, guildVanityUrlJsonCount: rows.length }
|
||||||
|
} catch (err) {
|
||||||
|
this.log.error('vanity-url.json error', {
|
||||||
|
guildId: gid,
|
||||||
|
context: 'heal.vanity-url',
|
||||||
|
error: err?.message || String(err)
|
||||||
|
})
|
||||||
|
span.fail(err)
|
||||||
|
return { relisted: 0, error: err?.message || String(err) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { vanityUrlJsonMixin }
|
||||||
Reference in New Issue
Block a user