Skip to content

Operations and processes

This library performs 5 distinct operations spanning the anonymous ping request itself, the default per-target ping pipeline, registration-time DI wiring, controller discovery, and failure reporting.

Operation catalog

ID Operation Primary component Business rules
OP-01 Ping the API PingableController.Get BR-01, BR-02, BR-03, BR-04, BR-05, BR-06, BR-09
OP-02 Run the default ping pipeline for one target IPingableService.PingAsync BR-07, BR-08, BR-09
OP-03 Register a pingable service IServiceCollectionExtensions.AddPingable* BR-11, BR-15
OP-04 Enable the ping route and discover pingable controllers MvcBuilderExtensions.WithPingableController, ControllerRetriever BR-03, BR-13, BR-14
OP-05 Raise a ping failure PingServiceException constructor BR-10

Process flow diagram

The following diagram traces a single GET /Ping request from the host's MVC pipeline through target resolution, concurrent pinging, and failure reporting.

flowchart TD
    A[GET /Ping request] --> B[Construct PingableController - OP-01 step 1]
    B --> C[Default guid if absent]
    C --> D[Resolve DI-registered IPingableService targets]
    D --> E["Discover + resolve pingable controllers - OP-04"]
    E --> F[Start all PingAsync concurrently - OP-02]
    F --> G{Task.WhenAll}
    G -->|all awaited tasks succeed| H[Return 200 OK with guid]
    G -->|faulted or canceled| I[Flatten/wrap failure into PingServiceException - OP-05]
    I --> J[Throw 500 PingServiceException]
    J --> K["DynamicErrorHandler -> IErrorHandler formats response,<br>if registered"]

Failure and edge-case behavior

  • Any constructor or dependency-resolution failure for a pingable service or controller is treated as a ping failure and surfaces as a 500 (BR-05).
  • IPingableService.PingAsync's default implementation lets an implementer veto a failure via IsThrowablePingError, converting what would otherwise be a failing ping into a successful one (BR-08); an OnPingFailure or IsThrowablePingError override that itself throws replaces the original Ping exception with its own, and an OnPingSuccess override that throws can fault the task even after a clean or swallowed Ping — see OP-02.
  • WithPingableController() is the supported convenience path for enabling the /Ping route and controller discovery together; without it (or an equivalent explicit application-part and IControllerRetriever registration), /Ping is not routed at all (BR-13).
  • Pingable controllers are resolved from DI by concrete type, so the controller-discovery channel additionally requires the host to call AddControllersAsServices() (or an equivalent explicit registration) only when such controllers exist; otherwise GetService(type) returns null and the resulting NullReferenceException surfaces as a 500 (BR-14).
  • A faulted Task.WhenAll (one or more awaited pings failed), a canceled Task.WhenAll (rethrown when whenAll.Exception is null), and a synchronous resolution/reflection failure are three distinct failure paths, not one — see OP-01 steps 6–7.
  • Converting a thrown PingServiceException into a formatted HTTP 500 response depends on the host having DynamicErrorHandler (and its injected IErrorHandler) registered, which BaseApiStartup-derived hosts do by default; without it, ASP.NET Core's default unhandled-exception handling still yields a 500, but without SAIF formatting.

Sources

  • src/SAIF.NetCore.PingableService/SAIF.NetCore.PingableService/Controllers/PingableController.cs
  • src/SAIF.NetCore.PingableService/SAIF.NetCore.PingableService/IPingableService.cs
  • src/SAIF.NetCore.PingableService/SAIF.NetCore.PingableService/Extensions/IServiceCollectionExtensions.cs
  • src/SAIF.NetCore.PingableService/SAIF.NetCore.PingableService/Extensions/MvcBuilderExtensions.cs
  • src/SAIF.NetCore.PingableService/SAIF.NetCore.PingableService/Services/ControllerRetriever.cs
  • src/SAIF.NetCore.PingableService/SAIF.NetCore.PingableService/Exceptions/PingServiceException.cs
  • src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/Middleware/DynamicErrorHandler.cs
  • src/SAIF.NetCore.ErrorHandler/SAIF.NetCore.ErrorHandler/SAIF.NetCore.ErrorHandler/ErrorHandler.cs