Skip to main content

@axinom/mosaic-service-common

This package contains modules that help to create a Mosaic-based service.

Configuration management

Microservices have the benefit to be developed independently from each other, potentially with different approaches and technologies. But this can make it quite hard to know and learn about all the different ways and patterns on how to configure each service individually.

The Mosaic configuration management offers a set of common configuration settings and how to load them from the environment variables, validate them, and exposes them inside of Mosaic based applications.

You can pick one of the existing configuration definitions and define your own that you can reuse in your different services. There are utility functions for basic configurations, GraphQL settings, database connections, Rabbit MQ, etc.

Logging and Error handling

There is a common logging solution that encapsulates all the aspects around logging. It includes different log levels and log configurations. It includes a log masking middleware which helps to not write secret values to your log files. To ensure a central handling of those log aspects a global console.log overwrite can be used to route all log messages to this logging logic.

The library offers utilities that help you with consistent error handling. It has different classes that inherit from the base JavaScript Error class and provide additional functionality. It includes specific error handlers e.g. mappings for PostgreSQL database error codes.

Health Monitoring

The following section describes the helper functions that are exported through this library and their usage.

setupLivenessAndReadiness

When your services are deployed with Axinom Hosting or when you self-host with the help of a container orchestration layer (i.e. k8s), it will be essential to expose liveness & readiness endpoints that can be probed by the hosting layer for ensuring appropriate steps are taken when the service goes through different life-cycles.

Liveness probe

Liveness probes determine when to restart a service. For example, liveness probes could be used when a service enters a deadlock while it's running and is unable to make progress or auto-heal. If a service sets its liveness probe to false, it will be restarted.

Readiness probe

Readiness probes determine when a service is ready to start accepting traffic. This is useful when waiting for the service to perform time-consuming boot-up sequence tasks, such as establishing network connections, loading files, and warming caches. Until the service will set its readiness to true, it will not receive any traffic.

Usage

The function signature is given below.

setupLivenessAndReadiness = (
config: BasicConfig,
livenessReadinessOptions: ILivenessReadinessOptions = {},
logger?: Logger,
): {
liveness: State<boolean>;
readiness: State<boolean>;
}

The table below describes the arguments in the function signature.

ParameterDescription
configThe config object of the service.
livenessReadinessOptionsThis parameter is an optional object that is used to configure the liveness & readiness default behaviors.
loggerThis is an optional parameter that can be used to pass a logging utility..

This function is called at the service start-up, typically from the index.ts of the service. Then the service can use the liveness & readiness return values to control the behavior as necessary. It will create an express app that listens on the port that's configured on config.healthEndpointPort, which is 9000 by default.

You could change the readiness of your service by calling readiness.setState(true) after your service has gone through the boot-up sequence.

You could change the liveness at any point using some custom asynchronous/event based logic by calling liveness.setState(false). For example, if your service is stuck in an unrecoverable state due to a deadlock situation, it could call the liveness.setState(false) method and let the container orchestration layer detect that on the next liveness probing and automatically restart the container to potentially fix the deadlock issue.

setupServiceHealthEndpoint

This sets up a health endpoint for an express application. The serviceHealthOptions object will contain the options to configure the health endpoint route as required, and if not specified, will default to /health. The function will return a serviceHealthData handle, that can be used to set the current health data of the service (i.e. a key-value object as defined by the service). If not set, this will default to an empty object. When an HTTP GET request is made to the health endpoint of a service, it will return a 200 response code along with contents set to the serviceHealthData handle by the service.

note

This is different from the setupLivenessAndReadiness helper described above. The setupLivenessAndReadiness is used internally by the container orchestration layer (such as k8s) to automatically react to service life-cycle changes. Where-as setupServiceHealthEndpoint is meant to expose a publicly accessible route that provides a Key-Value pair object to indicate the current running state of your service in a much more granular way that can be used in further monitoring tools and integrations as necessary.

Usage

The function signature is given below.

const setupServiceHealthEndpoint = (
app: Express,
ServiceHealthEndpointOptions: ServiceHealthEndpointOptions = {},
logger?: Logger,
): {
serviceHealthData: HealthData;
}

The table below describes the arguments in the function signature.

ParameterDescription
appInstance of the Express application.
ServiceHealthEndpointOptionsThis parameter is an optional object that is used to configure options related to the service health endpoint.
loggerThis is an optional parameter that can be used to pass a logging utility..

This function is called at the service start-up, typically from the index.ts of the service.

isServiceAvailable

This function is used to check the health status of a service by accessing the /health endpoint. The function returns a Promise<boolean> indicating whether the service is available. It check the availability of a service by making HTTP requests to the specified URL and route and returning true if the service is available and false otherwise.

Usage

The function signature is shown below.

const isServiceAvailable = async (
baseUrl: string,
healthRoute = '/health',
maxRetryAttempts = 15,
logger?: Logger,
): Promise<boolean>

The table below describes the arguments in the isServiceAvailable function.

ParameterDescription
baseUrlThe base URL of the service..
healthRouteThe path to mount the service health endpoint. If not specified, will default to /health.
maxRetryAttemptsThe maximum number of retry attempts when checking the service’s availability, default count will be 15.
loggerA logger object to use for output generated inside the middleware.

This function is called at the service start-up, typically from the index.ts of the service.

Utilities

In addition to the above mentioned modules, this library includes a lot of other utility modules. Those are about type definitions, unit testing helpers, seed data generation, and a lot more.