UNPKG

@kurrent/kurrentdb-client

Version:
145 lines 6.14 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.batchAppend = void 0; const uuid_1 = require("uuid"); const timestamp_pb_1 = require("google-protobuf/google/protobuf/timestamp_pb"); const streams_grpc_pb_1 = require("../../../generated/streams_grpc_pb"); const streams_pb_1 = require("../../../generated/streams_pb"); const shared_pb_1 = require("../../../generated/shared_pb"); const utils_1 = require("../../utils"); const unpackError_1 = require("./unpackError"); const streamCache = new WeakMap(); const promiseBank = new Map(); const batchAppend = async function (streamName, events, { streamState, batchAppendSize, ...baseOptions }) { const correlationId = (0, uuid_1.v4)(); const stream = await this.GRPCStreamCreator(streams_grpc_pb_1.StreamsClient, "appendToStream", (client) => client .batchAppend(...this.callArguments(baseOptions, { deadline: Infinity, })) .on("data", (resp) => { const resultingId = (0, utils_1.parseUUID)(resp.getCorrelationId()); const [resolve, reject] = promiseBank.get(resultingId); promiseBank.delete(resultingId); if (resp.hasError()) { const grpcError = resp.getError(); if (!this.throwOnAppendFailure) { const wrongExpectedVersion = (0, unpackError_1.unpackWrongExpectedVersion)(grpcError); if (wrongExpectedVersion) { const nextExpectedRevision = wrongExpectedVersion.hasCurrentStreamRevision() ? BigInt(wrongExpectedVersion.hasCurrentStreamRevision()) : BigInt(-1); return resolve({ success: false, nextExpectedRevision, position: undefined, }); } } return reject((0, unpackError_1.unpackToCommandError)(grpcError, Buffer.from(resp.getStreamIdentifier().getStreamName()).toString("utf8"))); } const success = resp.getSuccess(); const nextExpectedRevision = BigInt(success.getCurrentRevision()); const grpcPosition = success.getPosition(); const position = grpcPosition ? { commit: BigInt(grpcPosition.getCommitPosition()), prepare: BigInt(grpcPosition.getPreparePosition()), } : undefined; return resolve({ success: true, nextExpectedRevision, position, }); }) .on("error", (error) => { for (const [_, reject] of promiseBank.values()) { reject((0, utils_1.convertToCommandError)(error)); } promiseBank.clear(); }), streamCache)(); return new Promise(async (...batchPromise) => { promiseBank.set(correlationId, batchPromise); const correlationUUID = (0, utils_1.createUUID)(correlationId); const options = new streams_pb_1.BatchAppendReq.Options(); const identifier = (0, utils_1.createStreamIdentifier)(streamName); const deadline = timestamp_pb_1.Timestamp.fromDate(this.createDeadline(baseOptions.deadline)); options.setStreamIdentifier(identifier); options.setDeadline21100(deadline); switch (streamState) { case "any": { options.setAny(new shared_pb_1.Empty()); break; } case "no_stream": { options.setNoStream(new shared_pb_1.Empty()); break; } case "stream_exists": { options.setStreamExists(new shared_pb_1.Empty()); break; } default: { options.setStreamPosition(streamState.toString(10)); break; } } for (const batch of eventBatcher(events, correlationUUID, options, batchAppendSize)) { utils_1.debug.command_grpc("batchAppend: %g", batch); await (0, utils_1.backpressuredWrite)(stream, batch); } }); }; exports.batchAppend = batchAppend; function* eventBatcher(events, correlationId, options, maxBatchSize) { const createAppendRequest = (addOptions = false) => { const appendRequest = new streams_pb_1.BatchAppendReq(); if (addOptions) { appendRequest.setOptions(options); } appendRequest.setCorrelationId(correlationId); appendRequest.setIsFinal(false); return appendRequest; }; let appendRequest = createAppendRequest(true); let batchSize = 0; for (const event of events) { const message = new streams_pb_1.BatchAppendReq.ProposedMessage(); const id = new shared_pb_1.UUID(); id.setString(event.id); message.setId(id); message.getMetadataMap().set("type", event.type); message.getMetadataMap().set("content-type", event.contentType); switch (event.contentType) { case "application/json": { const data = JSON.stringify(event.data); message.setData(Buffer.from(data, "utf8").toString("base64")); break; } case "application/octet-stream": { message.setData(event.data); break; } } if (event.metadata) { if (event.metadata.constructor === Uint8Array) { message.setCustomMetadata(event.metadata); } else { const metadata = JSON.stringify(event.metadata); message.setCustomMetadata(Buffer.from(metadata, "utf8").toString("base64")); } } const messageSize = message.serializeBinary().length; if (batchSize + messageSize >= maxBatchSize) { yield appendRequest; appendRequest = createAppendRequest(false); batchSize = 0; } batchSize += messageSize; appendRequest.addProposedMessages(message); } appendRequest.setIsFinal(true); yield appendRequest; } //# sourceMappingURL=batchAppend.js.map