TaskHub.Shared

Networking

The Networking layer standardizes how TaskHub services call each other (and external HTTP APIs). It enforces resilience, observability, and declarative configuration β€” services declare who they want to talk to in appsettings.json, not how.

🎯 Design Goals

  1. Resilience by default. Every named client gets retry, timeout, and circuit breaker policies via Polly β€” no service ships a raw HttpClient.
  2. Configuration over code. Endpoints, timeouts, retry counts, and user agents live in appsettings.json. Code stays clean.
  3. Observable. Outgoing HTTP is traced (OpenTelemetry HttpClient instrumentation) and tagged with the target service name.
  4. Auth-aware. Bearer tokens are forwarded automatically through a DelegatingHandler, so internal calls preserve the caller’s identity.

πŸ“¦ Modules

Module Purpose
Networking Abstractions IClient marker, ClientBase, settings models β€” what every client implements.
Networking Implementation Polly-backed AppHttpClient, BearerTokenHandler, options resolution, DI registration.

🧭 The Mental Model

A Client is a typed wrapper around a named HttpClient for one downstream service:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  IUsersClient (your code)              β”‚
β”‚    └─► HttpClient "Users"              β”‚
β”‚           β”œβ”€ BaseUrl: https://users:7006β”‚
β”‚           β”œβ”€ Retry Γ— 3 (exponential)   β”‚
β”‚           β”œβ”€ Timeout: 750 ms           β”‚
β”‚           β”œβ”€ BearerTokenHandler        β”‚
β”‚           └─ OTel HttpClient tracing   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

The implementation module reads Networking:Services:Users:BaseUrl from config and merges it with Networking:Defaults (retry count, timeout, etc.) to produce effective options per client.

βš™οΈ Minimal Configuration

"Networking": {
  "Defaults": {
    "RetryCount": 3,
    "TimeoutInMilliseconds": 750,
    "RetryDelayInMilliseconds": 500,
    "RetryStrategy": "Exponential",
    "UserAgent": "task-service/1.0"
  },
  "Services": {
    "Users": { "BaseUrl": "https://users:7006" },
    "Plans": { "BaseUrl": "https://plans:7005" }
  }
}

Services-specific overrides nest inside each service: "Users": { "BaseUrl": "...", "TimeoutInMilliseconds": 2000 }.

βœ… When to Use What

You want to… Use
Call another TaskHub service Define IFooClient : IClient, implement against ClientBase
Call an external REST API Same pattern β€” register the BaseUrl, get retry+timeout for free
Call something raw (no resilience) Resolve IHttpClientFactory directly β€” but justify it

πŸ”— See Also