UNPKG

node-opcua-client

Version:

pure nodejs OPCUA SDK - module client

128 lines 6.12 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.republish = republish; const chalk_1 = __importDefault(require("chalk")); const node_opcua_assert_1 = __importDefault(require("node-opcua-assert")); const node_opcua_debug_1 = require("node-opcua-debug"); const node_opcua_status_code_1 = require("node-opcua-status-code"); const node_opcua_types_1 = require("node-opcua-types"); const client_subscription_reconnection_1 = require("./client_subscription_reconnection"); const reconnection_1 = require("./reconnection"); const debugLog = (0, node_opcua_debug_1.make_debugLog)("RECONNECTION"); const doDebug = (0, node_opcua_debug_1.checkDebugFlag)("RECONNECTION"); function _sendRepublish(session, subscription) { return new Promise((resolve, reject) => { (0, node_opcua_assert_1.default)(Number.isFinite(subscription.lastSequenceNumber) && subscription.lastSequenceNumber + 1 >= 0); const request = new node_opcua_types_1.RepublishRequest({ retransmitSequenceNumber: subscription.lastSequenceNumber + 1, subscriptionId: subscription.subscriptionId }); // c8 ignore next if (doDebug) { // c8 ignore next debugLog(chalk_1.default.bgCyan.yellow.bold(" republish Request for subscription"), request.subscriptionId, " retransmitSequenceNumber=", request.retransmitSequenceNumber); } if (!session || session._closeEventHasBeenEmitted) { debugLog("ClientPublishEngine#_republish aborted "); return resolve({ isDone: true }); } session.republish(request, (err, response) => { if (!response) { reject(err); return; } const statusCode = err ? node_opcua_status_code_1.StatusCodes.Bad : response.responseHeader.serviceResult; if (!err && (statusCode.equals(node_opcua_status_code_1.StatusCodes.Good) || statusCode.equals(node_opcua_status_code_1.StatusCodes.BadMessageNotAvailable))) { // reprocess notification message and keep going if (statusCode.equals(node_opcua_status_code_1.StatusCodes.Good)) { subscription.onNotificationMessage(response.notificationMessage); } return resolve({ isDone: false }); } if (!err) { err = new Error(response.responseHeader.serviceResult.toString()); } debugLog(" _send_republish ends with ", err.message); reject(err); }); }); } async function _republish(engine, subscription) { const session = engine.session; // loop until done (all messages re-published or error) let isDone = false; while (!isDone) { // yield to event loop before each iteration await new Promise((resolve) => setImmediate(resolve)); const result = await _sendRepublish(session, subscription); isDone = result.isDone; } debugLog("nbPendingPublishRequest = ", engine.nbPendingPublishRequests); debugLog(" _republish ends with ", "null"); } async function __askSubscriptionRepublish(engine, subscription) { try { await _republish(engine, subscription); } catch (err) { // prettier-ignore { const _err = (0, reconnection_1._shouldNotContinue2)(subscription); if (_err) { throw _err; } } const error = err; debugLog("__askSubscriptionRepublish--------------------- err =", error.message); if (error.message.match(/BadSessionInvalid/)) { // _republish failed because session is not valid anymore on server side. throw error; } if (error.message.match(/SubscriptionIdInvalid/)) { // _republish failed because subscriptionId is not valid anymore on server side. // // This could happen when the subscription has timed out and has been deleted by server // Subscription may time out if the duration of the connection break exceed the max life time // of the subscription. // // In this case, Client must recreate a subscription and recreate monitored item without altering // the event handlers // debugLog(chalk_1.default.bgWhite.red("__askSubscriptionRepublish failed " + " subscriptionId is not valid anymore on server side.")); await (0, client_subscription_reconnection_1.recreateSubscriptionAndMonitoredItem)(subscription); return; } if (error.message.match(/|MessageNotAvailable/)) { // start engine and start monitoring } } // check after successful republish too const _err = (0, reconnection_1._shouldNotContinue2)(subscription); if (_err) { throw _err; } } function republish(engine, callback) { // After re-establishing the connection the Client shall call Republish in a loop, starting with // the next expected sequence number and incrementing the sequence number until the Server returns // the status BadMessageNotAvailable. // After receiving this status, the Client shall start sending Publish requests with the normal Publish // handling. // This sequence ensures that the lost NotificationMessages queued in the Server are not overwritten // by newPublish responses /** * call Republish continuously until all Notification messages of * un-acknowledged notifications are reprocessed. */ const processAll = async () => { const entries = Object.entries(engine.subscriptionMap); for (const [_subscriptionId, subscription] of entries) { await __askSubscriptionRepublish(engine, subscription); } }; processAll().then(() => callback()).catch(() => callback()); } //# sourceMappingURL=client_publish_engine_reconnection.js.map