UNPKG

rocketmq-client-nodejs

Version:
248 lines 24.9 kB
"use strict"; /** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Producer = void 0; const node_assert_1 = __importDefault(require("node:assert")); const promises_1 = require("node:timers/promises"); const definition_pb_1 = require("../../proto/apache/rocketmq/v2/definition_pb"); const service_pb_1 = require("../../proto/apache/rocketmq/v2/service_pb"); const retry_1 = require("../retry"); const exception_1 = require("../exception"); const client_1 = require("../client"); const message_1 = require("../message"); const PublishingSettings_1 = require("./PublishingSettings"); const PublishingLoadBalancer_1 = require("./PublishingLoadBalancer"); const SendReceipt_1 = require("./SendReceipt"); const Transaction_1 = require("./Transaction"); const util_1 = require("../util"); class Producer extends client_1.BaseClient { #publishingSettings; #checker; #publishingRouteDataCache = new Map(); constructor(options) { if (!options.topics && options.topic) { options.topics = Array.isArray(options.topic) ? options.topic : [options.topic]; } super(options); // https://rocketmq.apache.org/docs/introduction/03limits/ // Default max number of message sending retries is 3 const retryPolicy = retry_1.ExponentialBackoffRetryPolicy.immediatelyRetryPolicy(options.maxAttempts ?? 3); this.#publishingSettings = new PublishingSettings_1.PublishingSettings(options.namespace, this.clientId, this.endpoints, retryPolicy, this.requestTimeout, this.topics); this.#checker = options.checker; } get publishingSettings() { return this.#publishingSettings; } beginTransaction() { (0, node_assert_1.default)(this.#checker, 'Transaction checker should not be null'); return new Transaction_1.Transaction(this); } async endTransaction(endpoints, message, messageId, transactionId, resolution) { const request = new service_pb_1.EndTransactionRequest() .setMessageId(messageId) .setTransactionId(transactionId) .setTopic((0, util_1.createResource)(message.topic).setResourceNamespace(this.namespace)) .setResolution(resolution); const response = await this.rpcClientManager.endTransaction(endpoints, request, this.requestTimeout); exception_1.StatusChecker.check(response.getStatus()?.toObject()); } async onRecoverOrphanedTransactionCommand(endpoints, command) { const transactionId = command.getTransactionId(); const messagePB = command.getMessage(); const messageId = messagePB.getSystemProperties().getMessageId(); if (!this.#checker) { this.logger.error('No transaction checker registered, ignore it, messageId=%s, transactionId=%s, endpoints=%s, clientId=%s', messageId, transactionId, endpoints, this.clientId); return; } let messageView; try { messageView = new message_1.MessageView(messagePB); } catch (err) { this.logger.error('[Bug] Failed to decode message during orphaned transaction message recovery, messageId=%s, transactionId=%s, endpoints=%s, clientId=%s, error=%s', messageId, transactionId, endpoints, this.clientId, err); return; } try { const resolution = await this.#checker.check(messageView); if (resolution === null || resolution === definition_pb_1.TransactionResolution.TRANSACTION_RESOLUTION_UNSPECIFIED) { return; } await this.endTransaction(endpoints, messageView, messageId, transactionId, resolution); this.logger.info('Recover orphaned transaction message success, transactionId=%s, resolution=%s, messageId=%s, clientId=%s', transactionId, resolution, messageId, this.clientId); } catch (err) { this.logger.error('Exception raised while checking the transaction, messageId=%s, transactionId=%s, endpoints=%s, clientId=%s, error=%s', messageId, transactionId, endpoints, this.clientId, err); return; } } getSettings() { return this.#publishingSettings; } wrapHeartbeatRequest() { return new service_pb_1.HeartbeatRequest() .setClientType(definition_pb_1.ClientType.PRODUCER); } wrapNotifyClientTerminationRequest() { return new service_pb_1.NotifyClientTerminationRequest(); } async send(message, transaction) { if (!transaction) { const sendReceipts = await this.#send([message], false); return sendReceipts[0]; } const publishingMessage = transaction.tryAddMessage(message); const sendReceipts = await this.#send([message], true); const sendReceipt = sendReceipts[0]; transaction.tryAddReceipt(publishingMessage, sendReceipt); return sendReceipt; } async #send(messages, txEnabled) { const pubMessages = []; const topics = new Set(); for (const message of messages) { pubMessages.push(new message_1.PublishingMessage(message, this.#publishingSettings, txEnabled)); topics.add(message.topic); } if (topics.size > 1) { throw new TypeError(`Messages to send have different topics=${JSON.stringify(topics)}`); } const topic = pubMessages[0].topic; const messageType = pubMessages[0].messageType; const messageGroup = pubMessages[0].messageGroup; const messageTypes = new Set(pubMessages.map(m => m.messageType)); if (messageTypes.size > 1) { throw new TypeError(`Messages to send have different types=${JSON.stringify(messageTypes)}`); } // Message group must be same if message type is FIFO, or no need to proceed. if (messageType === definition_pb_1.MessageType.FIFO) { const messageGroups = new Set(pubMessages.map(m => m.messageGroup)); if (messageGroups.size > 1) { throw new TypeError(`FIFO messages to send have message groups, messageGroups=${JSON.stringify(messageGroups)}`); } } // Get publishing topic route. const loadBalancer = await this.#getPublishingLoadBalancer(topic); // Prepare the candidate message queue(s) for retry-sending in advance. const candidates = messageGroup ? [loadBalancer.takeMessageQueueByMessageGroup(messageGroup)] : this.#takeMessageQueues(loadBalancer); return await this.#send0(topic, messageType, candidates, pubMessages, 1); } #wrapSendMessageRequest(pubMessages, mq) { const request = new service_pb_1.SendMessageRequest(); for (const pubMessage of pubMessages) { if (this.namespace) { request.addMessages(pubMessage.toProtobuf(this.namespace, mq)); } else { request.addMessages(pubMessage.toProtobuf('', mq)); } } return request; } /** * Isolate specified Endpoints */ #isolate(endpoints) { this.isolated.set(endpoints.facade, endpoints); } async #send0(topic, messageType, candidates, messages, attempt) { // Calculate the current message queue. const index = (attempt - 1) % candidates.length; const mq = candidates[index]; const acceptMessageTypes = mq.acceptMessageTypesList; if (this.#publishingSettings.isValidateMessageType() && !acceptMessageTypes.includes(messageType)) { throw new TypeError('Current message type not match with ' + 'topic accept message types, topic=' + topic + ', actualMessageType=' + messageType + ', ' + 'acceptMessageTypes=' + JSON.stringify(acceptMessageTypes)); } const endpoints = mq.broker.endpoints; const maxAttempts = this.#getRetryPolicy().getMaxAttempts(); const request = this.#wrapSendMessageRequest(messages, mq); let sendReceipts = []; try { const response = await this.rpcClientManager.sendMessage(endpoints, request, this.requestTimeout); sendReceipts = SendReceipt_1.SendReceipt.processResponseInvocation(mq, response); } catch (err) { const messageIds = messages.map(m => m.messageId); // Isolate endpoints because of sending failure. this.#isolate(endpoints); if (attempt >= maxAttempts) { // No need more attempts. this.logger.error('Failed to send message(s) finally, run out of attempt times, maxAttempts=%s, attempt=%s, topic=%s, messageId(s)=%s, endpoints=%s, clientId=%s, error=%s', maxAttempts, attempt, topic, messageIds, endpoints, this.clientId, err); throw err; } // No need more attempts for transactional message. if (messageType === definition_pb_1.MessageType.TRANSACTION) { this.logger.error('Failed to send transactional message finally, maxAttempts=%s, attempt=%s, topic=%s, messageId(s)=%s, endpoints=%s, clientId=%s, error=%s', maxAttempts, attempt, topic, messageIds, endpoints, this.clientId, err); throw err; } // Try to do more attempts. const nextAttempt = 1 + attempt; // Retry immediately if the request is not throttled. if (!(err instanceof exception_1.TooManyRequestsException)) { this.logger.warn('Failed to send message, would attempt to resend right now, maxAttempts=%s, attempt=%s, topic=%s, messageId(s)=%s, endpoints=%s, clientId=%s, error=%s', maxAttempts, attempt, topic, messageIds, endpoints, this.clientId, err); return this.#send0(topic, messageType, candidates, messages, nextAttempt); } const delay = this.#getRetryPolicy().getNextAttemptDelay(nextAttempt); this.logger.warn('Failed to send message due to too many requests, would attempt to resend after %sms, maxAttempts=%s, attempt=%s, topic=%s, messageId(s)=%s, endpoints=%s, clientId=%s, error=%s', delay, maxAttempts, attempt, topic, messageIds, endpoints, this.clientId, err); await (0, promises_1.setTimeout)(delay); return this.#send0(topic, messageType, candidates, messages, nextAttempt); } // Resend message(s) successfully. if (attempt > 1) { const messageIds = sendReceipts.map(r => r.messageId); this.logger.info('Resend message successfully, topic=%s, messageId(s)=%j, maxAttempts=%s, attempt=%s, endpoints=%s, clientId=%s', topic, messageIds, maxAttempts, attempt, endpoints, this.clientId); } // Send message(s) successfully on first attempt, return directly. return sendReceipts; } async #getPublishingLoadBalancer(topic) { let loadBalancer = this.#publishingRouteDataCache.get(topic); if (!loadBalancer) { const topicRouteData = await this.getRouteData(topic); loadBalancer = this.#updatePublishingLoadBalancer(topic, topicRouteData); } return loadBalancer; } #updatePublishingLoadBalancer(topic, topicRouteData) { let loadBalancer = this.#publishingRouteDataCache.get(topic); if (loadBalancer) { loadBalancer = loadBalancer.update(topicRouteData); } else { loadBalancer = new PublishingLoadBalancer_1.PublishingLoadBalancer(topicRouteData); } this.#publishingRouteDataCache.set(topic, loadBalancer); return loadBalancer; } /** * Take message queue(s) from route for message publishing. */ #takeMessageQueues(loadBalancer) { return loadBalancer.takeMessageQueues(this.isolated, this.#getRetryPolicy().getMaxAttempts()); } #getRetryPolicy() { return this.#publishingSettings.getRetryPolicy(); } } exports.Producer = Producer; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUHJvZHVjZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcHJvZHVjZXIvUHJvZHVjZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7Ozs7Ozs7Ozs7R0FlRzs7Ozs7O0FBRUgsOERBQWlDO0FBQ2pDLG1EQUFrRDtBQUNsRCxnRkFJc0Q7QUFDdEQsMEVBTW1EO0FBTW5ELG9DQUVrQjtBQUNsQiw0Q0FBdUU7QUFDdkUsc0NBQW9FO0FBQ3BFLHdDQUFxRjtBQUNyRiw2REFBMEQ7QUFFMUQscUVBQWtFO0FBQ2xFLCtDQUE0QztBQUM1QywrQ0FBNEM7QUFDNUMsa0NBQXlDO0FBUXpDLE1BQWEsUUFBUyxTQUFRLG1CQUFVO0lBQ3RDLG1CQUFtQixDQUFxQjtJQUN4QyxRQUFRLENBQXNCO0lBQzlCLHlCQUF5QixHQUFHLElBQUksR0FBRyxFQUFrQyxDQUFDO0lBRXRFLFlBQVksT0FBd0I7UUFDbEMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLElBQUksT0FBTyxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ3JDLE9BQU8sQ0FBQyxNQUFNLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUUsT0FBTyxDQUFDLEtBQUssQ0FBRSxDQUFDO1FBQ3BGLENBQUM7UUFDRCxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDZiwwREFBMEQ7UUFDMUQscURBQXFEO1FBQ3JELE1BQU0sV0FBVyxHQUFHLHFDQUE2QixDQUFDLHNCQUFzQixDQUFDLE9BQU8sQ0FBQyxXQUFXLElBQUksQ0FBQyxDQUFDLENBQUM7UUFDbkcsSUFBSSxDQUFDLG1CQUFtQixHQUFHLElBQUksdUNBQWtCLENBQUMsT0FBTyxDQUFDLFNBQVMsRUFBRSxJQUFJLENBQUMsUUFBUSxFQUFFLElBQUksQ0FBQyxTQUFTLEVBQUUsV0FBVyxFQUM3RyxJ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