Pete news code-review fixes: realm-first ordering, parked-row reap, death-emit gate

- emitZoneClearNews: claim realm-first before the name guard so an unnamed
  straggler's first clear seeds news_realm_firsts (else the next named
  clearer is mis-announced as first-ever). Mirrors backfillZoneFirsts.
- RunMaintenance: reap permanently-parked pete_emit_queue rows (unsent,
  >30d) so a durable Pete outage can't accrete rows forever.
- emitDeathNews: gate on Enabled()/newsEmissionOn() before the char DB
  reads; markAdventureDead fires per-member on party wipes + in the sim.
This commit is contained in:
prosolis
2026-07-11 07:56:41 -07:00
parent ae7ff38996
commit 1634bb1970
3 changed files with 18 additions and 4 deletions

View File

@@ -619,6 +619,11 @@ func RunMaintenance() {
// Pete adventure-news queue — reap delivered rows (kept only for // Pete adventure-news queue — reap delivered rows (kept only for
// idempotency); undelivered rows stay so the sender can retry/park them. // idempotency); undelivered rows stay so the sender can retry/park them.
{"pete_emit_queue", `DELETE FROM pete_emit_queue WHERE sent_at IS NOT NULL AND sent_at < ?`, []interface{}{cutoff7d}}, {"pete_emit_queue", `DELETE FROM pete_emit_queue WHERE sent_at IS NOT NULL AND sent_at < ?`, []interface{}{cutoff7d}},
// ...and reap permanently-parked rows: the sender exhausts its retries
// within a few hours, so anything still unsent after 30 days is dead
// weight the drain query already skips — drop it so a durable outage
// can't accrete rows forever.
{"pete_emit_queue_parked", `DELETE FROM pete_emit_queue WHERE sent_at IS NULL AND created_at < ?`, []interface{}{cutoff30d}},
// Rate limits — purge entries older than today // Rate limits — purge entries older than today
{"rate_limits", `DELETE FROM rate_limits WHERE date < ?`, []interface{}{today}}, {"rate_limits", `DELETE FROM rate_limits WHERE date < ?`, []interface{}{today}},

View File

@@ -583,6 +583,11 @@ func markAdventureDead(userID id.UserID, source, location string) {
// unless the seam is enabled. Uses the character name (never the Matrix handle); // unless the seam is enabled. Uses the character name (never the Matrix handle);
// skips silently if the name is unknown. // skips silently if the name is unknown.
func emitDeathNews(userID id.UserID, location string) { func emitDeathNews(userID id.UserID, location string) {
// Gate before the char lookups: markAdventureDead fires per-member on a
// party wipe and in the sim harness, so skip the DB reads when disabled.
if !peteclient.Enabled() || !newsEmissionOn() {
return
}
name := charName(userID) name := charName(userID)
if name == "" { if name == "" {
return return

View File

@@ -266,6 +266,14 @@ func emitZoneClearNews(userID id.UserID, exp *Expedition) {
if !peteclient.Enabled() || !newsEmissionOn() { if !peteclient.Enabled() || !newsEmissionOn() {
return return
} }
// Claim the realm-first BEFORE the name guard, so an unnamed straggler's
// genuine first clear still seeds news_realm_firsts. Otherwise the next
// named clearer would claim it and be mis-announced as the first-ever.
// Mirrors backfillZoneFirsts, which claims before its own name check.
eventType, tier := "zone_clear", "bulletin"
if claimRealmFirst("zone", string(exp.ZoneID)) {
eventType, tier = "zone_first", "priority"
}
name := charName(userID) name := charName(userID)
if name == "" { if name == "" {
return return
@@ -278,10 +286,6 @@ func emitZoneClearNews(userID id.UserID, exp *Expedition) {
} }
} }
lvl := charLevel(userID) lvl := charLevel(userID)
eventType, tier := "zone_clear", "bulletin"
if claimRealmFirst("zone", string(exp.ZoneID)) {
eventType, tier = "zone_first", "priority"
}
ts := nowUnix() ts := nowUnix()
disc := fmt.Sprintf("%s:%d", exp.ZoneID, ts) disc := fmt.Sprintf("%s:%d", exp.ZoneID, ts)
emitFact(peteclient.Fact{ emitFact(peteclient.Fact{