Skip to content

Construct and configure the client

This operation builds a ConnectionClient instance, caches its two injected dependencies, and resolves the DBConnectionAPI service URL, the three engine endpoint segments, and the outbound client-identity headers before the instance is handed to a caller.

Field Value
Operation ID OP-DBC-01
Trigger DI factory in ServiceExtensions.RegisterDBConnectionClient (singleton lifetime), or a direct new ConnectionClient(IHttpJsonClient httpJsonClient, IEnvironmentClient envClient) call
Inputs IHttpJsonClient httpJsonClient, IEnvironmentClient envClient
Outputs A configured ConnectionClient instance
Primary components ConnectionClient constructor, ConnectionClient.Setup
Entry point src/SAIF.NetCore.DbConnectionClient/SAIF.NetCore.DBConnectionClient/SAIF.NetCore.DBConnectionClient/ConnectionClient.cs

Steps

  1. Initialize the empty connection cache _connections and store the two injected dependencies (IHttpJsonClient, IEnvironmentClient).
  2. Call the virtual Setup() method.
  3. Read ServiceUrl from configuration key DBConnectionClient:ServiceUrl via the injected IEnvironmentClient.GetSettingValue(key, section) contract (BR-DBC-01).
  4. 3.1. Build a dictionary key from section/configKey and load the DBConnectionClient section into the settings cache if it has not already been loaded. When the standard BaseEnvironmentClient implementation is registered, loading a section first calls CheckForUpdates, which reloads the whole settings cache only when a periodic timestamp probe (throttled to once per TimeToWaitSeconds, 60 seconds by default) determines the remote EnvironmentAPI's LastRefreshed is newer than the local value, or unconditionally when the local cache is still empty — it is not an unconditional reload on every call once the standard refresh interval has elapsed. That reload clears the cached settings dictionary but preserves the set of already-loaded section names, then reloads each of them in turn; an exception partway through that per-section reload loop can leave a not-yet-reloaded section still marked loaded with no data behind it until a later refresh succeeds.
  5. 3.2. If the DBConnectionClient section is not yet loaded, the standard implementation issues one request to the EnvironmentAPI for it and classifies the result: a null result, an unsuccessful response, or a successful response with no settings collection at all throws EnvironmentClientException, which propagates out of this operation uncaught; a successful response with zero individual settings is not an error, but it stores nothing and leaves the section unmarked (or removes it if it had previously been marked loaded), so the next call retries the load; only a successful, nonempty result both upserts the returned settings into the cache and marks the section name as loaded.
  6. 3.3. Look the key up in the loaded settings and return its value, or an empty string if the key is not found. For the standard BaseEnvironmentClient implementation, a configured developer-settings-override file is checked first and takes precedence over the loaded dictionary; falling through to the dictionary and then to an empty string on a miss means that implementation does not throw for a missing key — this is a property of that registered implementation, not a universal guarantee of the IEnvironmentClient contract itself.

Origin: Steps 3.1–3.3 are implemented in Load section and Get setting value (SAIF.NetCore.EnvironmentClient, BaseEnvironmentClient.CheckForUpdates/LoadSection/HandleGetConfigurationSettingsResults/GetSettingFromDictionary) when the host registers the standard BaseEnvironmentClient/SecureEnvironmentClient implementation, and executed on behalf of this operation. A differently registered IEnvironmentClient implementation can resolve the value differently. 4. Read SqlConnectionEndpoint, PostgreSqlConnectionEndpoint, and OracleConnectionEndpoint from the same DBConnectionClient section (BR-DBC-01). - No null/empty validation is performed — missing values flow unchecked into URL paths built later. 5. Configure the HTTP client's identity: SetClientInfo(ServiceUrl, "DBConnectionClient", EnvClient.ApplicationHost, EnvClient.ApplicationName), which sets the base URL plus Client-User, Client-Name, and Application-Id headers (BR-DBC-02). - 5.1. This library (ConnectionClient.Setup) itself constructs neither a Uri nor a ClientInfo; it only calls IHttpJsonClient.SetClientInfo with the four string arguments. When the standard HttpJsonClient implementation is registered, that call first constructs and assigns a new ClientInfo from the three identity arguments — throwing immediately on a null identity argument — and only after that succeeds constructs and assigns a new Uri from ServiceUrl, throwing immediately on an invalid ServiceUrl; the two assignments are not atomic, so a failing ServiceUrl can still leave the newly constructed ClientInfo applied to the instance.

Origin: Step 5.1 is implemented in Initialize client (SAIF.NetCore.HttpClients) when the standard HttpJsonClient implementation is registered, and executed on behalf of this operation. 6. Enable NTLM authentication using the current process identity: SetNtlmAuthentication() with no arguments (BR-DBC-03). - 6.1. This library calls only IHttpJsonClient.SetNtlmAuthentication() with no arguments; when the standard HttpJsonClient implementation is registered, that call builds a parameterless NtlmAuthenticator (current process identity) and stores it on the client instance as _authenticator. The stored authenticator is only assigned to a RestClient later, inside CreateClient, each time that implementation builds a new RestClient for an outbound request — not at the time SetNtlmAuthentication is called. A differently registered IHttpJsonClient implementation is not required to construct an NtlmAuthenticator or assign it the same way.

Origin: Step 6.1 is implemented in Configure authentication (SAIF.NetCore.HttpClients) when the standard HttpJsonClient implementation is registered, and executed on behalf of this operation. - On failure: any exception raised by the environment client or HTTP client during steps 3–6 propagates out of the constructor uncaught; there is no error handling in Setup.

Process flow

flowchart TD
    Start([Constructor invoked]) --> Init[Initialize cache and store dependencies]
    Init --> Setup[Call Setup]
    Setup --> ReadUrl["Read ServiceUrl, endpoint segments"]
    ReadUrl --> ClientInfo["SetClientInfo: base URL + identity headers"]
    ClientInfo --> Ntlm["SetNtlmAuthentication: current process identity"]
    Ntlm --> Done([Configured instance ready])

Failure and edge-case behavior

  • Any exception thrown by IEnvironmentClient or IHttpJsonClient during Setup() propagates out of the constructor; the caller receives a failed construction, not a partially configured instance.
  • Because Setup() is virtual and called from the constructor, a subclass override runs before the subclass's own constructor body completes*.

Note: Statements marked with * were inferred from code structure, naming conventions, or contextual evidence where direct confirmation was not available in source artifacts.

Sources

  • src/SAIF.NetCore.DbConnectionClient/SAIF.NetCore.DBConnectionClient/SAIF.NetCore.DBConnectionClient/ConnectionClient.cs
  • src/SAIF.NetCore.EnvironmentClient/SAIF.NetCore.EnvironmentClient/SAIF.NetCore.EnvironmentClient/BaseEnvironmentClient.cs (CheckForUpdates, LoadSection, HandleGetConfigurationSettingsResults, GetSettingFromDictionary — collaborator detail reached when the standard IEnvironmentClient implementation is registered)
  • src/SAIF.NetCore.HttpClients/SAIF.NetCore.HttpClients/SAIF.NetCore.HttpClients/HttpJsonClient/HttpJsonClient.cs (SetClientInfo, SetNtlmAuthentication, CreateClient — collaborator detail reached when the standard IHttpJsonClient implementation is registered)