train_track
Core framework crate for Railscale. Defines all protocol-agnostic traits and the generic Pipeline orchestrator.
Module Layout
src/
lib.rs — re-exports
error.rs — RailscaleError enum
sampler.rs — metrics-full request sampling
atom/
frame.rs — Frame trait, ParsedData enum
parser.rs — FrameParser trait
core/
pipeline.rs — FramePipeline trait
service.rs — Service trait, Pipeline struct, OtelMetrics
io/
source.rs — StreamSource trait
destination.rs — StreamDestination trait
router.rs — DestinationRouter trait
destinations/
file.rs — FileDestination (BufWriter-based)
multi.rs — MultiDestination wrapper
route.rs — MatchStrategy, MatchingRouter
Core Traits
Frame
pub trait Frame: Send + Sized + Sync {
fn as_bytes(&self) -> &[u8];
fn into_bytes(self) -> Bytes;
fn routing_key(&self) -> Option<&[u8]>;
}FrameParser
pub trait FrameParser<R: AsyncRead + Unpin + Send>: Send {
type Frame: Frame;
type Error: Into<RailscaleError>;
fn parse(self, reader: R) -> impl Stream<Item = Result<ParsedData<Self::Frame>, Self::Error>> + Send;
}FramePipeline
pub trait FramePipeline: Send + Sync {
type Frame: Frame;
fn process(&self, frame: Self::Frame) -> Self::Frame;
}StreamSource
pub trait StreamSource: Send {
type ReadHalf: AsyncRead + Unpin + Send;
type WriteHalf: AsyncWrite + Unpin + Send;
fn accept(&self) -> impl Future<Output = Result<(Self::ReadHalf, Self::WriteHalf), impl Into<RailscaleError>>> + Send;
}StreamDestination
pub trait StreamDestination: Send {
type Error: Into<RailscaleError>;
async fn write(&mut self, bytes: Bytes) -> Result<(), Self::Error>;
async fn relay_response<W: AsyncWrite + Send + Unpin>(&mut self, client: &mut W) -> Result<u64, Self::Error>;
}DestinationRouter
pub trait DestinationRouter: Send + Sync {
type Destination: StreamDestination;
async fn route(&self, routing_key: &[u8]) -> Result<Self::Destination, RailscaleError>;
}Pipeline Orchestrator
Pipeline<Src, Par, Pip, Rtr> ties everything together:
source: Src— accepts connectionsparser_factory: fn() -> Par— creates a parser per connectionpipeline: Arc<Pip>— shared frame processorrouter: Arc<Rtr>— shared destination router
See Railscale Connection Lifecycle for the full do_connection flow.
Routing
MatchStrategy provides SIMD-accelerated domain matching:
Exact— full domain matchSuffix— e.g.,.example.comPrefix— e.g.,api.Contains— substring viamemmem::Finder
MatchingRouter<D> chains strategies with factory functions, implementing DestinationRouter.