Service Registration & Heartbeat
Service Registration & Heartbeat
Relevant source files
The following files were used as context for generating this wiki page:
The Service module provides a standardized mechanism for microservices to announce their presence and maintain an active status within a central service_registry table. This module facilitates service discovery by ensuring that service metadata (base URLs and available endpoints) is kept up-to-date and that stale service entries can be identified via heartbeat timestamps.
Service Data Shape
The module defines a shared interface, IServiceRegistry, which represents the data structure stored in the database. To maintain database agnosticism, this interface is a plain TypeScript interface without decorators or dependencies on specific ORMs src/service/service-registry.ts:4-11.
| Property | Type | Description |
|---|---|---|
code | string | Unique identifier for the service (e.g., "emailsender"). |
base_url | string | The root URL where the service is reachable. |
endpoints | Record<string, unknown> | A map of functional endpoints exposed by the service. |
Sources: src/service/service-registry.ts:12-16
The ServiceRegistrar Class
The ServiceRegistrar is the primary orchestrator for service lifecycle events. It handles the initial registration (upsert logic) and the background heartbeat interval. It is designed to be DB-agnostic by depending on the ServiceRegistryPort rather than a specific Data Access Layer (DAL) src/service/service-registrar.ts:11-19.
Configuration
The registrar is configured via the ServiceRegistrarConfig object:
serviceCode: The unique name of the service.baseUrl: The current address of the service instance.endpoints: Metadata describing available routes.heartbeatIntervalMs: Frequency of heartbeat updates (defaults to 60,000ms if not provided) src/service/service-registrar.ts:28-31.
Registration Logic
When register() is called, the class performs an "upsert" against the provided port:
- It queries for an existing entry using
findByCodesrc/service/service-registrar.ts:35. - If the service exists, it calls
updateByCodeto refresh thebase_urlandendpointssrc/service/service-registrar.ts:38-42. - If no entry is found, it calls
insertto create a new record src/service/service-registrar.ts:45-49.
Heartbeat Management
startHeartbeat(): Initializes asetIntervalthat periodically callsupdateHeartbeat()src/service/service-registrar.ts:64-67.updateHeartbeat(): Triggers a partial update of thebase_url. This operation is designed to be resilient; it catches and logs database errors to prevent the service from crashing due to transient network or DB issues src/service/service-registrar.ts:54-62.stopHeartbeat(): Clears the interval timer and nullifies the reference, ensuring a clean shutdown src/service/service-registrar.ts:69-74.
Sources: src/service/service-registrar.ts:4-75, src/service/tests/service-registrar.test.ts:33-78
Service Registry Port
The SDK interacts with the database through the ServiceRegistryPort. The consuming microservice must provide an adapter implementation that maps these calls to their specific database driver or ORM (e.g., TypeORM, Knex, or a custom DAL) src/ports/service-registry-port.ts:6-9.
Service Registration Data Flow
Code
Sources: src/ports/service-registry-port.ts:10-19, src/service/service-registrar.ts:20-25
Implementation Mapping
The following diagram bridges the high-level registration concepts to the specific code entities defined in the SDK.
Code Entity Mapping
Code
Sources: src/service/service-registry.ts:12-16, src/ports/service-registry-port.ts:10-19, src/service/service-registrar.ts:20-75