Acquire HA generator lock #1247
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Acquire a high-availability generator worker advisory lock by adding
db.LockKindGeneratorWorkerwith value0x04and invokingpayerreport.workers.GeneratorWorker.GenerateReportsto take the lock before report generation in generator.goThis change introduces a new advisory lock kind and methods to acquire it, and updates the generator worker to obtain the lock before generating reports. It adds the
db.LockKindGeneratorWorkerconstant with value0x04, extends the advisory locker interfaces and implementations to supportLockGeneratorWorker, and modifiespayerreport.workers.GeneratorWorker.GenerateReportsto acquire and release the transaction-scoped lock around its work.db.LockKindGeneratorWorker(0x04) and implementingdb.AdvisoryLocker.LockGeneratorWorkeranddb.TransactionScopedAdvisoryLocker.LockGeneratorWorkerusingqueries.AdvisoryLockWithKey.w.store.GetAdvisoryLocker(w.ctx), deferRelease, and callLockGeneratorWorker()before fetching nodes and iterating.📍Where to Start
Start with the
payerreport.workers.GeneratorWorker.GenerateReportsmethod in generator.go, then review the lock kind and locker methods in advisory_lock.go.📊 Macroscope summarized 07f4943. 2 files reviewed, 3 issues evaluated, 3 issues filtered, 0 comments posted
🗂️ Filtered Issues
pkg/db/advisory_lock.go — 0 comments posted, 1 evaluated, 1 filtered
TransactionScopedAdvisoryLocker.Release()always callstx.Rollback()even on successful paths. While this releases a transaction-scoped advisory lock, if any writes are accidentally performed within the same transaction in future changes, they would be silently discarded. Given the current code confines the transaction to advisory lock acquisition, this works, but it couples correctness to a fragile assumption. Consider constraining the transaction strictly to advisory lock acquisition (and avoid using it for any other operations) or using a connection-level/session-level advisory lock to decouple from transaction semantics. At minimum, document that the transaction must not be used for any writes. [ Low confidence ]pkg/payerreport/workers/generator.go — 0 comments posted, 2 evaluated, 2 filtered
GetAdvisoryLockerandLockGeneratorWorker, and only released at function end via deferredRelease()(rollback). This keeps a DB connection checked out for the entire duration ofregistry.GetNodes()and the loop overallNodescallingmaybeGenerateReport. If these operations are slow or the node count is large, it can starve the DB connection pool and block other operations, causing timeouts or deadlocks. Advisory locks that are transaction-scoped should be held for the minimal critical section necessary to make a decision; otherwise, use a dedicated session-scoped advisory lock on a separate connection or restructure to acquire/release around a shorter critical section. [ Low confidence ]Release()are ignored inGenerateReports(defer func(){ _ = haLock.Release() }()). If the rollback fails (e.g., connection error) the transaction might not be closed cleanly, potentially leaking resources or leaving the lock state uncertain. At minimum, log the error; ideally, ensure the transaction is deterministically closed and the error is surfaced or handled. Whilesql.Tx.Rollback()commonly returnssql.ErrTxDoneif already completed, ignoring all errors obscures real failures. [ Low confidence ]