IDataContext
Trax's own data context: an EF Core context over the trax tables (runs, logs, manifests, the work queue, dead letters and the rest), and the effect provider that persists a train's metadata. UsePostgres, UseSqlite and UseInMemory each register an implementation.
Inject it to read Trax's tables, or to make a write commit with an enqueue through IEnqueueContextAccessor. Your own tables belong in a domain data context, not here.
Signature
namespace Trax.Effect.Data.Services.DataContext;
public interface IDataContext : IEffectProvider, IAsyncDisposable // IEffectProvider is IDisposable
{
DbSet<Metadata> Metadatas { get; }
DbSet<Log> Logs { get; }
DbSet<Manifest> Manifests { get; }
DbSet<ManifestGroup> ManifestGroups { get; }
DbSet<WorkQueue> WorkQueues { get; }
DbSet<DeadLetter> DeadLetters { get; }
DbSet<BackgroundJob> BackgroundJobs { get; }
DbSet<SchedulerConfig> SchedulerConfigs { get; }
DbSet<PersistedOperation> PersistedOperations { get; }
DbSet<PersistedOperationHistory> PersistedOperationHistories { get; }
DbSet<RunnerNonce> RunnerNonces { get; }
DbSet<SnapshotDraft> SnapshotDrafts { get; }
DbSet<EffectClaim> EffectClaims { get; }
int Changes { get; set; }
Task<IDataContextTransaction> BeginTransaction();
Task<IDataContextTransaction> BeginTransaction(CancellationToken cancellationToken);
Task<IDataContextTransaction> BeginTransaction(IsolationLevel isolationLevel);
Task<IDataContextTransaction> BeginTransaction(IsolationLevel isolationLevel, CancellationToken cancellationToken);
Task CommitTransaction();
Task RollbackTransaction();
void Reset();
DataContext<TDbContext> Raw<TDbContext>() where TDbContext : DbContext;
}
namespace Trax.Effect.Data.Services.DataContextTransaction;
public interface IDataContextTransaction : IDisposable
{
Task Commit();
Task Rollback();
}From IEffectProvider it also has Track(IModel), Update(IModel) and SaveChanges(CancellationToken), which the effect runner uses to persist a run.
Tables
| Property | Table | Holds |
|---|---|---|
Metadatas | trax.metadata | One row per train run: state, input, output, timing, failure |
Logs | trax.log | Log entries written by AddDataContextLogging |
Manifests | trax.manifest | Scheduled jobs: train, input properties, schedule |
ManifestGroups | trax.manifest_group | Groups of manifests that share dispatch settings |
WorkQueues | trax.work_queue | Runs waiting to be dispatched |
DeadLetters | trax.dead_letter | Manifests that exhausted their retries |
BackgroundJobs | trax.background_job | Dispatched runs waiting for, or held by, a worker; only in-flight work |
SchedulerConfigs | trax.scheduler_config | The persisted, dashboard-editable scheduler settings; zero or one row |
PersistedOperations, PersistedOperationHistories | trax.persisted_operation, trax.persisted_operation_history | Persisted GraphQL operations and their audit history |
RunnerNonces | trax.runner_nonce | Nonces a runner accepted on signed requests |
SnapshotDrafts | trax.snapshot_draft | State-machine drafts, one per user and draft id |
EffectClaims | trax.effect_claim | Exactly-once state-machine effect intents |
RunnerNonces, SnapshotDrafts and EffectClaims have default implementations on the interface, so an implementation written before they existed still loads.
Members
| Member | Description |
|---|---|
BeginTransaction(...) | Starts a transaction, optionally at an isolation level. Returns an IDataContextTransaction to commit, roll back or dispose. |
CommitTransaction() / RollbackTransaction() | Commits or rolls back the context's current transaction |
Reset() | Clears the change tracker, so a long-lived context stops tracking what it loaded |
Changes | A count of tracked changes not yet saved |
Raw<TDbContext>() | Casts to the concrete DataContext<TDbContext>, for EF members the interface does not surface. Throws InvalidCastException when the implementation is not that type. |
Getting one
| How | Lifetime | Use |
|---|---|---|
Inject IDataContext | Scoped: one per scope, created from the provider's context factory | Reads and writes inside a request or a train's scope |
Inject IDataContextProviderFactory and call CreateDbContextAsync(ct) | A new context per call; dispose it | Background services and anything outside a scope |
Example
using Microsoft.EntityFrameworkCore;
using Trax.Effect.Data.Services.DataContext;
using Trax.Effect.Enums;
public class FailedRunReport(IDataContext data)
{
public Task<List<string>> TrainsFailingSince(DateTime sinceUtc, CancellationToken ct) =>
data.Metadatas.AsNoTracking()
.Where(m => m.TrainState == TrainState.Failed && m.EndTime > sinceUtc)
.Select(m => m.Name)
.Distinct()
.ToListAsync(ct);
}Treat the trax tables as read-only from application code. Trax's services write them, and a row changed behind their back (a run's state, a work queue entry's status) can break the scheduler's invariants.
Package
dotnet add package Trax.Effect.DataA data provider package (Trax.Effect.Data.Postgres, Trax.Effect.Data.Sqlite or Trax.Effect.Data.InMemory) brings it in.