UNPKG

@ceramicnetwork/core

Version:

Typescript implementation of the Ceramic protocol

74 lines 3.68 kB
import { Observable, EMPTY, pipe, of, from } from 'rxjs'; import { ServiceMetrics as Metrics } from '@ceramicnetwork/observability'; import { map, catchError, mergeMap, withLatestFrom, tap } from 'rxjs/operators'; import { deserialize, serialize } from './pubsub-message.js'; import { IncomingChannel, filterExternal, checkSlowObservable } from './incoming-channel.js'; import { TaskQueue } from '../ancillary/task-queue.js'; const textDecoder = new TextDecoder('utf-8'); function ipfsToPubsub(peerId$, pubsubLogger, topic) { return pipe(withLatestFrom(peerId$), mergeMap(([incoming, peerId]) => of(incoming).pipe(map((incoming) => { const message = deserialize(incoming); const serializedMessage = serialize(message); const logMessage = { ...incoming, ...JSON.parse(textDecoder.decode(serializedMessage)) }; delete logMessage.data; delete logMessage.key; delete logMessage.signature; pubsubLogger.log({ peer: peerId, event: 'received', topic: topic, message: logMessage }); return message; }), catchError(() => EMPTY)))); } const PUBSUB_PUBLISHED = 'pubsub_published'; const PUBSUB_RECEIVED = 'pubsub_received'; export class Pubsub extends Observable { constructor(ipfs, topic, resubscribeEvery, lateMessageAfter, pubsubLogger, logger, tasks = new TaskQueue()) { super((subscriber) => { const incoming$ = new IncomingChannel(ipfs, topic, resubscribeEvery, lateMessageAfter, pubsubLogger, logger, tasks); incoming$ .pipe(filterExternal(this.peerId$), checkSlowObservable(lateMessageAfter, logger, `IPFS did not provide any internal messages, please check your IPFS configuration.`), ipfsToPubsub(this.peerId$, pubsubLogger, topic), tap((message) => { Metrics.count(PUBSUB_RECEIVED, 1, { typ: message.typ }); })) .subscribe(subscriber); }); this.ipfs = ipfs; this.topic = topic; this.resubscribeEvery = resubscribeEvery; this.lateMessageAfter = lateMessageAfter; this.pubsubLogger = pubsubLogger; this.logger = logger; this.tasks = tasks; this.peerId$ = from(this.ipfs.id().then((_) => _.id.toString())); } next(message) { return this.peerId$ .pipe(mergeMap(async (peerId) => { const serializedMessage = serialize(message); const logMessage = { ...message, ...JSON.parse(textDecoder.decode(serializedMessage)) }; try { await this.ipfs.pubsub.publish(this.topic, serializedMessage); Metrics.count(PUBSUB_PUBLISHED, 1, { typ: message.typ }); this.pubsubLogger.log({ peer: peerId, event: 'published', topic: this.topic, message: logMessage, }); } catch (error) { this.pubsubLogger.log({ peer: peerId, event: 'publish-error', topic: this.topic, message: logMessage, }); if (error.message.includes('validation ignored')) { this.logger.err(`HTTP validation error received while publishing message to pubsub, this usually indicates there was a duplicate message published and should be safe to ignore: ${error}`); } else { this.logger.err(`Error received while publishing message to pubsub: ${error}`); } } })) .subscribe(); } } //# sourceMappingURL=pubsub.js.map