pub struct InventoryTracker<P: Producer> { /* private fields */ }Expand description
Emits inventory records for one shared resource.
§Hashing and sampling
InventoryTracker decides whether to emit a message for a given record based on the
configured sample_rate and a hash of the record ID passed in by the caller. A sample
rate of 1.0 means it will emit messages for 100% of records. A sample rate of 0.5
means it will emit messages for 50% of records. If a record is sampled out, no change
to that record will ever emit a message. If a record is included in the sample, every
change to that record will emit a message.
The hash is what InventoryTracker actually uses to populate the record_id message
field. Each message also includes the sample rate that was in effect at the time.
The hash is a permanent wire contract. Changing the algorithm, the byte ranges, or introducing a salt renames every record, and consumers will double-count until the old identifiers age out.
§Example
use objectstore_inventory_tracker::{InventoryTracker, NoopProducer};
use std::time::SystemTime;
let tracker = InventoryTracker::new(NoopProducer, "example_resource", 1.0);
tracker.write(
"example_feature/org.123/project.456/objects/abc",
"example_feature",
4096,
SystemTime::now(),
None,
Some(123),
Some(456),
)?;Implementations§
Source§impl<P: Producer> InventoryTracker<P>
impl<P: Producer> InventoryTracker<P>
Sourcepub fn new(
producer: P,
shared_resource_id: impl Into<String>,
sample_rate: f64,
) -> Self
pub fn new( producer: P, shared_resource_id: impl Into<String>, sample_rate: f64, ) -> Self
Creates a tracker emitting for shared_resource_id at sample_rate.
shared_resource_id is meant to match a label on a provisioned storage backend so
that downstream consumers can join the change stream dataset with, for instance,
billing info.
sample_rate is clamped to [0, 1]. A rate of 1.0 emits every record and
short-circuits the sampling check entirely. A rate of 0.0 emits no records.
The storage resource this tracker emits for.
Sourcepub fn sample_rate(&self) -> f64
pub fn sample_rate(&self) -> f64
The fraction of records being emitted.
Sourcepub fn write(
&self,
storage_key: &str,
app_feature: &str,
size: u64,
timestamp: SystemTime,
expiration_time: Option<SystemTime>,
organization_id: Option<u64>,
project_id: Option<u64>,
) -> Result<(), P::Error>
pub fn write( &self, storage_key: &str, app_feature: &str, size: u64, timestamp: SystemTime, expiration_time: Option<SystemTime>, organization_id: Option<u64>, project_id: Option<u64>, ) -> Result<(), P::Error>
Emits a WRITE: the record was created, or replaced with new contents.
Does nothing and returns Ok(()) if storage_key is not sampled.
Sourcepub fn update(
&self,
storage_key: &str,
app_feature: &str,
timestamp: SystemTime,
expiration_time: Option<SystemTime>,
organization_id: Option<u64>,
project_id: Option<u64>,
) -> Result<(), P::Error>
pub fn update( &self, storage_key: &str, app_feature: &str, timestamp: SystemTime, expiration_time: Option<SystemTime>, organization_id: Option<u64>, project_id: Option<u64>, ) -> Result<(), P::Error>
Emits an UPDATE: metadata changed but the stored size did not.
Does nothing and returns Ok(()) if storage_key is not sampled.
Sourcepub fn delete(
&self,
storage_key: &str,
app_feature: &str,
timestamp: SystemTime,
) -> Result<(), P::Error>
pub fn delete( &self, storage_key: &str, app_feature: &str, timestamp: SystemTime, ) -> Result<(), P::Error>
Emits a DELETE: the record is gone.
Does nothing and returns Ok(()) if storage_key is not sampled.
Sourcepub fn join(
&self,
timeout: Duration,
) -> impl Future<Output = Result<(), P::Error>> + Send + use<P>
pub fn join( &self, timeout: Duration, ) -> impl Future<Output = Result<(), P::Error>> + Send + use<P>
Waits for emitted records to be delivered, or until timeout elapses.
Call this during shutdown, within whatever budget the service allows for draining. Without it, records emitted moments before exit are still in a local queue and are lost with the process.