Skip to content

SAIF.NetCore.Clients.UC4 architecture

SAIF.NetCore.Clients.UC4 is an implementation-layer library (per Architecture.md) that provides a single, thin outbound REST client for scheduling jobs against the UC4/Automic job-scheduling system's "UC4 Core API," wrapping IHttpJsonClient and IEnvironmentClient from SAIF.NetCore.ServiceContracts with no other SAIF package dependency.

Responsibilities

  • Validate at construction time that the two required uc4coreapi environment settings (url, schedulejobroute) exist.
  • Lazily configure the injected IHttpJsonClient with the UC4 Core API base URL and caller-identity headers on the first ScheduleJob call.
  • Issue a single outbound POST to the UC4 Core API's schedule-job route, appending the caller-supplied job name to the configured route.
  • Return the raw IHttpRequestResult to the caller unchanged, leaving success/failure interpretation and response parsing to the consumer.

Component boundaries

  • IUC4Client (namespace SAIF.NetCore.Clients.UC4): the public contract, exposing only ScheduleJob(string appname, string jobname).
  • UC4Client (namespace SAIF.NetCore.Clients.UC4.Services): the sole implementation, owning settings validation, lazy client initialization (Init), and the outbound POST.
  • Constants (internal): owns the uc4coreapi setting-group and key names (url, schedulejobroute).
  • The library has no DI registration extension method; consumers register IUC4Client/UC4Client by hand, and no other library in this repository registers it on their behalf*.

Interaction model

  • A consumer constructs UC4Client (directly, or via manual DI registration) supplying IEnvironmentClient and IHttpJsonClient; the constructor eagerly validates the two uc4coreapi settings exist and reads their values, throwing NotSupportedException if either key is missing.
  • On the first ScheduleJob call, UC4Client.Init configures the injected IHttpJsonClient with the base URL and identity headers (Client-User, Client-Name, Application-ID); this configuration is fixed for the lifetime of the UC4Client instance and is not re-applied on later calls, even with a different appname*.
  • Each ScheduleJob call POSTs an empty JSON object ({}), with no job parameters, to {ScheduleJobEndpoint}{jobname} through IHttpJsonClient, which applies its own default retry policy (401/502/503, up to 3 retries) before returning the result.
  • IEnvironmentClient and IHttpJsonClient are resolved from the DI container by the consumer; this library has no compile-time dependency on their concrete implementations (SAIF.NetCore.EnvironmentClient, SAIF.NetCore.HttpClients), which the consumer typically obtains via SAIF.NetCore.ServiceExtensions*.

Architecture diagram

The following diagram shows this library's single NuGet dependency on SAIF.NetCore.ServiceContracts, the runtime services a consumer must supply, and the outbound call to the external UC4 Core API.

flowchart TD
    SC["SAIF.NetCore.ServiceContracts<br>(IEnvironmentClient, IHttpJsonClient,<br>IHttpRequestResult)"]
    UC4["SAIF.NetCore.Clients.UC4<br>IUC4Client / UC4Client"]
    ENV["SAIF.NetCore.EnvironmentClient<br>(IEnvironmentClient impl)"]
    HTTP["SAIF.NetCore.HttpClients<br>(IHttpJsonClient impl)"]
    UC4API["UC4 Core API<br>(external job scheduler)"]
    APP["Consuming application"]

    UC4 -.->|NuGet ref| SC
    APP -->|constructs / resolves| UC4
    UC4 -->|DI-resolved by consumer| ENV
    UC4 -->|DI-resolved by consumer| HTTP
    UC4 -->|POST schedule-job route| UC4API

Sequence diagram

The following diagram shows the primary request sequence for scheduling a UC4 job, including the first-call lazy initialization.

sequenceDiagram
    participant App as Consuming application
    participant UC4Client
    participant EnvironmentClient as "IEnvironmentClient"
    participant HttpJsonClient as "IHttpJsonClient"
    participant UC4API as "UC4 Core API"

    App->>UC4Client: new UC4Client(env, httpJsonClient)
    UC4Client->>EnvironmentClient: HasSetting / GetSettingValue(uc4coreapi.url, schedulejobroute)
    EnvironmentClient-->>UC4Client: ServiceUrl, ScheduleJobEndpoint
    App->>UC4Client: ScheduleJob(appname, jobname)
    alt first call (IsConfigured == false)
        UC4Client->>HttpJsonClient: SetClientInfo(ServiceUrl, ClientName, MachineName, appname)
    end
    UC4Client->>HttpJsonClient: PostAsync(ScheduleJobEndpoint + jobname, {})
    HttpJsonClient->>UC4API: POST schedule-job route
    UC4API-->>HttpJsonClient: HTTP response
    HttpJsonClient-->>UC4Client: IHttpRequestResult
    UC4Client-->>App: IHttpRequestResult

Design constraints

  • The library takes no NuGet dependency on any other SAIF implementation library — only on SAIF.NetCore.ServiceContracts — consistent with the repo-wide rule that implementation libraries depend solely on the foundation layer.
  • IsConfigured has a public setter; a caller that sets it true before the first ScheduleJob call skips Init entirely, which fails later with ClientNotInitializedException from HttpJsonClient unless the injected client was configured elsewhere*.
  • Client identity (appname) is fixed from the first successful call for the life of the instance; later calls with a different appname silently reuse the first value (BR-UC4-06).
  • The schedule-job POST is retried automatically by HttpJsonClient on 401/502/503 — standard HttpJsonClient defaults, changeable by a host that calls SetOptions, though UC4 itself never calls SetOptions; whether a retry after an already-accepted job can result in duplicate job submissions depends on whether the UC4 Core API's schedule endpoint is idempotent, which is unknown**.
  • UC4 itself calls no authentication method (no NTLM, Basic, or bearer token) and does not clear or override the injected IHttpJsonClient's authenticator; HttpJsonClient.CreateClient assigns client.Authenticator = _authenticator, preserving whatever authenticator the host configured on that instance — null if the host configured none, or a working authenticator (demonstrably capable of carrying credentials) if it did. Only informational, caller-asserted headers (Client-Name, Application-ID, Client-User) are added by UC4 itself.
  • There is no DI registration extension method shipped with this library; registration is entirely manual for every consumer.

Note: Statements marked with * were inferred from code structure, naming conventions, or contextual evidence where direct confirmation was not available in source artifacts. Statements marked with ** could not be confirmed; treat as unknown until verified.

Sources

  • src/SAIF.NetCore.Clients.UC4/SAIF.NetCore.Clients.UC4/SAIF.NetCore.Clients.UC4/SAIF.NetCore.Clients.UC4.csproj
  • src/SAIF.NetCore.Clients.UC4/SAIF.NetCore.Clients.UC4/SAIF.NetCore.Clients.UC4/Constants.cs
  • src/SAIF.NetCore.Clients.UC4/SAIF.NetCore.Clients.UC4/SAIF.NetCore.Clients.UC4/IUC4Client.cs
  • src/SAIF.NetCore.Clients.UC4/SAIF.NetCore.Clients.UC4/SAIF.NetCore.Clients.UC4/Services/UC4Client.cs
  • src/SAIF.NetCore.HttpClients/SAIF.NetCore.HttpClients/SAIF.NetCore.HttpClients/HttpJsonClient/HttpJsonClient.cs — declares the retry policy and CreateClient's client.Authenticator = _authenticator assignment described in Design constraints.
  • src/SAIF.NetCore.ServiceContracts/SAIF.NetCore.ServiceContracts/SAIF.NetCore.ServiceContracts/HttpClientOptions.cs — declares the default RetryOnStatusCodes set.
  • Architecture.md