@axinom/mosaic-transactional-inbox-outbox
Version:
This library encapsulates the Mosaic based transactional inbox and outbox pattern
72 lines • 3.69 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.createMessagingMetric = void 0;
const node_crypto_1 = require("node:crypto");
const prom_client_1 = require("prom-client");
const common_1 = require("../common");
const outbox_inbox_health_check_handler_1 = require("./outbox-inbox-health-check-handler");
/**
* Creates a `Gauge` metric with the name `ax_messaging` which can be added to a metric registry.
* This metric will have an integer value of the duration in seconds if the service can acquire a
* service account token, send a message, and afterwards receive it. Or a value of `0` otherwise.
*
* @param healthCheckRoutingKey The RabbitMQ routing key for sending the outbox message
* @param storeOutboxMessage The outbox storage function for starting the message processing
* @param getAccessToken Get the access token with admin permissions to include in the message
* @param ownerPool The database owner pool as this is independent of an environment
* @param timeoutMs The optinal timeout in milliseconds after which the messaging should be considered as failure
* @returns A `Gauge` metric with a name `ax_messaging`.
*/
const createMessagingMetric = (healthCheckRoutingKey, storeOutboxMessage, getAccessToken, ownerPool, timeoutMs = 30000) => {
return new prom_client_1.Gauge({
name: `ax_messaging`,
help: `Message sending and receiving via RabbitMQ and the transactional outbox and inbox.`,
async collect() {
const nonce = (0, node_crypto_1.randomUUID)();
const start = Date.now();
const client = await ownerPool.connect();
try {
await (0, common_1.awaitWithTimeout)(async () => {
await client.query('INSERT INTO app_private.messaging_health (key) VALUES ($1);', [nonce]);
await storeOutboxMessage(nonce, (0, outbox_inbox_health_check_handler_1.getServiceHealthCheckMessagingSettings)(healthCheckRoutingKey), {
nonce,
}, client, {
envelopeOverrides: {
auth_token: await getAccessToken(),
},
});
// no await - stops when the client is released
client.query('LISTEN messaging_health_handled;');
let res;
const promise = new Promise((resolve) => {
res = resolve;
});
client.removeAllListeners('notification');
client.on('notification', (data) => {
var _a;
const payload = JSON.parse((_a = data.payload) !== null && _a !== void 0 ? _a : '{}');
if (payload.key === nonce) {
res(payload.success); // set to true or false in the handler
}
});
const success = await promise;
if (success) {
this.set(Math.ceil((Date.now() - start) / 1000));
}
else {
this.set(0);
}
await client.query('DELETE FROM app_private.messaging_health WHERE key = $1;', [nonce]);
}, timeoutMs);
client.release();
}
catch (error) {
this.set(0);
client.release(true);
return;
}
},
});
};
exports.createMessagingMetric = createMessagingMetric;
//# sourceMappingURL=messaging-health-metrics.js.map
;