OP-02: Run the default ping pipeline for one target¶
| Field | Value |
|---|---|
| Operation ID | OP-02 |
| Trigger | Invoked once per target from OP-01 step 5; implementers may also call PingAsync directly. |
| Inputs | guid (run id), logger (ISaifLogService, may be null). |
| Outputs | A Task that completes successfully, or faults. In the common case the fault carries the original exception thrown by Ping, but an IsThrowablePingError/OnPingFailure override that itself throws replaces it, and an OnPingSuccess override that throws can fault the task even when Ping succeeded or its failure was swallowed — see Failure and edge-case behavior below. |
| Primary components | IPingableService.PingAsync (default interface implementation) |
| Entry point | IPingableService.PingAsync |
Steps¶
- Inside
Task.Run, executePing(guid, logger); the default implementation is a no-op, and implementers re-implement it to test connectivity or other health signals (BR-07). If an implementer re-implementsPingAsyncitself instead ofPing, none of these steps apply.* - On exception, call
IsThrowablePingError(guid, ex, logger); the default returnstrue(BR-07). - If throwable, call
OnPingFailure(guid, ex, logger)(default no-op); providedOnPingFailurecompletes without itself throwing, thecatchblock's barethrow;then rethrows the original exception unchanged to fault the task (BR-07). IfOnPingFailureitself throws, that new exception propagates from within thecatchblock instead, andthrow;is never reached — the original exception is not rethrown at all.* - If not throwable, the exception is swallowed and execution falls through to step 5 (BR-08).
- Call
OnPingSuccess(guid, logger)(default no-op) — this runs both on a clean success and on a swallowed non-throwable failure (BR-08, BR-09).
Process flow¶
flowchart TD
A[PingAsync starts in Task.Run] --> B[Execute Ping - default no-op]
B --> C{Exception thrown?}
C -->|No| D[OnPingSuccess runs]
C -->|Yes| E[IsThrowablePingError classifies]
E --> F{Throwable?}
F -->|Yes| G["OnPingFailure runs, then rethrow - task faults"]
F -->|No| H[Exception swallowed]
H --> D
Failure and edge-case behavior¶
ISaifLogServiceis only ever passed through to the hooks; the library itself never calls a member on it, so anulllogger never causes a failure here.- An implementer that overrides
PingAsyncdirectly bypasses this entire pipeline, including theIsThrowablePingError/OnPingFailure/OnPingSuccesshook contract.* - The task does not necessarily fault with the original
Pingexception: ifIsThrowablePingErrororOnPingFailureitself throws, that new exception propagates instead of the original one, not in addition to it — thethrow;statement that would rethrow the original is never reached, so the original exception does not propagate at all once a hook (or the classifier) throws from within thecatchblock. Similarly,OnPingSuccessruns outside thetry/catchentirely, so an override that throws faults the task with that new exception even on a clean success or a swallowed non-throwable failure.
Related documentation¶
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.PingableService/SAIF.NetCore.PingableService/IPingableService.cs