Repository navigation
Transports NATS
Request and reply between services over NATS: one subject for each distributed key, and the options of the NATS client as they are.
dotnet add package FxMap.NatsEvery service that maps data needs the core FxMap package, and the owning service also needs a data provider. All FxMap.* packages must use the same version.
The same call is used on the service that needs data and on the service that owns it. NatsOpts gives you the options of the NATS client:
builder.Services.AddFxMap(cfg =>
{
cfg.AddEntitiesFromAssemblyContaining<SomeEntityAssemblyMarker>();
cfg.AddProfilesFromAssemblyContaining<SomeProfileAssemblyMarker>();
cfg.AddNats(c => c.NatsOpts(opts => opts.Url = "nats://localhost:4222"));
});cfg.AddNats(c =>
{
c.TopicPrefix("billing"); // optional, see Naming
c.NatsOpts(opts =>
{
opts.Url = "nats://localhost:4222";
opts.MaxReconnectRetry = 5;
opts.ConnectTimeout = TimeSpan.FromSeconds(5);
// ... any other property of FxNatsOpts
});
});FxNatsOpts exposes the properties of the NATS client options: Url, Name, AuthOpts, TlsOpts, MaxReconnectRetry, ReconnectWaitMin and ReconnectWaitMax, PingInterval, ConnectTimeout and more. Each starts with the default of the NATS client.
Credentials and TLS are the AuthOpts and TlsOpts of the NATS client. FxMap does not wrap them:
cfg.AddNats(c => c.NatsOpts(opts =>
{
opts.Url = "tls://nats.example.com:4222";
opts.AuthOpts = new NatsAuthOpts { Username = "svc-orders", Password = builder.Configuration["Nats:Password"] };
opts.TlsOpts = new NatsTlsOpts { Mode = TlsMode.Require };
}));The names and the values of these types belong to the NATS client library (NATS.Net): see its documentation for tokens, NKeys, credentials files and certificates.
Register the entities and a data provider as usual, and add NATS. The service subscribes to the subject of each distributed key it owns, and no endpoint is needed:
builder.Services.AddFxMap(cfg =>
{
cfg.AddEntitiesFromAssemblyContaining<UserConfig>();
cfg.AddNats(c => c.NatsOpts(opts => opts.Url = "nats://localhost:4222"));
})
.AddEntityFrameworkCore(c => c.AddDbContexts(typeof(UserDbContext)));- Each request holds the ids and the expressions for one distributed key and one level. A hundred objects that need a
UserNamemake one request. - The client sends it with the request and reply of NATS to the subject of the key, with the headers of the
IContextand the trace context. - The owner answers with the values, and with the expression errors it isolated (4.1.3+).
- If nobody answers within the request timeout (30 seconds by default,
cfg.SetRequestTimeOut(...)), the request fails. See Retry Policy to retry it.
FxMap uses one subject for each distributed key: fxmap-{namespace}-{type name}, in lower case, for example fxmap-myapp.contracts-userdistributedkey. With TopicPrefix("billing") the subject becomes billing-fxmap-{namespace}-{type name}, which keeps the services of two environments or two teams apart on one NATS server. Do not use these subjects for anything else.
// Shared contract
public sealed class UserDistributedKey : IDistributedKey;
// Owner (users service): the entity and how it is exposed
public class UserConfig : EntityConfigureOf<User>
{
protected override void Configure()
{
Id(x => x.Id);
DefaultProperty(x => x.Name);
UseDistributedKey<UserDistributedKey>();
}
}
// Client (orders service): the DTO and where its values come from
public class OrderResponse
{
public string Id { get; set; }
public string UserId { get; set; }
public string? UserName { get; set; }
public string? UserEmail { get; set; }
}
public class OrderResponseProfile : ProfileOf<OrderResponse>
{
protected override void Configure() =>
UseDistributedKey<UserDistributedKey>()
.Of(x => x.UserId)
.For(x => x.UserName)
.For(x => x.UserEmail, "Email");
}
// In an endpoint of the orders service
await distributedMapper.MapDataAsync(orders);The servers of the subjects run under the supervisor, which restarts a server that fails. Since 4.1.5 a server can be started again after it was stopped.
This is plain request and reply of NATS core, with no stream: a request that nobody answers ends at the timeout and is not stored. FxMap does not use JetStream.
A request sent in the few milliseconds after a server was stopped can reach its subscription before the NATS server has processed the unsubscribe, and nobody answers it: it ends at the request timeout. It matters only when a server is stopped and started again at once, as the supervisor does with OneForAll and RestForOne.
Source: https://fxmapper.net/docs/transports/nats/ — the website is always the most up to date version.
Introduction
Getting Started
Configuration
- Service Registration
- Entities & Profiles
- Handlers
- Pipelines
- Strongly Typed IDs
- Error Handling
- Retry Policy
- Supervisor
- Telemetry
- Kestrel (HTTP/2)
- Analyzers
Expressions
- Overview
- Property Access
- Filters, Sorting & Paging
- Functions
- Aggregations
- Projections
- Coalesce & Ternary
- GroupBy
Data Providers
Transports
Integrations
Quality
AI Assistants
Migration
Release Notes