Observe the Connection State

Table of Contents

+#+filetags: :pattern:nats:diagnostics: +#+created: 2026-10-14 +#+updated: 2026-10-14 +#+pattern_group: diagnostics

This page defines the nats pattern Observe the Connection State in the NATS service patterns language. It is bus-specific: the state it observes is the client library's own, and no outer pattern covers it.

1. Also known as

  • Reconnection callbacks; connection events.

2. Context

A connection can be lost and regained without the process noticing. The client library reconnects on its own, the subscriptions are re-established, and the service looks as though nothing happened — while messages published during the gap were never delivered to it.

3. Problem

How does a reader tell "no messages arrived" from "this service was not connected to the bus when they arrived"?

4. Forces

  • A reconnection is silent by default: the service resumes and its log shows nothing.
  • A gap in a service's log is otherwise indistinguishable from a quiet period.
  • Only the sender's log records what was published during the gap, and a person investigating has one log.
  • The bus reports errors on its own thread, where a logging call can fault.

5. Solution

Install callbacks for the connection's state and write one line for each transition, plus one for an asynchronous transport error:

natsOptions_SetDisconnectedCB(opts, [](natsConnection*, void*) {
    BOOST_LOG_SEV(lg(), warn) << "NATS disconnected: the server is unreachable "
                                 "and subscriptions are not receiving.";
}, nullptr);

natsOptions_SetReconnectedCB(opts, [](natsConnection*, void*) {
    BOOST_LOG_SEV(lg(), warn) << "NATS reconnected: subscriptions are receiving "
                                 "again. Anything published while disconnected was "
                                 "delivered only if its subject is on a stream.";
}, nullptr);

Three rules:

  • Warn, not info. A transition is an event worth finding in a log that is otherwise at info level.
  • Say what the gap cost. The reconnected line states the consequence: messages on a stream were kept, messages on core NATS were not.
  • Never let a logging call fault. These callbacks run on a library thread and the logging system may already be shutting down, so each is guarded.

A transport error is reported the same way, through the error handler, rather than being printed to standard error by the library.

6. Failure handling

Concern What the pattern does
Errors An asynchronous transport error is logged instead of reaching stderr unlabelled.
Timeouts A dropped connection can surface to a caller as a request timeout; these lines explain it.
Retries The library reconnects on its own; the lines record that it did.
Idempotency Unaffected.
Observability This pattern is the bus-side observability rule.

7. Pitfalls

  • No callbacks installed. A service that lost and regained its connection is indistinguishable from one that never lost it.
  • A reconnected line with no consequence stated. The reader does not know whether anything was missed.
  • A callback that can throw. A logging call that faults on a library thread terminates the service.
  • Logging every transport event at info. Routine disconnects fill the log and the ones that matter are lost.

8. Resulting context

Benefits
A gap in a service's log is attributable, and an unexplained caller timeout has a candidate cause in the log.
Liabilities
Warnings appear for connections that recovered harmlessly, which a reader must learn to read as context rather than as a fault.

9. In ORE Studio

`ores.nats` installs a disconnected callback, a reconnected callback and an error handler when it connects, each logging at warn and each guarded against a torn-down logging system. The orderly connection loss during shutdown is deliberately suppressed so a clean stop does not read as a fault.

10. Related patterns

11. Sources

12. See also

  • NATS service patterns — the structure note that orders this pattern language, and where to read this page in it.

Emacs 29.3 (Org mode 9.6.15)