Skip to main content

FileBroker

Struct FileBroker 

Source
pub struct FileBroker { /* private fields */ }
Expand description

A log kept in one .ss stream file for the RustStream messaging framework: it survives restarts, replays what it recorded, and needs no server.

new is synchronous and records only the path; the file opens in the consuming Broker::connect, which creates it when it is missing. The file transport builds on Unix systems only, an upstream constraint of the file client.

A publish appends the message under its stream key and flushes it, so the bytes reach the operating system before the call returns; the file is synced to the device at shutdown. The file client caps a stream file at 16 GiB: a publish that reaches the cap fails, and every later publish to that file fails too. Brokers opened on one path in one process share the file’s writer: once one of them shuts down, a publish through another fails with SeaFileError::Publish carrying the client’s ProducerEnded.

The FileBroker page shows it in a service.

§Examples

use ruststream_sea_file::file::prelude::*;
use serde::Deserialize;

#[derive(Debug, Deserialize)]
struct Order {
    id: u64,
}

#[subscriber(FileStream::new("orders"), start_at(FilePosition::beginning()))]
async fn handle(order: &Order) -> HandlerOutcome {
    tracing::info!(order.id, "accepted");
    HandlerOutcome::ack()
}

#[ruststream::app]
fn app() -> impl App {
    RustStream::new(AppInfo::new("orders", "0.1.0"))
        .with_broker(FileBroker::new("/var/lib/orders.ss").end_with_eos(), |b| {
            b.include(handle);
        })
}

A test runs the app main runs. With the testing feature, TestApp::start connects this broker to a stream file held in memory, and the test addresses it by its production type:

use std::error::Error;

use ruststream::testing::TestApp;
use ruststream_sea_file::file::prelude::*;
use serde::{Deserialize, Serialize};

#[derive(Debug, Deserialize, Serialize, Outgoing, PartialEq)]
#[outgoing(name = "orders")]
pub struct Order {
    pub id: u64,
}

#[derive(Debug, Deserialize, Serialize, Outgoing, PartialEq)]
#[outgoing(name = "receipts")]
pub struct Receipt {
    pub order: u64,
}

#[subscriber(FileStream::new("orders"), reply)]
async fn confirm(order: &Order) -> Receipt {
    Receipt { order: order.id }
}

/// The app `main` runs.
pub fn app() -> impl App {
    RustStream::new(AppInfo::new("orders", "0.1.0"))
        .with_broker(FileBroker::new("/var/lib/orders.ss"), |b| {
            b.include(confirm);
        })
}

pub async fn confirms_an_order() -> Result<(), Box<dyn Error>> {
    let tb = TestApp::start(app()).await?;

    // The publish returns once the handler it woke has settled.
    tb.broker::<FileBroker>()
        .message(&Order { id: 1 })
        .publish()
        .await?;

    tb.broker::<FileBroker>()
        .subscriber("orders")
        .assert_called(1)
        .with(&Order { id: 1 });
    tb.broker::<FileBroker>()
        .published::<Receipt>("receipts")
        .assert_called(1)
        .with(&Receipt { order: 1 });

    tb.shutdown().await?;
    Ok(())
}

Implementations§

Source§

impl FileBroker

Source

pub fn new(path: impl Into<String>) -> Self

Records the path of the stream file (created on connect when missing). No I/O.

Source

pub fn existing_only(self) -> Self

Requires the file to exist instead of creating it on connect.

Source

pub fn end_with_eos(self) -> Self

Writes an end-of-stream mark when the broker shuts down, marking the file finished.

A subscription that tails the file reads the mark and ends there, which is the only thing that ends a live subscription. A replay completes at the mark, or at the end of the file when there is none, after delivering every message before it.

Source

pub fn beacon_interval(self, bytes: u32) -> Self

The interval of the file’s in-place index (must be a positive multiple of 1024); denser beacons make seeking finer-grained at the cost of file size.

Source

pub fn publisher(&self) -> FilePublisher

A publisher sharing this broker’s connection cell; buildable before connect.

Trait Implementations§

Source§

impl Broker for FileBroker

Source§

type Error = SeaFileError

The error type returned by broker-level operations.
Source§

type Connected = ConnectedFileBroker

The connected form of this broker: the typed witness that connect succeeded.
Source§

async fn connect(self) -> Result<Self::Connected, Self::Error>

Establishes the connection to the broker, consuming the unconnected form. Read more
Source§

fn bindable(self) -> Bindable<Self>
where Self: 'static,

Wraps the broker for publisher-token minting before registration: the returned Bindable hands out Bound tokens via its bind, and is itself what with_broker takes. Read more
Source§

impl Clone for FileBroker

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for FileBroker

Source§

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

Formats the value using the given formatter. Read more
Source§

impl DescribeServer for FileBroker

Source§

fn describe_server(&self) -> ServerSpec

Returns the server coordinates for this broker.
Source§

impl InProcess for FileBroker

Available on crate feature testing only.

The in-process mode: the connected form a test runs the production app against, over a stream file held in memory in place of the one at the path.

The file is new and empty, and every clone of this broker shares it, as clones share the file they connect. The settings are checked the way connect checks them, so a broker a service could not connect is not one a test can connect either: the path must form a file address, and the beacon interval must be a positive multiple of 1024. existing_only reads the in-memory file as the one the operator provisioned.

Source§

async fn connect_in_process(self) -> Result<Self::Connected, Self::Error>

Connects to the in-process transport, consuming the configuration. 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<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<B> BrokerRegistration for B
where B: Broker + 'static,

Source§

type Broker = B

The broker being registered.
Source§

fn into_parts(self) -> (B, Arc<Mutex<Option<Arc<<B as Broker>::Connected>>>>)

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DynClone for T
where T: Clone,

Source§

fn __clone_box(&self, _: Private) -> *mut ()

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> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> PublishedThrough<DefaultSlot> for T

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
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