-
Notifications
You must be signed in to change notification settings - Fork 2
feat: add migrate package #247
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: feat/PLAT-347/election-pkg
Are you sure you want to change the base?
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the 📝 WalkthroughWalkthroughThis PR introduces a startup-blocking migration framework for the server. It includes distributed locking via election, status tracking persisted to etcd, and sequential execution of migrations before service initialization. The system tracks migration revisions and execution metadata across instances. Changes
Sequence DiagramsequenceDiagram
participant App as App Startup
participant Runner as Migration Runner
participant Election as Election/Lock
participant Store as etcd Store
participant Migration as Migration Handler
App->>Runner: Run(ctx)
Runner->>Store: Get current revision
Store-->>Runner: Current revision
Runner->>Election: Acquire lock with candidate
Election-->>Runner: Lock acquired (leadership)
Runner->>Runner: Determine pending migrations from revision
loop For each pending migration
Runner->>Migration: Run(ctx, injector)
Migration->>Store: Update revision & status
Store-->>Migration: Persisted
Migration-->>Runner: Success/Error
Runner->>Store: Record execution metadata
end
Runner->>Store: Watch for revision changes (other instances)
Runner->>Election: Release lock
Runner-->>App: Return result
Estimated code review effort🎯 4 (Complex) | ⏱️ ~75 minutes
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
448017e to
847d42a
Compare
64e7057 to
24aad70
Compare
847d42a to
9238c9f
Compare
24aad70 to
8b2d7e1
Compare
9238c9f to
295b6d9
Compare
8b2d7e1 to
278a4cb
Compare
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
278a4cb to
d35513b
Compare
tsivaprasad
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good and has been verified through tests.
go test -v ./server/internal/migrate/
=== RUN TestRunner
=== RUN TestRunner/acquires_lock_and_runs_migrations
=== NAME TestRunner
writer.go:27: {"level":"debug","component":"migration_runner","message":"starting watch"}
writer.go:27: {"level":"debug","component":"election_candidate","election_name":"migration_runner","candidate_id":"host-1","message":"attempting to claim leadership"}
writer.go:27: {"level":"debug","component":"election_candidate","election_name":"migration_runner","candidate_id":"host-1","message":"successfully claimed leadership"}
writer.go:27: {"level":"debug","component":"election_candidate","election_name":"migration_runner","candidate_id":"host-1","message":"i am the current leader"}
writer.go:27: {"level":"debug","component":"election_candidate","election_name":"migration_runner","candidate_id":"host-1","message":"starting watch"}
writer.go:27: {"level":"info","component":"migration_runner","migration":"test-migration","message":"running migration"}
=== RUN TestRunner/multiple_runners
=== NAME TestRunner
writer.go:27: {"level":"debug","component":"migration_runner","message":"starting watch"}
writer.go:27: {"level":"debug","component":"migration_runner","message":"starting watch"}
writer.go:27: {"level":"debug","component":"election_candidate","election_name":"migration_runner","candidate_id":"host-1","message":"attempting to claim leadership"}
writer.go:27: {"level":"debug","component":"election_candidate","election_name":"migration_runner","candidate_id":"host-2","message":"attempting to claim leadership"}
writer.go:27: {"level":"debug","component":"election_candidate","election_name":"migration_runner","candidate_id":"host-1","message":"successfully claimed leadership"}
writer.go:27: {"level":"debug","component":"election_candidate","election_name":"migration_runner","candidate_id":"host-1","message":"i am the current leader"}
writer.go:27: {"level":"debug","component":"election_candidate","election_name":"migration_runner","candidate_id":"host-1","message":"starting watch"}
writer.go:27: {"level":"info","component":"migration_runner","migration":"test-migration","message":"running migration"}
writer.go:27: {"level":"debug","component":"election_candidate","election_name":"migration_runner","candidate_id":"host-2","message":"starting watch"}
{"level":"error","ts":"2026-01-16T17:51:22.191650+0530","caller":"embed/etcd.go:912","msg":"setting up serving from embedded etcd failed.","error":"http: Server closed","stacktrace":"go.etcd.io/etcd/server/v3/embed.(*Etcd).errHandler\n\t/Users/sivat/go/pkg/mod/go.etcd.io/etcd/server/[email protected]/embed/etcd.go:912\ngo.etcd.io/etcd/server/v3/embed.(*serveCtx).startHandler.func1\n\t/Users/sivat/go/pkg/mod/go.etcd.io/etcd/server/[email protected]/embed/serve.go:90"}
{"level":"error","ts":"2026-01-16T17:51:22.191637+0530","caller":"embed/etcd.go:912","msg":"setting up serving from embedded etcd failed.","error":"mux: server closed","stacktrace":"go.etcd.io/etcd/server/v3/embed.(*Etcd).errHandler\n\t/Users/sivat/go/pkg/mod/go.etcd.io/etcd/server/[email protected]/embed/etcd.go:912\ngo.etcd.io/etcd/server/v3/embed.(*serveCtx).startHandler.func1\n\t/Users/sivat/go/pkg/mod/go.etcd.io/etcd/server/[email protected]/embed/serve.go:90"}
{"level":"error","ts":"2026-01-16T17:51:22.191841+0530","caller":"embed/etcd.go:912","msg":"setting up serving from embedded etcd failed.","error":"accept tcp 127.0.0.1:58876: use of closed network connection","stacktrace":"go.etcd.io/etcd/server/v3/embed.(*Etcd).errHandler\n\t/Users/sivat/go/pkg/mod/go.etcd.io/etcd/server/[email protected]/embed/etcd.go:912\ngo.etcd.io/etcd/server/v3/embed.(*Etcd).startHandler.func1\n\t/Users/sivat/go/pkg/mod/go.etcd.io/etcd/server/[email protected]/embed/etcd.go:906"}
{"level":"error","ts":"2026-01-16T17:51:22.229545+0530","caller":"embed/etcd.go:912","msg":"setting up serving from embedded etcd failed.","error":"accept tcp 127.0.0.1:58877: use of closed network connection","stacktrace":"go.etcd.io/etcd/server/v3/embed.(*Etcd).errHandler\n\t/Users/sivat/go/pkg/mod/go.etcd.io/etcd/server/[email protected]/embed/etcd.go:912\ngo.etcd.io/etcd/server/v3/embed.(*Etcd).startHandler.func1\n\t/Users/sivat/go/pkg/mod/go.etcd.io/etcd/server/[email protected]/embed/etcd.go:906"}
--- PASS: TestRunner (0.57s)
--- PASS: TestRunner/acquires_lock_and_runs_migrations (0.03s)
--- PASS: TestRunner/multiple_runners (0.03s)
=== RUN TestRunnerMigrationOrdering
=== RUN TestRunnerMigrationOrdering/runs_migrations_in_order
=== RUN TestRunnerMigrationOrdering/starts_from_current_revision
=== RUN TestRunnerMigrationOrdering/stops_on_first_failure
=== RUN TestRunnerMigrationOrdering/records_status_for_each_migration
=== RUN TestRunnerMigrationOrdering/updates_revision_after_each_successful_migration
=== RUN TestRunnerMigrationOrdering/does_not_update_revision_after_failed_migration
{"level":"error","ts":"2026-01-16T17:51:23.199168+0530","caller":"embed/etcd.go:912","msg":"setting up serving from embedded etcd failed.","error":"http: Server closed","stacktrace":"go.etcd.io/etcd/server/v3/embed.(*Etcd).errHandler\n\t/Users/sivat/go/pkg/mod/go.etcd.io/etcd/server/[email protected]/embed/etcd.go:912\ngo.etcd.io/etcd/server/v3/embed.(*serveCtx).startHandler.func1\n\t/Users/sivat/go/pkg/mod/go.etcd.io/etcd/server/[email protected]/embed/serve.go:90"}
{"level":"error","ts":"2026-01-16T17:51:23.199168+0530","caller":"embed/etcd.go:912","msg":"setting up serving from embedded etcd failed.","error":"mux: server closed","stacktrace":"go.etcd.io/etcd/server/v3/embed.(*Etcd).errHandler\n\t/Users/sivat/go/pkg/mod/go.etcd.io/etcd/server/[email protected]/embed/etcd.go:912\ngo.etcd.io/etcd/server/v3/embed.(*serveCtx).startHandler.func1\n\t/Users/sivat/go/pkg/mod/go.etcd.io/etcd/server/[email protected]/embed/serve.go:90"}
{"level":"error","ts":"2026-01-16T17:51:23.199328+0530","caller":"embed/etcd.go:912","msg":"setting up serving from embedded etcd failed.","error":"accept tcp 127.0.0.1:58881: use of closed network connection","stacktrace":"go.etcd.io/etcd/server/v3/embed.(*Etcd).errHandler\n\t/Users/sivat/go/pkg/mod/go.etcd.io/etcd/server/[email protected]/embed/etcd.go:912\ngo.etcd.io/etcd/server/v3/embed.(*Etcd).startHandler.func1\n\t/Users/sivat/go/pkg/mod/go.etcd.io/etcd/server/[email protected]/embed/etcd.go:906"}
{"level":"error","ts":"2026-01-16T17:51:23.227938+0530","caller":"embed/etcd.go:912","msg":"setting up serving from embedded etcd failed.","error":"accept tcp 127.0.0.1:58882: use of closed network connection","stacktrace":"go.etcd.io/etcd/server/v3/embed.(*Etcd).errHandler\n\t/Users/sivat/go/pkg/mod/go.etcd.io/etcd/server/[email protected]/embed/etcd.go:912\ngo.etcd.io/etcd/server/v3/embed.(*Etcd).startHandler.func1\n\t/Users/sivat/go/pkg/mod/go.etcd.io/etcd/server/[email protected]/embed/etcd.go:906"}
--- PASS: TestRunnerMigrationOrdering (1.00s)
--- PASS: TestRunnerMigrationOrdering/runs_migrations_in_order (0.05s)
--- PASS: TestRunnerMigrationOrdering/starts_from_current_revision (0.04s)
--- PASS: TestRunnerMigrationOrdering/stops_on_first_failure (0.03s)
--- PASS: TestRunnerMigrationOrdering/records_status_for_each_migration (0.03s)
--- PASS: TestRunnerMigrationOrdering/updates_revision_after_each_successful_migration (0.03s)
--- PASS: TestRunnerMigrationOrdering/does_not_update_revision_after_failed_migration (0.04s)
PASS
ok github.com/pgEdge/control-plane/server/internal/migrate 2.074s
➜ control-plane git:(feat/PLAT-347/migrations)
295b6d9 to
51a12aa
Compare
Adds a `migrate` package with a mechanism to run an ordered set of migrations on startup, such as Etcd data migrations. The migrations runner uses the `election` package to ensure that only one server instance is running the migrations at a time. Other instances will block startup until the migrations are complete, so we should aim to keep migrations as lightweight as possible. As stated in the package documentation, these migrations should be idempotent and, where possible, non-destructive. PLAT-347
d35513b to
b81f4bf
Compare
Summary
Adds a
migratepackage with a mechanism to run an ordered set of migrations on startup, such as Etcd data migrations. The migrations runner uses theelectionpackage to ensure that only one server instance is running the migrations at a time. Other instances will block startup until the migrations are complete, so we should aim to keep migrations as lightweight as possible. As stated in the package documentation, these migrations should be idempotent and, where possible, non-destructive.Testing
This PR does not add any migrations, so there are no functional changes. You should see a log message
control-plane db is up to date, no migrations to runfrom one of the hosts.PLAT-347
Summary by CodeRabbit
New Features
Tests
✏️ Tip: You can customize this high-level summary in your review settings.