Skip to content

Conversation

@mostronator
Copy link
Collaborator

@mostronator mostronator commented Feb 12, 2026

Summary

Prevents the stale real-hash cleanup from repeatedly querying LND and logging confirmation messages for orders that have already been verified as paid.

Closes #585

Problem

The stale real-hash cleanup in job_process_dev_fee_payment() runs every 60s and queries all orders with dev_fee_paid = 1 and a real payment hash. For already-paid orders, check_dev_fee_payment_status() would:

  1. Query LND via TrackPaymentV2 → Succeeded
  2. Set dev_fee_paid = true (already true — no-op)
  3. Log ✅ Order ... dev fee payment confirmed via LN status check

Nothing changed in the order to exclude it from the next cycle, causing infinite repetition.

Solution

Track confirmed order IDs in an in-memory HashSet<Uuid>. Each order is checked at most once per daemon lifetime:

  • First check after startup: queries LND, confirms status (crash recovery) ✅
  • Subsequent cycles: skips confirmed orders via HashSet lookup ✅
  • Daemon restart: HashSet is empty, all orders re-checked once ✅
  • Normal payment flow: newly paid orders are also added to the set ✅

Changes

  • src/scheduler.rs: Add confirmed_dev_fee_orders: HashSet<Uuid> to track verified orders
    • Skip cleanup check for orders already in the set
    • Insert order ID after LND confirms Succeeded (both cleanup and normal flow)

Summary by CodeRabbit

  • Refactor
    • Improved dev-fee processing to skip redundant verification for payments already confirmed during the current daemon session, reducing repeated checks and improving runtime efficiency.
    • Retains crash-recovery behavior and existing TTL-based cleanup so confirmations are revalidated after restarts and stale entries are purged.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 12, 2026

Warning

Rate limit exceeded

@mostronator has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 20 minutes and 40 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

Walkthrough

Adds an in-memory confirmed_dev_fee_orders HashSet in the scheduler to track dev-fee orders confirmed during the current daemon session; scheduler skips LN status checks for orders present in the set and inserts order IDs when confirmation is observed.

Changes

Cohort / File(s) Summary
In-memory dev-fee confirmation tracking
src/scheduler.rs
Adds std::collections::HashSet and confirmed_dev_fee_orders to cache confirmed dev-fee order IDs for the session; skips processing for IDs in the set and inserts IDs when a dev-fee payment is verified (via LN status or DB verification).

Sequence Diagram(s)

sequenceDiagram
participant Scheduler
participant DB
participant LND
Scheduler->>DB: Query candidate orders (stale/real-hash)
loop per order
    alt order_id in confirmed_dev_fee_orders
        Scheduler-->>Scheduler: Skip LN check
    else
        Scheduler->>LND: check_dev_fee_payment_status(order_id)
        alt LND reports Succeeded
            LND-->>Scheduler: Succeeded
            Scheduler->>DB: verify/update order as paid
            Scheduler-->>Scheduler: confirmed_dev_fee_orders.add(order_id)
        else
            LND-->>Scheduler: Not yet/Failed
            Scheduler->>DB: handle pending/stale logic
        end
    end
end
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Possibly related PRs

Poem

🐰 I found a set, small and neat,

Remembering fees with nimble feet.
Once confirmed, I skip the chase,
No more logs all over the place —
A hop, a grin, session saved with grace.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change—preventing redundant LND queries for confirmed dev fee payments—which is the core fix in the changeset.
Linked Issues check ✅ Passed The PR fully implements the objectives from issue #585: introduces an in-memory HashSet to track confirmed orders, skips cleanup checks for confirmed entries, and inserts order IDs upon LND-confirmed success.
Out of Scope Changes check ✅ Passed All changes remain focused on preventing redundant LND queries for confirmed dev fee payments; no unrelated modifications are present.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/stale-cleanup-redundant-checks

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@src/scheduler.rs`:
- Around line 558-563: The comment and the following let binding are
misformatted for rustfmt; update the declaration of confirmed_dev_fee_orders so
it is formatted as a single rustfmt-friendly line (e.g., put the full type and
initializer on one line or align the type/initializer per rustfmt conventions)
and then run cargo fmt. Locate the variable confirmed_dev_fee_orders and its
HashSet type (std::collections::HashSet<uuid::Uuid>) and adjust spacing/line
breaks (or add a local use for std::collections::HashSet and shorten the
declaration) so rustfmt no longer reports differences, then re-run CI.
🧹 Nitpick comments (2)
src/scheduler.rs (2)

722-744: Recovery path doesn't add to confirmed_dev_fee_orders, causing one extra LND round-trip.

When an order is recovered here (has a payment hash but dev_fee_paid=false), it gets marked as paid but isn't inserted into the set. On the next cycle it will match the real-hash query (Line 659) and trigger an LND TrackPaymentV2 call before finally being added to the set. Consider inserting the order ID here too.

Proposed fix
                             Ok(_) => {
                                 info!(
                                     "✅ Recovered order {} - marked as paid with existing hash",
                                     order_id
                                 );
+                                confirmed_dev_fee_orders.insert(order_id);
                                 // Verify recovery

562-563: confirmed_dev_fee_orders grows without bound over the daemon lifetime.

Every confirmed order is inserted but never removed. For a long-running daemon this is an unbounded (albeit slow) memory growth. If the daemon processes a high volume of orders over weeks/months, consider periodically clearing the set or switching to an LRU cache with a reasonable capacity.

@mostronator mostronator force-pushed the fix/stale-cleanup-redundant-checks branch from 9ee126c to cd13bb9 Compare February 12, 2026 14:19
The stale real-hash cleanup runs every scheduler cycle and queries all orders
with dev_fee_paid=true and a real payment hash. For orders where the payment
already succeeded, check_dev_fee_payment_status() would query LND, confirm
success, and log the confirmation — but nothing changed in the order to
exclude it from the next cycle's query. This caused:

1. Redundant LND TrackPaymentV2 queries every 60s for every paid order
2. Repeated '✅ Order ... dev fee payment confirmed' log messages
3. Unnecessary DB updates (setting dev_fee_paid=true when already true)

Fix: Track confirmed order IDs in an in-memory HashSet so each order is
only checked once per daemon lifetime. On daemon restart, the set is empty
and all orders get re-checked once (preserving crash recovery behavior).
Orders confirmed via the normal payment flow are also added to the set.

Closes #585
@mostronator mostronator force-pushed the fix/stale-cleanup-redundant-checks branch from cd13bb9 to b4954f9 Compare February 12, 2026 14:25
@grunch grunch merged commit 473d1cd into main Feb 12, 2026
6 checks passed
@grunch grunch deleted the fix/stale-cleanup-redundant-checks branch February 12, 2026 14:30
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.

Stale real-hash cleanup repeatedly logs confirmed payments every scheduler cycle

2 participants