Skip to content

Add non-atomic ordered batch write method to KVStore traits#4379

Draft
joostjager wants to merge 4 commits intolightningdevkit:mainfrom
joostjager:batch-write
Draft

Add non-atomic ordered batch write method to KVStore traits#4379
joostjager wants to merge 4 commits intolightningdevkit:mainfrom
joostjager:batch-write

Conversation

@joostjager
Copy link
Contributor

@joostjager joostjager commented Feb 4, 2026

Adds write_batch method to both KVStoreSync and KVStore traits with default implementations that delegate to the single write method.

  • BatchWriteEntry: struct containing namespace, key, and data
  • BatchWriteResult: returns successful write count and optional error
  • Writes execute sequentially in order; stops on first error
  • Existing implementations automatically inherit the default behavior

And show how it can be used in the background processor to write a complete batch.

Based on #4317

Update MonitorUpdatingPersister and MonitorUpdatingPersisterAsync to
queue persist operations in memory instead of writing immediately to
disk. The Persist trait methods now return ChannelMonitorUpdateStatus::
InProgress and the actual writes happen when flush() is called.

This fixes a race condition that could cause channel force closures:
previously, if the node crashed after writing channel monitors but
before writing the channel manager, the monitors would be ahead of
the manager on restart. By deferring monitor writes until after the
channel manager is persisted (via flush()), we ensure the manager is
always at least as up-to-date as the monitors.

The flush() method takes a count parameter specifying how many queued
writes to flush. The background processor captures the queue size
before persisting the channel manager, then flushes exactly that many
writes afterward. This prevents flushing monitor updates that arrived
after the manager state was captured.

Key changes:
- Add PendingWrite enum with FullMonitor and Update variants for queued writes
- Add pending_writes queue to MonitorUpdatingPersisterAsyncInner
- Add pending_write_count() and flush(count) to Persist trait and ChainMonitor
- ChainMonitor::flush() calls channel_monitor_updated for each completed write
- Stale update cleanup happens in flush() after full monitor is written
- Call flush() in background processor after channel manager persistence

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@ldk-reviews-bot
Copy link

👋 Hi! I see this is a draft PR.
I'll wait to assign reviewers until you mark it as ready for review.
Just convert it out of draft status when you're ready for review!

@codecov
Copy link

codecov bot commented Feb 4, 2026

Codecov Report

❌ Patch coverage is 0% with 67 lines in your changes missing coverage. Please review.
✅ Project coverage is 85.96%. Comparing base (f43803d) to head (3aa6003).

Files with missing lines Patch % Lines
lightning/src/util/persist.rs 0.00% 67 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4379      +/-   ##
==========================================
- Coverage   86.01%   85.96%   -0.06%     
==========================================
  Files         156      156              
  Lines      102857   102924      +67     
  Branches   102857   102924      +67     
==========================================
+ Hits        88474    88478       +4     
- Misses      11876    11936      +60     
- Partials     2507     2510       +3     
Flag Coverage Δ
tests 85.96% <0.00%> (-0.06%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

joostjager and others added 3 commits February 5, 2026 14:02
Adds `write_batch` method to both `KVStoreSync` and `KVStore` traits
with default implementations that delegate to the single `write` method.

- `BatchWriteEntry`: struct containing namespace, key, and data
- `BatchWriteResult`: returns successful write count and optional error
- Writes execute sequentially in order; stops on first error
- Existing implementations automatically inherit the default behavior

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Refactors flush() to batch all writes into a single write_batch() call
instead of individual write() calls. On partial failure, failed and
subsequent writes are re-queued at the front of the pending writes queue
for retry on the next flush.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Extends Persist::flush() to accept channel_manager_bytes, allowing the
channel manager to be written in the same write_batch() call as channel
monitors. The channel manager is always written first in the batch to
ensure proper ordering.

This removes the separate channel manager persistence from the background
processor and combines it with the monitor flush, reducing round trips.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
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.

2 participants