Commit 2ef7cbb
committed
fix: catchup shows no codes after startup backfill
Three bugs prevented /catchup from showing codes to newly registered users:
1. backfillHandler never persisted pending codes - incremented stats.pendingCodes
counter but never called codeManager.addPendingCode(), so no codes were
stored in the database for /catchup to find.
2. backfillHandler skipped all user redemptions - checked 'success' in
userDetailsResponse which is never true for valid PlayerData responses
(they have a 'details' property, not 'success'). Fixed by checking
!playerData?.details instead.
3. codeManager was missing several methods used by production code and tests:
normalizeCodeStatus, isCodeRedeemedByUser, getAllValidCodes,
addNewPendingCodes, getRedeemedCodeCount, deleteUserRedeemedCodes,
getRedeemedCodesByUsers, getServerCodeStats, getAggregateLoot (now backed
by loot_totals table), and backfillLootTotals.
Additional fixes in codeManager:
- addRedeemedCode: normalize numeric status codes via /^\d+$/ guard,
fix onConflictDoUpdate target to [code, discordId], propagate isPublic
flag correctly, write loot aggregates to loot_totals on Success.
- addPendingCode: add onConflictDoNothing() to make it idempotent.
- getRedeemedCodeDetails: add optional offset parameter.
- addNewPendingCodes: chunk inserts at 499 rows (2 params/row) to stay
within SQLite 999-variable limit.
- getRedeemedCodesFromList: chunk IN queries at 997 codes (+2 status
params) to stay within SQLite 999-variable limit.
- deleteUserRedeemedCodes: COUNT(*) + DELETE instead of RETURNING to
avoid materialising a large deleted-row array.
- getRedeemedCodesByUsers: chunk discordIds within per-query param budget.
- getPublicUnexpiredCodes: deduplicate by code (keep latest per code).
- getAllValidCodes: single SQL query using NOT IN subquery on expired set.
- Export CHEST_TYPE_NAMES and LootSummary type (used by codes.ts/stats.ts).
backfillHandler fixes:
- Normalize instance_id with String(...).trim() before comparing to '0'.
- Use inserted.length from addNewPendingCodes() for stats.pendingCodes so
re-runs do not over-report codes as newly pending.
- Validate instance_id is present and non-'0' before calling submitCode,
matching the guard in autoRedeemer.ts.
- Replace N+1 isCodeRedeemed/addPendingCode loop with a single
getRedeemedCodesFromList query + bulk addNewPendingCodes insert.
Adds end-to-end tests covering the startup-backfill -> setup -> catchup
flow, including API failure fallback, duplicate backfill idempotency,
invalid instance_id skip, SQLite chunking boundary paths, and
getPublicUnexpiredCodes multi-user deduplication.
Signed-off-by: Michael Cramer <michael@bigmichi1.de>1 parent 8f207e4 commit 2ef7cbb
4 files changed
Lines changed: 673 additions & 239 deletions
File tree
- src/bot
- database
- handlers
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
59 | 59 | | |
60 | 60 | | |
61 | 61 | | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
62 | 66 | | |
63 | 67 | | |
64 | 68 | | |
| |||
447 | 451 | | |
448 | 452 | | |
449 | 453 | | |
| 454 | + | |
| 455 | + | |
| 456 | + | |
| 457 | + | |
| 458 | + | |
| 459 | + | |
| 460 | + | |
| 461 | + | |
| 462 | + | |
| 463 | + | |
| 464 | + | |
| 465 | + | |
| 466 | + | |
| 467 | + | |
| 468 | + | |
| 469 | + | |
| 470 | + | |
| 471 | + | |
| 472 | + | |
| 473 | + | |
| 474 | + | |
| 475 | + | |
| 476 | + | |
| 477 | + | |
| 478 | + | |
| 479 | + | |
| 480 | + | |
| 481 | + | |
| 482 | + | |
| 483 | + | |
| 484 | + | |
| 485 | + | |
| 486 | + | |
| 487 | + | |
| 488 | + | |
| 489 | + | |
| 490 | + | |
| 491 | + | |
| 492 | + | |
| 493 | + | |
| 494 | + | |
| 495 | + | |
| 496 | + | |
| 497 | + | |
| 498 | + | |
| 499 | + | |
| 500 | + | |
| 501 | + | |
| 502 | + | |
| 503 | + | |
| 504 | + | |
| 505 | + | |
| 506 | + | |
| 507 | + | |
| 508 | + | |
450 | 509 | | |
451 | 510 | | |
452 | 511 | | |
| |||
511 | 570 | | |
512 | 571 | | |
513 | 572 | | |
| 573 | + | |
| 574 | + | |
| 575 | + | |
| 576 | + | |
| 577 | + | |
| 578 | + | |
| 579 | + | |
| 580 | + | |
514 | 581 | | |
515 | 582 | | |
516 | 583 | | |
| |||
594 | 661 | | |
595 | 662 | | |
596 | 663 | | |
| 664 | + | |
| 665 | + | |
| 666 | + | |
| 667 | + | |
| 668 | + | |
| 669 | + | |
| 670 | + | |
| 671 | + | |
597 | 672 | | |
598 | 673 | | |
599 | 674 | | |
| |||
786 | 861 | | |
787 | 862 | | |
788 | 863 | | |
| 864 | + | |
| 865 | + | |
| 866 | + | |
| 867 | + | |
| 868 | + | |
| 869 | + | |
| 870 | + | |
| 871 | + | |
| 872 | + | |
| 873 | + | |
789 | 874 | | |
| 875 | + | |
0 commit comments