Skip to content

refactor(migrate): abstract the migration lock behind a Locker interface #64

Description

@tdakkota

Follow-up to #46 (PR #63). Runner.Run (internal/ent/migrate/runner.go) currently
takes a Postgres session advisory lock (pg_advisory_lock/pg_advisory_unlock)
inline to serialize concurrent migrators. That ties the coordination mechanism
directly to Postgres and makes Runner's apply logic (sequencing, error
propagation, unlock-on-cancel) hard to unit test without a real database.

  • Extract a Locker interface (Lock(ctx) error / Unlock(ctx) error) out
    of the advisory-lock code; keep the Postgres advisory lock as the default
    implementation, injected via RunnerOptions (struct-options pattern per
    CLAUDE.md), not hardcoded in NewRunner.
  • Generate a moq mock for Locker so Runner.Run's sequencing/error
    handling can be unit-tested with a fake lock, independent of the
    integration test that already covers real Postgres concurrency
    (internal/ent/migrate/runner_integration_test.go).
  • Leaves the door open for a non-Postgres coordination backend (etcd,
    Consul, ...) later, without touching Runner.

Not blocking: today's Postgres advisory lock is correct and already covered by
an integration test (TestRunConcurrentCallersSerialize). This is a
testability/extensibility cleanup, not a bug fix.

Related: #48 (generalized Postgres job queue — same "don't hardcode Postgres
as the coordination primitive" theme, but for the ingest queue, not migration
locking).

Metadata

Metadata

Assignees

No one assigned

    Labels

    architectureArchitecture / structural

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions