Henara.Grpc.Client.DakotaSlim 2.1.0

Henara.Grpc.Client.DakotaSlim

Slim Dakota gRPC client for a native host that owns its own Keycloak login + session (written for the SmartVO Windows client). It adapts the host's access token onto the Dakota clients — it has no interactive login and no token refresh of its own. The host's session manager stays the single token authority.

The host must perform the interactive login before any Dakota call, on its UI thread, so a session exists by the time the clients are used. The per-RPC token resolver only reads/refreshes that session — it must not try to log in, because it runs inside the gRPC call-credentials interceptor on a background thread where opening the host's WPF login window throws. See Registration.

Do not also call AddNativeKeycloakAuth (from Henara.Grpc.Client.Common). That starts a second refresh-token rotation against the same Keycloak session and the two invalidate each other (invalid_grant). AddSlimNativeDakotaClient enforces this — it throws at registration if any ICallTokenProvider or native Keycloak provider is already registered.

Endpoints

Two environment variables, read and validated at registration (throws if missing):

Variable Value
URL_DAKOTA_PIPELINE Dakota pipeline gateway gRPC URL
URL_DAKOTA_REPORTER Dakota reporting gRPC URL

http:// targets are served as plaintext h2c (call credentials are still attached); use https:// in production.

Registration

services.AddSlimNativeDakotaClient((sp, ct) => /* return a valid raw access token, no "Bearer " prefix */);

The callback is invoked per RPC and must return a valid (auto-refreshed) access token, doing no UI work. In SmartVO it resolves ISessionManager and reads its current token:

services.AddSlimNativeDakotaClient((sp, ct) =>
    sp.GetRequiredService<ISessionManager>().GetValidAccessTokenAsync(ct));

GetValidAccessTokenAsync only reads/refreshes an existing session and throws "Not signed in." when Current is null. So the host must sign in once, on its UI thread, before the first Dakota call, which establishes Current:

var tokens = await keycloakAuthService.LoginAsync(ct);
await sessionManager.ConsumeNewLoginToken(tokens, ct);

Do not call LoginAsync/ConsumeNewLoginToken from inside the resolver: the resolver runs in the gRPC call-credentials interceptor on a background thread, and opening the WPF login/PIN windows there throws.

This registers two clients — IDakotaGatewayClient (pipeline) and IDakotaReporterClient (reporting). Inject them wherever you need them.

Pipeline — IDakotaGatewayClient

Submits Dakota processing jobs and queries retry state.

IAsyncEnumerable<DakotaDispatchResult> DispatchDakotaProcess(
    List<DakotaPairRequest> pairs, CancellationToken ct = default);

Task<Result<bool, Failure>> IsPipelineStepRetryDispatched(Guid tickerId);

DispatchDakotaProcess streams one ESOL/AUF file pair per DakotaPairRequest and yields one result per pair. The intake gate authorises each pair by the sender (praxis) IK carried in the file; a rejected pair returns IsDispatched == false with a Message.

var pairs = new List<DakotaPairRequest>
{
    new(
        FilePair:           new FileRequestInfoDto(esolBytes, aufBytes, "file.con"),
        CustomerId:         20131386,
        Channel:            ChannelTypeEnum.Production,
        IsEsolPreprocessed: false,
        OverwriteRecipient: null)
};

await foreach (var r in gateway.DispatchDakotaProcess(pairs, ct))
    Console.WriteLine(r.IsDispatched
        ? $"dispatched {r.FileName} -> {r.PipelineId}"
        : $"rejected {r.FileName}: {r.Message}");

IsPipelineStepRetryDispatched returns true if a retry is already queued for a step ticker; otherwise a Failure.

Reporting — IDakotaReporterClient

Reads process statuses and files. The server scopes all results to the signed-in user's customer id(s); Henara admins see everything.

IAsyncEnumerable<DakotaProcessInfoDto> GetDakotaStati(DakotaFilter? filter = null);

Task<(IReadOnlyList<DakotaFileRowDto> Rows, long Total)> GetFilesPaged(int page, int pageSize, string search);

IAsyncEnumerable<SingleIlFileInfoDto> DownloadFiles(List<(int oid, DownloadFileTypeEnum type)> filesToDownload);
  • GetDakotaStati — streams process-status aggregates. The DakotaFilter (all members optional) narrows by customer id, receiver IK, time range, pipeline step, status, or file name; null returns everything the caller may see.
  • GetFilesPaged — server-paged, searchable file list; search matches file name / receiver IK (empty matches all). Returns the page rows and the total count.
  • DownloadFiles — streams raw file contents for the given object ids. Dakota file types are DownloadFileTypeEnum.DakotaEsol and DakotaAuf.
var filter = new DakotaFilter { CustomerId = new MatchesIntFilterDto(20131386) };
await foreach (var p in reporter.GetDakotaStati(filter))
    Console.WriteLine($"{p.CreatedAt:o} {p.ReceiverIk} {p.FileName}");

var (rows, total) = await reporter.GetFilesPaged(page: 0, pageSize: 100, search: "");

var ids = rows.Select(r => (r.DataOid, DownloadFileTypeEnum.DakotaEsol)).ToList();
await foreach (var f in reporter.DownloadFiles(ids))
    await File.WriteAllBytesAsync(f.FileName, f.FileData, ct);

DTO reference

Type Shape
DakotaPairRequest (FileRequestInfoDto FilePair, int CustomerId, ChannelTypeEnum Channel, bool IsEsolPreprocessed, string? OverwriteRecipient)
FileRequestInfoDto (byte[] EsolFile, byte[] AufFile, string FileName)
ChannelTypeEnum Test, Staging, Production
DakotaDispatchResult (bool IsDispatched, Guid? PipelineId, string FileName, string? Message)
DakotaProcessInfoDto ProcessId, CustomerId, FileName, ReceiverIk, CreatedAt, EsolFileId/AufFileId, FileVersions, per-step Stages
DakotaFileRowDto (int DataOid, DateTimeOffset CreatedAt, string FileName, string FileType, Guid ProcessId, string ReceiverIk, int Step)
SingleIlFileInfoDto (Guid ProcessId, byte[] FileData, string FileType, string FileName, int Oid)
DownloadFileTypeEnum DakotaEsol, DakotaAuf (plus IlResult, IlVerordnung — not Dakota)

Identity

Setting Value
Keycloak realm henara @ https://auth.praxx.me
Client id henara-main-sso

No packages depend on Henara.Grpc.Client.DakotaSlim.

.NET 10.0

Version Downloads Last updated
2.2.0 122 07/13/2026
2.1.0 3 07/09/2026
2.0.0 2 07/05/2026
1.3.0 2 06/25/2026
1.2.0 0 06/25/2026
1.1.0 0 06/25/2026
1.0.0 2 06/25/2026