Skip to content

fix: resolve duplicate migration timestamps causing ambiguous ordering - #1356

Merged
RUKAYAT-CODER merged 1 commit into
rinafcode:mainfrom
Rafiat30:Ajibose/fix/duplicate-migration-timestamps
Aug 27, 2026
Merged

fix: resolve duplicate migration timestamps causing ambiguous ordering#1356
RUKAYAT-CODER merged 1 commit into
rinafcode:mainfrom
Rafiat30:Ajibose/fix/duplicate-migration-timestamps

Conversation

@Rafiat30

Copy link
Copy Markdown

Closes #1196

Problem

Three pairs of migration files under src/migrations/ shared identical numeric timestamps. TypeORM orders migrations by that timestamp, so within each pair the relative run order was undefined — it depended on filesystem load order rather than an explicit, deterministic sequence:

  • 1783000000003-add-course-full-text-search.ts and 1783000000003-clear-legacy-bcrypt-refresh-tokens.ts
  • 1790000000000-add-paused-subscription-status.ts and 1790000000000-fix-invoice-number-sequence.ts
  • 1796000000000-add-invoice-tax-columns.ts and 1796000000000-reconcile-schema-drift.ts (found while implementing the fix — not called out in the original issue, but the same bug)

For the first pair specifically, clear-legacy-bcrypt-refresh-tokens performs a data UPDATE on users, so it must not race or interleave with the DDL-only add-course-full-text-search migration (or the other DDL migrations at 1783000000004/1783000000005).

Fix

Renumbered one migration in each pair to the next unused timestamp, and renamed its class to match (TypeORM derives the migration's recorded name from the class name, so the two must stay in sync):

File Old timestamp New timestamp Class
clear-legacy-bcrypt-refresh-tokens.ts 1783000000003 1783000000006 ClearLegacyBcryptRefreshTokens1783000000006
fix-invoice-number-sequence.ts 1790000000000 1790000000001 FixInvoiceNumberSequence1790000000001
reconcile-schema-drift.ts 1796000000000 1796000000001 ReconcileSchemaDrift1796000000001 (also updates the explicit name field)

clear-legacy-bcrypt-refresh-tokens was bumped to 1783000000006 (rather than 1783000000004, which collides with the existing add-forum-indexes migration) so it deterministically runs after the full 17830000000031783000000005 DDL block instead of being sandwiched between DDL migrations.

The other file in each pair (add-course-full-text-search, add-paused-subscription-status, add-invoice-tax-columns) is unchanged.

No other files reference the old class names or timestamps (add-course-full-text-search is mentioned in src/search/search.service.ts, but that file kept its original timestamp, so the reference is still correct).

Files changed

Renamed (content + class name updated):

  • src/migrations/1783000000003-clear-legacy-bcrypt-refresh-tokens.tssrc/migrations/1783000000006-clear-legacy-bcrypt-refresh-tokens.ts
  • src/migrations/1790000000000-fix-invoice-number-sequence.tssrc/migrations/1790000000001-fix-invoice-number-sequence.ts
  • src/migrations/1796000000000-reconcile-schema-drift.tssrc/migrations/1796000000001-reconcile-schema-drift.ts

New:

  • src/migrations/migration-timestamps.spec.ts — test file (see below)

Tests added

src/migrations/migration-timestamps.spec.ts, following the existing filesystem-scanning spec pattern used elsewhere in the repo (e.g. src/monitoring/prometheus-rules.spec.ts):

  • Scans every file in src/migrations/ matching the digit-prefix convention TypeORM's migrations glob uses (src/migrations/[0-9]*).
  • Asserts no two migration files share the same numeric timestamp (the general regression guard for this class of bug).
  • Asserts every migration class name is suffixed with its own file's timestamp.
  • Asserts that where a migration sets an explicit name field, it matches the class name.
  • Regression-pins the three specific renumbered pairs: asserts the old duplicate-timestamp filenames no longer exist and the new ones do, and specifically asserts clear-legacy-bcrypt-refresh-tokens's timestamp is greater than add-course-full-text-search's (the ordering that matters per the issue).

How to test

npx jest src/migrations/migration-timestamps.spec.ts
node scripts/validate-migrations.js   # existing CI migration check, confirms it still passes

Both pass locally. Also verified:

  • grep'd the repo for the old class names/timestamps to confirm nothing else references them.
  • git mv was used so the renames are tracked as renames, not delete+add.
  • No new TypeScript errors introduced (npx tsc --noEmit shows the same pre-existing, unrelated errors in test/*.e2e-spec.ts on this branch as on main).

Three migration file pairs shared identical numeric timestamps, making
their relative execution order depend on non-deterministic file-load
order instead of the timestamp TypeORM uses to sequence migrations:

- 1783000000003: add-course-full-text-search / clear-legacy-bcrypt-refresh-tokens
- 1790000000000: add-paused-subscription-status / fix-invoice-number-sequence
- 1796000000000: add-invoice-tax-columns / reconcile-schema-drift

Renumber one migration in each pair to the next unused timestamp and
rename its class (TypeORM derives the recorded migration name from the
class) so `migrationsTableName` history stays consistent. For the first
pair, clear-legacy-bcrypt-refresh-tokens is bumped past the full-text-search
migration and the other 1783000000004/1783000000005 DDL migrations, since
it performs a data UPDATE that should not race DDL-only migrations.

The third pair (1796000000000) wasn't called out in the issue but was
found during implementation and fixed the same way for consistency.

Adds src/migrations/migration-timestamps.spec.ts, which asserts no two
migration files share a timestamp, that every migration class name is
suffixed with its file's timestamp, and pins down the three renumbered
pairs as a regression test.

Closes rinafcode#1196
@drips-wave

drips-wave Bot commented Aug 27, 2026

Copy link
Copy Markdown

@Rafiat30 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@RUKAYAT-CODER

Copy link
Copy Markdown
Contributor

Thank you for contributing to the project

@RUKAYAT-CODER
RUKAYAT-CODER merged commit 79d5c24 into rinafcode:main Aug 27, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Duplicate migration timestamps make ordering ambiguous (1783000000003, 1790000000000)

3 participants