pub struct FlowLedger { /* private fields */ }Expand description
The live half: the counters every transfer path bumps.
Cheap to clone through an Arc. A record is: one read lock, one hash
lookup, a handful of relaxed fetch_adds, and one BTreeSet insert per
session. Nothing on that path allocates once the namespace has a slot, and a
slot is made once per namespace per process.
Implementations§
Source§impl FlowLedger
impl FlowLedger
Sourcepub fn new(store: FlowStore) -> FlowLedger
pub fn new(store: FlowStore) -> FlowLedger
Open the ledger over a control store.
Sourcepub fn observe(&self, observer: FlowObserver)
pub fn observe(&self, observer: FlowObserver)
Tell observer the name of every namespace whose flow moves — a
recorded transfer, a refusal, an auth failure. Replaces any earlier
observer. Called on the transfer path, so it must be cheap: the
server’s usage ledger inserts the name into a set and returns.
Sourcepub fn store(&self) -> &FlowStore
pub fn store(&self) -> &FlowStore
The kept half, for the readers that want a series rather than today.
Sourcepub fn record(&self, namespace: &str, at_unix_ms: i64, transfer: &Transfer)
pub fn record(&self, namespace: &str, at_unix_ms: i64, transfer: &Transfer)
The counting point for a finished transfer. One call, one day.
Sourcepub fn refuse(&self, namespace: &str, at_unix_ms: i64, reason: Refusal)
pub fn refuse(&self, namespace: &str, at_unix_ms: i64, reason: Refusal)
The counting point for a refusal. No bytes moved; the tenant met a door.
Sourcepub fn auth_failure(&self, namespace: &str, at_unix_ms: i64)
pub fn auth_failure(&self, namespace: &str, at_unix_ms: i64)
The counting point for a principal with no grant here. See the module doc for the half that is not counted.
Sourcepub fn today(&self, namespace: &str, now_unix_ms: i64) -> Option<FlowDay>
pub fn today(&self, namespace: &str, now_unix_ms: i64) -> Option<FlowDay>
Today’s live figure for one namespace, whether or not it has been flushed. Read straight off the atomics — the store is not consulted, because the slot holds the whole day and the stored row is a copy of it.
None when this process has not seen the namespace today AND the store
holds no row for it: nothing happened, which is a fact and not a gap.
Sourcepub fn glance(&self, namespace: &str, now_unix_ms: i64) -> Glance
pub fn glance(&self, namespace: &str, now_unix_ms: i64) -> Glance
What Usage.Read puts beside the stock meters: today’s flow, and
when the namespace was last seen over the WHOLE kept window.
The two halves answer different questions and must not be folded into one. How much moved today is a rate; when did anything last move is what an operator reads to decide a tenant has gone quiet, and a tenant who has done nothing for six weeks has a today of zeroes and a last-seen six weeks ago. Reading the second out of the first is exactly the mistake this pair exists to prevent.
Sourcepub fn fleet(&self, now_unix_ms: i64, silent_after_days: i64) -> Fleet
pub fn fleet(&self, now_unix_ms: i64, silent_after_days: i64) -> Fleet
The whole box’s flow, folded — what moved today across every namespace, and how many tenants have gone quiet.
O(namespaces), and it reads the control document. It is for the dashboard band and for an operator’s fleet view, NEVER for a transfer: the flush tick computes it once a minute and the screen reads the result, because the dashboard’s own two-second tick is documented as reading a few atomics and nothing else.
silent_after_days is the caller’s policy, not this module’s. Fourteen
days is what the console uses; a different deployment may reasonably
call a tenant quiet sooner, and a constant here would make that a fork.
Sourcepub fn flush(&self, now_unix_ms: i64) -> Result<usize>
pub fn flush(&self, now_unix_ms: i64) -> Result<usize>
Copy every live slot into the store, and drop what has aged out.
The flush. Runs on a tick; touches redb once for the whole batch. It COPIES rather than adds, so running it twice in a row writes the same rows twice rather than doubling them — which is what makes it safe to run it again on shutdown, and safe for a restart to seed from it.
Returns how many rows it wrote, for the caller’s log line.
Sourcepub fn moved(
&self,
namespace: &str,
now_unix_ms: i64,
days: u32,
) -> Vec<(i64, u64)>
pub fn moved( &self, namespace: &str, now_unix_ms: i64, days: u32, ) -> Vec<(i64, u64)>
Bytes moved — in plus out — per UTC day, over the last days days,
today included: (day, bytes) for each day that moved anything,
oldest first. The durable half of admission’s usage: edda_admit’s
table SEEDS a namespace from this once, on first sight, and is the
cache from then on — so this is read once per namespace per process,
never per transfer (it takes the ledger’s locks and reads the store).
Wire bytes only. LFS bytes are already inside them (see
FlowDay::lfs_bytes_in), so adding the LFS pair would count one
transfer twice.
- today is the live slot, read off its atomics;
- the closed days are the store’s rows, plus any closed day still parked for the flush — a parked row is the FINAL figure for its day and replaces the store’s last-tick copy of it, never adds to it.
A slot still holding yesterday is rolled first, so a read just after midnight does not take yesterday’s live bytes for today’s.
Sourcepub fn window_bytes(&self, namespace: &str, now_unix_ms: i64, days: u32) -> u64
pub fn window_bytes(&self, namespace: &str, now_unix_ms: i64, days: u32) -> u64
FlowLedger::moved, summed: bytes in + out over the window.