Skip to content

Consolidate reconciliation recency maps into RecencyMap<K>#4386

Merged
cjdsellers merged 1 commit into
nautechsystems:developfrom
folknor:consolidate-reconciliation-recency-map
Jul 5, 2026
Merged

Consolidate reconciliation recency maps into RecencyMap<K>#4386
cjdsellers merged 1 commit into
nautechsystems:developfrom
folknor:consolidate-reconciliation-recency-map

Conversation

@folknor

@folknor folknor commented Jul 4, 2026

Copy link
Copy Markdown
Collaborator

Right now the monotonic-clock choice is a discipline, not a rule. Every one of
those four sites - ts_last_query, order_local_activity,
position_local_activity, recent_fills_cache - has to remember to stamp from
dst::time::Instant::now() and not self.clock, and to handle a future-marked
instant in the safe direction by hand.

So make it structural. RecencyMap<K> owns Instant::now() internally - you
mark(key), ask within(key, window), prune_older_than(ttl), and there is no
seam left to thread the wrong clock through.

The shape

struct RecencyMap<K> { inner: IndexMap<K, dst::time::Instant> }
mark / contains_key / remove / last_marked
within / within_at / elapsed / elapsed_at    // _at variants take the pass's `now`
prune_older_than

The _at variants exist so the reconciliation loop passes its loop-top now
once instead of resampling Instant::now() per order - the second half of that
same review note. Every checked_duration_since resolves a None
(marked-in-the-future) to the safe direction, matching what each original site
did by hand, so a garbage future instant reads as "0 elapsed, within window"
rather than panicking.

Renames

The ts_*-named fields you flagged in #4376 - ts_* repo-wide means a domain
UnixNanos, but these hold monotonic Instants, so the names lie:

  • InflightCheck::ts_submitted -> submitted_at
  • InflightCheck::last_query_ts -> last_query_at
  • the node scheduler's ts_last_* locals and ReconciliationCheckState fields
    -> last_*_check
  • ts_last_query -> order_query_recency (keyed on ClientOrderId, parallels
    order_local_activity; the other three map fields self-document under
    RecencyMap<K>, but this one's ts_ prefix did not survive the type change
    gracefully, so it got a real name too)

Tests

Focused RecencyMap unit tests: mark/contains/remove, monotonic expiry under
paused virtual time, pruning older-than-TTL, and the future-marked-instant safe
direction.

Still to come

The second promised follow-up - close the class: handle_missing_order's
venue-ts_last gate onto receipt time, plus the wider timer/throttle audit.

The live execution manager tracked four "mark now / within window? /
prune older than TTL" gates as bare IndexMap<K, dst::time::Instant>:
order_query_recency, order_local_activity, position_local_activity,
and recent_fills_cache. Every call site had to remember to stamp from
the monotonic dst::time clock rather than the trading self.clock, and
to handle a future-marked instant in the safe direction by hand.

Extract a RecencyMap<K> that owns dst::time::Instant::now() internally,
so the monotonic-clock choice becomes structural: a call site can no
longer reach for self.clock to build a recency gate. within/within_at,
elapsed/elapsed_at, and prune_older_than all resolve a None
checked_duration_since to the safe direction, matching each original
site. Migrate the four maps onto it.

Also apply the residual ts_*-named renames cjdsellers flagged in the
nautechsystems#4376 review, since ts_* repo-wide means a domain UnixNanos but these
hold monotonic instants: InflightCheck::ts_submitted -> submitted_at,
last_query_ts -> last_query_at, the node scheduler's ts_last_* locals
and state fields -> last_*_check, and the one map field whose ts_
prefix survived the type change, ts_last_query -> order_query_recency.

Add focused RecencyMap unit tests for mark/contains/remove, monotonic
expiry under paused time, pruning, and safe handling of a
future-marked instant.

Coded by an LLM.
@cjdsellers

Copy link
Copy Markdown
Member

Hi @folknor,

Thanks for the PR. I like the naming convention here: dropping the Hungarian-notation-esque domain ts_ component when the value is not a UnixNanos and does not represent a domain timestamp makes the clock axis much clearer. Names like submitted_at, last_query_at, and last_*_check read as real-time instants without implying domain time, while RecencyMap keeps the monotonic clock choice structural.

I traced the converted call sites and ran the focused recency, open-order query, inflight, fill-cache, and position-grace test slices. This looks good to me.

Will get to the next PR shortly!

@cjdsellers cjdsellers merged commit f52ad86 into nautechsystems:develop Jul 5, 2026
25 checks passed
@folknor folknor deleted the consolidate-reconciliation-recency-map branch July 5, 2026 09:00
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