Skip to content

Lock Postgres stores on initialization - #1012

Open
benthecarman wants to merge 1 commit into
lightningdevkit:mainfrom
benthecarman:postgres-init-advisory-lock
Open

Lock Postgres stores on initialization#1012
benthecarman wants to merge 1 commit into
lightningdevkit:mainfrom
benthecarman:postgres-init-advisory-lock

Conversation

@benthecarman

Copy link
Copy Markdown
Contributor

If we aren't going to get #1000 in before the release, we can add a simple lock on the postgres using its native pg_try_advisory_lock.

Prevent multiple nodes from opening the same PostgreSQL database table at once while allowing separate database and table pairs to coexist. Retain the session-scoped advisory lock for the store lifetime.

@ldk-reviews-bot

ldk-reviews-bot commented Aug 3, 2026

Copy link
Copy Markdown

👋 Thanks for assigning @tnull as a reviewer!
I'll wait for their review and will help manage the review process.
Once they submit their review, I'll check if a second reviewer would be helpful.

Comment thread src/io/postgres_store/mod.rs Outdated
pool: SmallPool,
// PostgreSQL advisory locks are session-scoped, so keep the connection that acquired our lock
// alive for the lifetime of the store.
_lock_client: ClientConnection,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] Fail closed when the lock session disconnects

This client is retained but never monitored. If its PostgreSQL session ends, the advisory lock is released while the independent pool can reconnect and continue serving operations. A second store can then acquire the lock while this store resumes writing. Please treat lock-session loss as terminal before any further operation, or otherwise reacquire and validate ownership without allowing stale writes. A regression test should terminate this backend, start a replacement store, and verify that the original store cannot operate.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we go ahead with advisory locks for now, maybe some form of monitoring can be added?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah if we're going with this, will add it so we attempt to reacquire the lock if it drops

Comment thread src/io/postgres_store/mod.rs
@tnull

tnull commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

@joostjager Mind sharing again why you think this PR is not sufficient for a first stopgap measure for v0.8/LDK Server v0.1?

From a first impression it looks like the kind of minimally invasive thing we want to land right now, before we can then take time to discuss the right approach / review #1000 etc.

@joostjager

Copy link
Copy Markdown
Contributor

The reason it is not sufficient is above in #1012 (comment). Maybe there are other edge cases that can happen with a connection-level lock.

If it is not possible to get the safer fix in and postgres must be included in the release, the advisory lock is of course better than no lock.

@tnull tnull added this to the 0.8 milestone Aug 7, 2026
@tnull

tnull commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator

Let's move forward with this minimalistic approach for v0.8, and do the more thorough #1000 in the v0.9 release cycle.

Comment thread src/builder.rs Outdated
///
/// The given `kv_table_name` will be used or default to
/// [`DEFAULT_KV_TABLE_NAME`](io::postgres_store::DEFAULT_KV_TABLE_NAME).
/// Building fails if another PostgreSQL-backed node using the same database and table is still

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's make these docs a more explicit warning that it's generally discouraged and considered unsafe to point multiple instances towards the same backend. It should be clear that it's the users responsibility to avoid this for now, while we do have some stop gaps in place.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@benthecarman
benthecarman force-pushed the postgres-init-advisory-lock branch from c5e7bab to 270a7d9 Compare August 7, 2026 09:13
@benthecarman

Copy link
Copy Markdown
Contributor Author

Added it so it'll reacquire the lock if we lose it.

@joostjager

Copy link
Copy Markdown
Contributor

Do we already need to think how we can upgrade from this intermediary solution later?

Comment thread src/io/postgres_store/mod.rs Outdated
self.reacquire_store_lock(&mut lock_client).await
}

async fn reacquire_store_lock(&self, lock_client: &mut ClientConnection) -> io::Result<()> {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The whole concept of reacquire sounds unsafe. If the node continued running with it's in-memory state, and another instance had the lock in the mean time and wrote data, we have a problem? #1000 hard-exits in this case, and a process restart can reload the latest state then.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed so we panic on loss of the lock

Prevent multiple nodes from opening the same PostgreSQL database
table at once while allowing separate database and table pairs to
coexist. Retain the session-scoped advisory lock for the store
lifetime, if we lose the lock, panic to prevent mismatched states.

This change was created with OpenAI Codex.
@benthecarman
benthecarman force-pushed the postgres-init-advisory-lock branch from 270a7d9 to 6271185 Compare August 7, 2026 19:27
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.

4 participants