UNPKG

@getanthill/datastore

Version:

Event-Sourced Datastore

118 lines (103 loc) 3.28 kB
import type { HandlerConfig, RunnerServices, Services, Source, } from '../../typings'; import { build } from '../../services'; import { random } from '../../utils'; function wait(delayInMilliseconds: number): Promise<void> { return new Promise((resolve) => setTimeout(resolve, delayInMilliseconds)); } function blockEventLoop(delayInMilliseconds: number): void { const tic = Date.now(); let blockedSince = 0; while (blockedSince < delayInMilliseconds) { blockedSince = Date.now() - tic; } } export async function main( url: URL, services: Services = build(), ): Promise<HandlerConfig> { const datastore = url.searchParams.get('datastore') ?? 'models'; const model = url.searchParams.get('model') ?? 'all'; const source = (url.searchParams.get('source') ?? 'events') as Source; const query = JSON.parse(url.searchParams.get('query') ?? '{}'); const timeout = Number.parseInt(url.searchParams.get('timeout') ?? '0', 10); const block = Number.parseInt(url.searchParams.get('block') ?? '0', 10); const exception = Number.parseInt( url.searchParams.get('exception') ?? '0', 10, ); const progress = Number.parseInt( url.searchParams.get('progress') ?? '1000', 10, ); const withHeartbeat = url.searchParams.get('with_heartbeat') === 'true'; const withFetch = url.searchParams.get('with_fetch') === 'true'; const stats = { processed: 0, processing: 0, exception: 0, waiting: 0, heartbeat: 0, fetching: 0, blocking: 0, }; return { triggers: [ { datastore, model, source, raw: false, query, }, ], start: async () => { services.telemetry.logger.info('[utils#log] Starting'); return services as unknown as RunnerServices; }, stop: async () => { services.telemetry.logger.info('[utils#log] Ending'); }, handler: async (event: any) => { stats.processing += 1; services.telemetry.logger.debug('[utils#log] Event', event); if (timeout > 0) { stats.waiting += 1; services.telemetry.logger.debug('[utils#log] Waiting', stats); await wait(timeout); stats.waiting -= 1; } if (withHeartbeat === true) { stats.heartbeat += 1; services.telemetry.logger.debug('[utils#log] Heartbeat', stats); await services.datastores.get(datastore)?.heartbeat(); stats.heartbeat -= 1; } if (withFetch === true) { stats.fetching += 1; services.telemetry.logger.debug('[utils#log] Fetch', stats); await services.datastores.get(datastore)?.find(model, {}, 0, 1000); stats.fetching -= 1; } if (block > 0) { stats.blocking += 1; services.telemetry.logger.debug('[utils#log] Block', stats); blockEventLoop(block); stats.blocking -= 1; } if (exception > 0 && random() <= exception) { stats.exception += 1; services.telemetry.logger.debug('[utils#log] Exception', stats); throw new Error('This is an error'); } stats.processing -= 1; stats.processed += 1; stats.processed % progress === 0 && services.telemetry.logger.info('[utils#log] Handled', stats); }, }; }