Skip to content

TraxSharp/Trax.Mediator

Repository files navigation

Trax.Mediator

Build NuGet Version NuGet Downloads .NET License: MIT Last Commit codecov Docs

Dispatch station for Trax trains. Hand it the cargo and it routes it to the right train, no need to know which train handles what.

The Trax Stack

Trax is a layered framework split across several repos. You can stop at whatever layer solves your problem. You are here: Trax.Mediator.

Repo Adds
Trax.Core Pipelines, junctions, railway error propagation
Trax.Effect Execution logging, DI, pluggable storage
Trax.Mediator Decoupled dispatch via TrainBus
Trax.Scheduler Cron schedules, retries, dead-letter queues
Trax.Api GraphQL API for remote access
Trax.Dashboard Blazor monitoring UI
Trax.Cli trax-cli project scaffolding tool
Trax.Samples Sample apps and a dotnet new template

Full documentation: traxsharp.net/docs.

The Problem

When one part of your system needs to send a train, it has to know exactly which train class to use. Controllers depend on concrete train types, stops that trigger other trains need direct references, and everything gets coupled together.

With TrainBus

TrainBus is a dispatch station. At startup it builds a map of what cargo goes on which train. To send something, you just drop off the cargo:

public class OrderController(ITrainBus trainBus) : ControllerBase
{
    [HttpPost]
    public async Task<IActionResult> Create(OrderRequest request)
    {
        var receipt = await trainBus.RunAsync<OrderReceipt>(request);
        return Ok(receipt);
    }
}

No reference to ProcessOrderTrain. The dispatch station looks at the cargo type and sends it on the right train.

Installation

dotnet add package Trax.Mediator

Trax.Mediator depends on Trax.Effect, which depends on Trax.Core. Both are pulled in transitively.

Setup

Register your train assemblies during startup. The dispatch station scans them for all IServiceTrain<TIn, TOut> implementations and builds the cargo-to-train map automatically:

builder.Services.AddTrax(trax =>
    trax.AddEffects(effects => effects.UsePostgres(connectionString))
        .AddMediator(typeof(Program).Assembly)
);

Multiple assemblies:

builder.Services.AddTrax(trax =>
    trax.AddEffects(effects => effects.UsePostgres(connectionString))
        .AddMediator(
            typeof(Program).Assembly,
            typeof(SomeTrainInAnotherProject).Assembly
        )
);

That's it. Every IServiceTrain<TIn, TOut> in those assemblies is now dispatchable through ITrainBus.

Usage

Dispatching a train

// With a return value: send cargo, get a delivery back
var user = await trainBus.RunAsync<User>(new CreateUserRequest
{
    Email = "[email protected]",
    Name = "Jane"
});

// One-way: send cargo, no delivery expected
await trainBus.RunAsync(new SendNotificationRequest { UserId = userId });

Cancellation

var receipt = await trainBus.RunAsync<OrderReceipt>(request, cancellationToken);

The cancellation signal is forwarded to the train and all its stops.

Nested trains

A stop can dispatch another train mid-journey. Pass the current Metadata to establish a parent-child relationship between the journeys:

public class SendWelcomeEmailJunction(ITrainBus trainBus) : Junction<User, Unit>
{
    public override async Task<Unit> Run(User input)
    {
        await trainBus.RunAsync(new SendEmailRequest
        {
            To = input.Email,
            Template = "welcome"
        });

        return Unit.Default;
    }
}

The departure board

The dispatch station exposes a registry of all known trains, which is useful for tooling and dashboards:

public class TrainListEndpoint(ITrainRegistry registry)
{
    public IEnumerable<string> GetTrainNames()
        => registry.InputTypeToTrain.Values.Select(t => t.Name);
}

How It Works

At startup, AddMediator scans the provided assemblies for types implementing IServiceTrain<TIn, TOut>. It builds a dictionary from cargo type (input) to train type and registers each train in the DI container. When you call RunAsync<TOut>(input), the dispatch station looks up input.GetType(), resolves the matching train from DI, and sends it on its way.

Next Layer

When you need recurring background jobs with retries and dead-lettering, move up to Trax.Scheduler.

License

MIT

Trademark & Brand Notice

Trax is an open-source .NET framework provided by TraxSharp. This project is an independent community effort and is not affiliated with, sponsored by, or endorsed by the Utah Transit Authority, Trax Retail, or any other entity using the "Trax" name in other industries.

About

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages