UNPKG

@rdfc/sds-storage-writer-ts

Version:

An RDF-Connect processor to write SDS streams into a given storage system

116 lines (115 loc) 4.86 kB
import { getLoggerFor } from "../utils/logUtil.js"; import { Lock } from "async-await-mutex-lock"; import { createClient } from "redis"; import { DataFactory, Parser } from "n3"; const { namedNode } = DataFactory; export class RedisRepository { url; metadata; data; index; client; logger = getLoggerFor(this); lock = new Lock(); constructor(url, metadata, data, index) { this.url = url; this.metadata = metadata; this.data = data; this.index = index; } async open() { this.client = createClient({ url: this.url }); await this.client.connect(); this.logger.debug(`Connected to ${this.url}`); } async close() { await this.client.disconnect(); this.logger.debug(`Closed connection to ${this.url}`); } async ingestMetadata(type, id, value) { await this.lock.acquire("metaRedis"); try { await this.client.set(`${this.metadata}:${encodeURIComponent(type)}:${encodeURIComponent(id)}`, value); } finally { this.lock.release("metaRedis"); } } async findMetadataFragmentations() { const keys = await this.client.keys(`${this.metadata}:fragmentation:*`); if (keys.length === 0) { return []; } const entries = await this.client.mGet(keys); return entries.map((entry, i) => { const key = keys[i].split(":"); return { id: namedNode(encodeURIComponent(key[2])), quads: new Parser().parse(entry), }; }); } async createIndices() { } prepareDataBulk() { return []; } async ingestDataBulk(bulk) { await Promise.all(bulk); } async handleRecord(record, data, bulk) { bulk.push(this.client.set(`${this.data}:${encodeURIComponent(record.payload)}`, data), this.client.set(`${this.data}:${encodeURIComponent(record.payload)}:created`, Date.now())); } prepareIndexBulk() { return []; } async ingestIndexBulk(bulk) { await Promise.all(bulk); } async handleMember(record, bucket, bulk) { bulk.push(this.client.json.set(`${this.index}:${encodeURIComponent(record.stream)}:${encodeURIComponent(bucket)}`, "$.updated", Date.now(), { XX: true })); bulk.push(this.client.sAdd(`${this.index}:${encodeURIComponent(record.stream)}:${encodeURIComponent(bucket)}:members`, record.payload)); } async handleBucket(bucket, bulk) { if (bucket.empty) { bulk.push(this.client.del(`${this.index}:${encodeURIComponent(bucket.streamId)}:${encodeURIComponent(bucket.id)}:members`)); } delete bucket.empty; bulk.push(this.client.json.set(`${this.index}:${encodeURIComponent(bucket.streamId)}:${encodeURIComponent(bucket.id)}`, "$", { created: Date.now() }, { NX: true })); bulk.push(this.client.json.merge(`${this.index}:${encodeURIComponent(bucket.streamId)}:${encodeURIComponent(bucket.id)}`, "$", { updated: Date.now(), ...bucket })); } async handleRelation(relation, path, value, bulk) { bulk.push(this.client.json.set(`${this.index}:${encodeURIComponent(relation.stream)}:${encodeURIComponent(relation.origin)}`, "$.updated", Date.now(), { XX: true })); bulk.push(this.client.sAdd(`${this.index}:${encodeURIComponent(relation.stream)}:${encodeURIComponent(relation.origin)}:relations`, JSON.stringify({ type: relation.type, stream: relation.stream, origin: relation.origin, bucket: relation.bucket, path: path, value: value, }))); } async removeRelation(relation, path, value, bulk) { const key = `${this.index}:${encodeURIComponent(relation.stream)}:${encodeURIComponent(relation.origin)}:relations`; const existingRelations = await this.client.sMembers(key); if (!existingRelations || existingRelations.length === 0) { return; } for (const rel of existingRelations) { try { const parsedRel = JSON.parse(rel); if (parsedRel.type === relation.type && parsedRel.bucket === relation.bucket && (path === undefined || parsedRel.path === path) && (value === undefined || parsedRel.value === value)) { bulk.push(this.client.sRem(key, rel)); } } catch (error) { this.logger.error(`Failed to parse relation: ${rel}`); this.logger.debug(error); } } bulk.push(this.client.json.set(`${this.index}:${encodeURIComponent(relation.stream)}:${encodeURIComponent(relation.origin)}`, "$.updated", Date.now(), { XX: true })); } }