Skip to main content

FlowLedger

Struct FlowLedger 

Source
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

Source

pub fn new(store: FlowStore) -> FlowLedger

Open the ledger over a control store.

Source

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.

Source

pub fn store(&self) -> &FlowStore

The kept half, for the readers that want a series rather than today.

Source

pub fn record(&self, namespace: &str, at_unix_ms: i64, transfer: &Transfer)

The counting point for a finished transfer. One call, one day.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

pub fn window_bytes(&self, namespace: &str, now_unix_ms: i64, days: u32) -> u64

FlowLedger::moved, summed: bytes in + out over the window.

Source

pub fn forget(&self, namespace: &str) -> Result<bool>

Drop a namespace’s live slot and its whole kept series. The flow half of deleting a namespace.

Trait Implementations§

Source§

impl Debug for FlowLedger

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<'a, T, E> AsTaggedExplicit<'a, E> for T
where T: 'a,

Source§

fn explicit(self, class: Class, tag: u32) -> TaggedParser<'a, Explicit, Self, E>

Source§

impl<'a, T, E> AsTaggedImplicit<'a, E> for T
where T: 'a,

Source§

fn implicit( self, class: Class, constructed: bool, tag: u32, ) -> TaggedParser<'a, Implicit, Self, E>

Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more