Private ReadonlyCACHE_Private ReadonlyCB_Private ReadonlyCB_Open circuit after 5 failures
Private ReadonlyconsulPrivatefailureFailure count
PrivatelastLast failure time
Private ReadonlyloggerPrivateroundPrivateservicePrivateshutdownDiscovers a healthy service instance from Consul's service registry.
Implements a resilient discovery flow with multiple layers of fault tolerance:
The registered Consul service name
(e.g. 'file-manager' or 'auth-service').
OptionalfetchType: FetchType = FetchType.FIRSTThe node selection strategy:
FetchType.FIRST — always returns the first healthy node.FetchType.ROUND_ROBIN — cycles through nodes sequentially per service.FetchType.RANDOM — picks a random healthy node.The selected service node containing address, port, and url.
// Basic usage with default strategy (FIRST)
const node = await this.serviceDiscoveryService.discoverService('file-manager');
// => { address: '10.0.1.5', port: 3001, url: 'http://10.0.1.5:3001' }
PrivategetAttempts to return a node from the local cache (even if stale) as a resilience fallback when Consul is unreachable.
This is the last line of defence — if the cache is empty or has never been populated for the requested service, the method throws, causing the caller to surface a hard failure.
The service name to look up in the cache.
The node selection strategy forwarded to selectNode.
A node selected from the (potentially stale) cache.
PrivategetFetches healthy service nodes from Consul with automatic retry and exponential backoff.
Retry schedule (default 8 attempts):
| Attempt | Backoff delay |
|---|---|
| 1 | 400 ms |
| 2 | 800 ms |
| 3 | 1600 ms |
| 4 | 3200 ms |
| 5 | 6400 ms |
| 6 | 12800 ms |
| 7 | 25600 ms |
| 8 | throws |
Before hitting the network, checks the local cache. If the cache entry is still within its TTL (CACHE_TTL_MS), the cached nodes are returned immediately — avoiding unnecessary Consul round-trips.
The raw Consul response is mapped into ServiceNode objects with a
pre-built url field for convenience.
The registered Consul service name to query.
Optionalretries: number = 8Maximum number of fetch attempts before giving up.
An array of healthy nodes for the service.
If all retry attempts are exhausted. The thrown error is the last error encountered (network failure or zero-instance response).
PrivateisChecks whether the cached entry for a given service is still within its time-to-live window (CACHE_TTL_MS, default 30 000 ms).
The service name to look up in the cache.
true if a cache entry exists and its age is less
than CACHE_TTL_MS; false otherwise.
PrivateisEvaluates whether the circuit breaker is currently in the Open state.
The circuit transitions through three states:
false).true if the circuit is Open (callers should skip
Consul and fall back to cache); false otherwise.
PrivaterecordRecords a Consul interaction failure by incrementing the failure counter and updating the last-failure timestamp.
Once failureCount reaches CB_THRESHOLD, the circuit breaker trips to the Open state (see isCircuitOpen).
PrivateresetResets the circuit breaker back to the Closed state by zeroing the failure counter.
Called after a successful Consul interaction to indicate the service registry is healthy again.
PrivateselectSelects a single ServiceNode from a list of healthy nodes using the specified load-balancing strategy.
| Strategy | Behaviour |
|---|---|
FetchType.FIRST |
Always returns nodes[0] (deterministic, no state). |
FetchType.ROUND_ROBIN |
Cycles through nodes via a per-service counter. |
FetchType.RANDOM |
Uniform random selection across all available nodes. |
The list of healthy service nodes to choose from. Must contain at least one element.
The service name, used as the key for the round-robin counter map.
The selection strategy to apply.
A single node chosen according to the strategy.
const nodes: ServiceNode[] = [
{ address: '10.0.0.1', port: 3000, url: 'http://10.0.0.1:3000' },
{ address: '10.0.0.2', port: 3000, url: 'http://10.0.0.2:3000' },
];
const selected = this.selectNode(nodes, 'auth-service', FetchType.ROUND_ROBIN);
// First call => nodes[0]
// Second call => nodes[1]
// Third call => nodes[0] (wraps around)
PrivateupdateStores (or overwrites) a service's healthy nodes in the in-memory cache, stamping the entry with the current time for TTL validation.
The service name used as the cache key.
The list of healthy nodes to cache.
Try again after 10 seconds