Skip to content

Commit 5faec91

Browse files
committed
Bound writer residency and seek wallet freshness by canonical order
1 parent aa9761f commit 5faec91

4 files changed

Lines changed: 38 additions & 12 deletions

File tree

docs/PUBLIC_API.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -263,9 +263,9 @@ responses distinguish complete collected-fee totals from partial evidence:
263263
`episode_selection: "last_activity_within_window"` and
264264
`financial_scope: "lifetime_of_selected_episodes"`. Do not treat these
265265
values as cash flows earned exclusively during the requested window.
266-
- Owner-list `financials.through_order` is the canonical
267-
`[block_number, transaction_index, log_index]` boundary captured in the same
268-
WAL snapshot as the financial aggregates. `financials.as_of` describes that
266+
- Owner-list `financials.through_order` contains the canonical `block_number`,
267+
`tx_index`, and `log_index` boundary captured in the same WAL snapshot as the
268+
financial aggregates. `financials.as_of` describes that
269269
boundary, not the time of the latest observed activity. Pending projection
270270
work or later activity keeps `financials.pending` true without advancing the
271271
captured boundary. A completed snapshot is distinct from complete history,

docs/RPC_OPERATIONS.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,19 @@ SQLite's variable limit. This avoids handing the Python interpreter to competing
7070
valuation workers between every inserted row. The outer durable transaction
7171
preserves the raw event/cursor/job boundary.
7272

73+
Adaptive scan sizing targets 50 ms of writer residency, half the observed
74+
100 ms block interval. Growth is capped by measured store throughput as well as
75+
log density, and history starts with eight blocks before adapting. This is a
76+
feedback target, not a hard transaction deadline; indivisible block work can
77+
exceed it. Multi-second history commits previously starved both the live lane
78+
and financial workers.
79+
80+
Wallet freshness reads walk the canonical event-order index after checking
81+
whether the requested scope is empty. A timestamp-range plan sorted the entire
82+
recent ledger before returning its newest event and exceeded 30 seconds on the
83+
production snapshot; the ordered lookup returned the same boundary in under
84+
0.25 seconds including process startup.
85+
7386
The CLI caps Python's thread-switch interval at 1 ms before starting workers,
7487
preserving an already-shorter interval. This reduces interpreter handoff delays
7588
when SQLite releases the GIL during ingestion while valuation threads run.

src/rhpools/lp_market_accounting.py

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3690,13 +3690,20 @@ def _scoped_owner_financial_state(
36903690
" WHERE " + " AND ".join(event_clauses)
36913691
if event_clauses else ""
36923692
)
3693-
through = conn.execute(
3694-
"SELECT e.block_number,e.tx_index,e.log_index,e.timestamp "
3695-
"FROM events e" + event_where
3696-
+ " ORDER BY e.block_number DESC,e.tx_index DESC,"
3697-
"e.log_index DESC LIMIT 1",
3698-
event_args,
3699-
).fetchone()
3693+
through = None
3694+
# A window lookup must not sort the entire recent ledger to find its
3695+
# newest event. Check empty scopes before walking the ordered index.
3696+
if not event_clauses or conn.execute(
3697+
"SELECT 1 FROM events e" + event_where + " LIMIT 1", event_args,
3698+
).fetchone() is not None:
3699+
order_index = "" if pool_id else " INDEXED BY events_block_idx"
3700+
through = conn.execute(
3701+
"SELECT e.block_number,e.tx_index,e.log_index,e.timestamp "
3702+
"FROM events e" + order_index + event_where
3703+
+ " ORDER BY e.block_number DESC,e.tx_index DESC,"
3704+
"e.log_index DESC LIMIT 1",
3705+
event_args,
3706+
).fetchone()
37003707
through_order = (
37013708
{
37023709
"block_number": int(through["block_number"]),

src/rhpools/lp_market_index.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,11 @@
5959
LIVE_MAX_CHUNK = 2_048
6060
RECENT_CATCHUP_PRIORITY_BLOCKS = 512
6161
HISTORY_MIN_CHUNK = 1
62-
HISTORY_INITIAL_CHUNK = 4_096
62+
HISTORY_INITIAL_CHUNK = 8
6363
HISTORY_MAX_CHUNK = 32_768
64-
MAX_INTERVAL_STORE_SECONDS = 2.0
64+
# Target half the chain's observed ~100 ms block interval, not multi-second
65+
# writer monopolies that stall live ingestion and every financial worker.
66+
MAX_INTERVAL_STORE_SECONDS = 0.05
6567
ENRICH_BATCH = 8
6668
ENRICHMENT_CAPABILITY_RECHECK_S = 300.0
6769
REPROJECT_BATCH = 128
@@ -3544,6 +3546,10 @@ def _resize_after_success(
35443546
current * 2,
35453547
sample_blocks * (MAX_LOGS_PER_RESPONSE * 4 // 5) // count,
35463548
)
3549+
if store_seconds > 0:
3550+
candidate = min(candidate, max(
3551+
minimum, int(sample_blocks * MAX_INTERVAL_STORE_SECONDS / store_seconds),
3552+
))
35473553
if candidate <= current:
35483554
return
35493555
resized = min(maximum, max(current + 1, candidate))

0 commit comments

Comments
 (0)