Files
Draupnir/src/models/MatrixDataManager.ts
T
MTRNord fffd8563e3 Add opentelemetry tracing support
Add logging to tracing

Improve logging

Fix order of imports

Add missing pieces of tracing code

Add more logging

Try nested spans

Expand traces using an decorator

Improve quality of spans

Add missing tracing decorations

Filter metrics and healthz

Add more traces

Fix return type error
2023-09-01 19:13:55 +02:00

60 lines
2.5 KiB
TypeScript

/**
* Copyright (C) 2023 Gnuxie <Gnuxie@protonmail.com>
*/
import { trace } from "../utils";
export const SCHEMA_VERSION_KEY = 'ge.applied-langua.ge.draupnir.schema_version';
export type RawSchemedData = object & Record<typeof SCHEMA_VERSION_KEY, unknown>;
export type SchemaMigration = (input: RawSchemedData) => Promise<RawSchemedData>;
export abstract class MatrixDataManager<Format extends RawSchemedData = RawSchemedData> {
protected abstract schema: SchemaMigration[];
protected abstract isAllowedToInferNoVersionAsZero: boolean;
protected abstract requestMatrixData(): Promise<unknown>
protected abstract storeMatixData(data: Format): Promise<void>;
protected abstract createFirstData(): Promise<Format>;
@trace('MatrixDataManager.migrateData')
protected async migrateData(rawData: RawSchemedData): Promise<RawSchemedData> {
const startingVersion = rawData[SCHEMA_VERSION_KEY] as number;
// Rememeber, version 0 has no migrations
if (this.schema.length < startingVersion) {
throw new TypeError(`Encountered a version that we do not have migrations for ${startingVersion}`);
} else if (this.schema.length === startingVersion) {
return rawData;
} else {
const applicableSchema = this.schema.slice(startingVersion);
const migratedData = await applicableSchema.reduce(
async (previousData: Promise<RawSchemedData>, schema: SchemaMigration) => {
return await schema(await previousData)
}, Promise.resolve(rawData)
);
return migratedData;
}
}
@trace('MatrixDataManager.loadData')
protected async loadData(): Promise<Format> {
const rawData = await this.requestMatrixData();
if (rawData === undefined) {
return await this.createFirstData();
} else if (typeof rawData !== 'object' || rawData === null) {
throw new TypeError("The data has been corrupted.");
}
if (!(SCHEMA_VERSION_KEY in rawData) && this.isAllowedToInferNoVersionAsZero) {
(rawData as RawSchemedData)[SCHEMA_VERSION_KEY] = 0;
}
if (SCHEMA_VERSION_KEY in rawData
&& Number.isInteger(rawData[SCHEMA_VERSION_KEY])
) {
// what if the schema migration is somehow incorrect and we are casting as Format?
return await this.migrateData(rawData) as Format;
}
throw new TypeError("The schema version or data has been corrupted")
}
}