UNPKG

substreams-sink-redis

Version:
112 lines 4.96 kB
import { TimeSeriesAggregationType } from "redis"; import { TS_ADD, SET, TS_CREATE, TS_CREATERULE } from "./redis.js"; import { parseKey, toTimestamp } from "./utils.js"; import { logger } from "substreams-sink"; export async function handleOutput(client, message, cursor, clock, options) { const type = await message.getType(); switch (type.typeName.toString()) { case "pinax.substreams.sink.prometheus.v1.PrometheusOperations": return handlePrometheusOperations(client, message, clock, options); case "sf.substreams.sink.kv.v1.KVOperations": return handleKVOperations(client, message, clock, options); } } export function handleClock(client, clock, options) { return Promise.all([ SET(client, parseKey("clock:timestamp", options), toTimestamp(clock)), SET(client, parseKey("clock:number", options), Number(clock.number)) ]); } export function handleCursor(client, cursor, options) { return SET(client, parseKey("cursor", options), cursor); } export async function handlePrometheusOperations(client, message, clock, options) { const operations = message?.operations || []; return Promise.all(operations.map(operation => { handlePrometheusOperation(client, operation, clock, options); })); } // global cache, stores all newly created keys const keys = new Set(); // global cache, stores all newly created rules const rules = new Set(); export async function createRules(client, key, options, labels) { if (options.kvCreateRules) { const destinationKey = `${key}:${options.kvBucketDuration}:sum`; // Destination key and rule already created, skip if (keys.has(destinationKey)) return; // Create source key if (!keys.has(key) && !await client.EXISTS(key)) { try { await TS_CREATE(client, key, labels, options.kvRetentionPeriod); keys.add(key); } catch (e) { logger.warn(`Failed to create key ${key}`, e); } } // Create destination key if (!keys.has(destinationKey) && !await client.EXISTS(destinationKey)) { try { await TS_CREATE(client, destinationKey, labels, 0); // does not include retention period keys.add(destinationKey); } catch (e) { logger.warn(`Failed to create destination key ${key}`, e); } } else if (!keys.has(destinationKey) && await client.EXISTS(destinationKey)) { keys.add(destinationKey); return; } try { await TS_CREATERULE(client, key, destinationKey, options); } catch (e) { logger.warn(`Failed to create rule for key ${key}`, e); } } } export async function handlePrometheusOperation(client, operation, clock, options) { const key = parseKey(operation.name, options, operation.labels); await createRules(client, key, options, operation.labels); switch (operation.operation.case) { case "counter": return await handlePrometheusCounter(client, key, operation.toJson(), clock, options); case "gauge": return await handlePrometheusGauge(client, key, operation.toJson(), clock, options); } } export async function handlePrometheusCounter(client, key, operation, clock, options) { // https://github.com/pinax-network/substreams-sink-prometheus.rs/blob/main/proto/substreams/sink/prometheus/v1/prometheus.proto#L48 switch (operation.counter.operation) { case "OPERATION_ADD": return await TS_ADD(client, key, operation.counter.value, clock, operation.labels, options); case "OPERATION_INC": return await TS_ADD(client, key, 1, clock, operation.labels, options); } } export async function handlePrometheusGauge(client, key, operation, clock, options) { // https://github.com/pinax-network/substreams-sink-prometheus.rs/blob/main/proto/substreams/sink/prometheus/v1/prometheus.proto#L23 switch (operation.gauge.operation) { case "OPERATION_ADD": return TS_ADD(client, key, operation.gauge.value, clock, operation.labels, options); case "OPERATION_INC": return TS_ADD(client, key, 1, clock, operation.labels, options); // TO-DO: Set gauge value // TO-DO: Remove gauge value } } export async function handleKVOperations(client, message, clock, options) { const operations = message?.operations || []; return Promise.all(operations.map(operation => { handleKVOperation(client, operation, clock, options); })); } export async function handleKVOperation(client, operation, clock, options) { const key = parseKey(operation.key, options); const value = Buffer.from(operation.value).toString(); return SET(client, key, value); } //# sourceMappingURL=handlers.js.map