@kurrent/kurrentdb-client
Version:
KurrentDB gRPC NodeJS Client SDK
145 lines • 6.14 kB
JavaScript
;
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