feat(postgres): add named push targets#830
Conversation
8cac7a7 to
6e4d79f
Compare
roborev: Combined Review (
|
|
Addressed in afc6ea0. |
|
Follow-up details for afc6ea0:
|
roborev: Combined Review (
|
mjacobs
left a comment
There was a problem hiding this comment.
Nice work — the named-target design is clean and the genuinely tricky parts are handled carefully. Things I specifically liked:
- Validation is correctly lazy:
finalize()(internal/config/config.go:1057) no longer validates PG targets, so a typo'ddefault_pgstill lets purely-local commands load and only PG resolution errors —TestLoadMinimal_DefersNamedPGValidationForNonPGCommandspins it. - Per-target watermark scoping is applied uniformly — every
last_push_at/boundary/fingerprint access inPushmoved froms.localto the scoped store fromeffectiveSyncState(), withpg_push_marker_iddeliberately kept DB-global (push.go) sopg push --alldoesn't self-conflict. - The legacy→default migration (internal/postgres/sync.go:43-94) is idempotent and self-healing: a legacy key is cleared only after its value lands in scope, so a crash leaves the value in both places, never neither.
- The status read path is genuinely read-only:
ReadLastPushAt(sync.go:342) builds its scoped store withmigrateLegacy=falseand only falls back to a plain read of the legacy key.
Two minor, non-blocking items:
- (low — test placement) The three
TestScopedSyncStateStore*tests ininternal/postgres/sync_test.gocover the most safety-critical new logic (the copy-then-clear migration), but that file is//go:build pgtest, so the defaultmake testskips them —go test -tags fts5 -run TestScopedSyncStateStore ./internal/postgres/...reports[no tests to run]. They need no PostgreSQL (testDBis justdb.Open(tmp)). Moving them — andtestDB— into the existing non-pgtestinternal/postgres/sync_unit_test.gowould let the default suite guard the migration loop. (Non-tagged files compile into the pgtest build too, so the remaining PG tests keep seeingtestDB.) - (nit) Header output differs between sibling commands for a single named target:
pg status workprintsTarget: work(pg.go:280) butpg push workprints nothing (pg.go:107). Cosmetic; aligning push to the status condition would letpg push workconfirm which target it wrote to.
One question: is pg push --all against a legacy single [pg] block (currently accepted as a plain single push) the intended contract, or would you rather it error since there's nothing to fan out over? Harmless either way.
Also checked the earlier automated-review items against the latest commit: the validation-scoping and status-read fixes are both in afc6ea0f and tested, the per-target classifier double-call is gone, and the unused ResolvePGTargets() is at most a minor cleanup (the CLI fan-out shares one ordering source via PGTargetNames()).
|
rebasing |
Named PostgreSQL targets need separate push state, routing, service status, and validation so one configured target cannot accidentally inherit state or defaults from another. Includes: - docs(postgres): clarify named target routing (kenn-io#517) - fix(postgres): isolate named target resolution (kenn-io#517) - fix(postgres): align service install with named targets (kenn-io#517) - test(postgres): prove selected-target routing and scoped state (kenn-io#517) - test(postgres): cover aggregate and service status paths (kenn-io#517) - refactor(postgres): centralize named target defaults (kenn-io#517) - test(postgres): isolate command proofs from local state (kenn-io#517) - Keep named PG target failures actionable - test(postgres): keep reserved target names explicit (kenn-io#517) - Lock reserved PG target names into tests - chore(postgres): drop duplicate review-generated test file (kenn-io#517) - Keep PG owner markers stable across named targets - Keep PG target docs aligned with the CLI - Keep empty PG service status from hiding healthy state - Keep named PG parsing case-stable - Keep the PG parser regression test honest - Keep reserved PG target names documented - Preserve direct Sync constructions after sync-state scoping - Keep named PG target validation scoped to PG flows
bd73851 to
e12054f
Compare
The sync-state migration checks do not require a live PostgreSQL server, so keeping them behind the pgtest tag leaves the default test suite without coverage for the copy-then-clear safety path. Move the SQLite-only tests and helper into the untagged sync unit test file, while keeping the PostgreSQL integration coverage in the pgtest file. Also align single-target pg push output with pg status so explicitly selected targets are visible in command output.
roborev: Combined Review (
|
PostgreSQL status should not create or migrate the local SQLite archive just to display PG counts. That read path only needs SQLite for an optional last-push watermark, so missing local state should produce an empty watermark rather than a writable open. The PG push validation tests also disable daemon autostart because they are asserting config and connection validation, not daemon lifecycle. This avoids Windows cleanup failures from background test processes holding the write-owner lock.
PostgreSQL status treats local sync state as display-only. A stale, empty, or otherwise unreadable SQLite archive should not block PG connection checks or PG session/message counts. Keep local watermark reads best-effort and covered with an empty-archive regression so upgrade or partial-state scenarios still show PostgreSQL status.
roborev: Combined Review (
|
pg pushandpg statusstill assume one global PostgreSQL destination, which makes multiple remotes clumsy to operate and unsafe to share because one target can advance the same local watermark another target depends on, and the default-target service status path still reports the unscoped legacy watermark.This change adds named
[pg.NAME]targets anddefault_pgwhile keeping the existing single[pg]shape working as it does today.pg pushandpg statuscan now use the default target, select one named target, or run--allsequentially. Target selection now resolves only the target being used, so a broken sibling target no longer blockspg push archive,pg status archive, or the per-target--allloop.pg push --watchfollows the default target or one selected named target, and rejects--allso the long-running multi-target watcher problem stays out of scope. The existingAGENTSVIEW_PG_*overrides stay supported, but they apply only to the effective default target instead of trying to rewrite every named entry.The sync layer now scopes push watermark state by target name in named-target mode and lazily migrates the legacy global watermark into the selected default target on first use. Follow-up review fixes keep
pg_push_marker_idlocal to the SQLite database sopg push --alldoes not self-conflict across named targets, preserveLast push: neverfor healthypg service statusoutput, and document that legacy[pg]field names are unavailable as named target identifiers.pg service statusnow reads the effective default target scope, and the PostgreSQL docs now describe named targets,default_pg, default-target-only environment overrides, and the default-target-only service and watch behavior.pg serve, service install, and the broader long-running multi-target watch problem still stay out of scope here so the PR stays reviewable.Fixes #517