Merge pull request #6888 from smatvienko-tb/js-executor-expiredTs

[3.4] Js executor expired ts
This commit is contained in:
Igor Kulikov 2022-07-07 10:48:54 +03:00 committed by GitHub
commit e0eaef1bba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 33 additions and 14 deletions

View File

@ -22,7 +22,7 @@ import java.util.UUID;
public class AbstractTbQueueTemplate { public class AbstractTbQueueTemplate {
protected static final String REQUEST_ID_HEADER = "requestId"; protected static final String REQUEST_ID_HEADER = "requestId";
protected static final String RESPONSE_TOPIC_HEADER = "responseTopic"; protected static final String RESPONSE_TOPIC_HEADER = "responseTopic";
protected static final String REQUEST_TIME = "requestTime"; protected static final String EXPIRE_TS_HEADER = "expireTs";
protected byte[] uuidToBytes(UUID uuid) { protected byte[] uuidToBytes(UUID uuid) {
ByteBuffer buf = ByteBuffer.allocate(16); ByteBuffer buf = ByteBuffer.allocate(16);

View File

@ -56,6 +56,7 @@ public class DefaultTbQueueRequestTemplate<Request extends TbQueueMsg, Response
final boolean internalExecutor; final boolean internalExecutor;
final ExecutorService executor; final ExecutorService executor;
final long maxRequestTimeoutNs; final long maxRequestTimeoutNs;
final long maxRequestTimeout;
final long maxPendingRequests; final long maxPendingRequests;
final long pollInterval; final long pollInterval;
volatile boolean stopped = false; volatile boolean stopped = false;
@ -76,6 +77,7 @@ public class DefaultTbQueueRequestTemplate<Request extends TbQueueMsg, Response
this.requestTemplate = requestTemplate; this.requestTemplate = requestTemplate;
this.responseTemplate = responseTemplate; this.responseTemplate = responseTemplate;
this.maxRequestTimeoutNs = TimeUnit.MILLISECONDS.toNanos(maxRequestTimeout); this.maxRequestTimeoutNs = TimeUnit.MILLISECONDS.toNanos(maxRequestTimeout);
this.maxRequestTimeout = maxRequestTimeout;
this.maxPendingRequests = maxPendingRequests; this.maxPendingRequests = maxPendingRequests;
this.pollInterval = pollInterval; this.pollInterval = pollInterval;
this.internalExecutor = (executor == null); this.internalExecutor = (executor == null);
@ -170,7 +172,7 @@ public class DefaultTbQueueRequestTemplate<Request extends TbQueueMsg, Response
log.error("[{}] Missing requestId in header and body", response); log.error("[{}] Missing requestId in header and body", response);
} else { } else {
requestId = bytesToUuid(requestIdHeader); requestId = bytesToUuid(requestIdHeader);
log.trace("[{}] Response received: {}", requestId, String.valueOf(response).replace("\n", " ")); //TODO remove overhead log.trace("[{}] Response received: {}", requestId, response);
ResponseMetaData<Response> expectedResponse = pendingRequests.remove(requestId); ResponseMetaData<Response> expectedResponse = pendingRequests.remove(requestId);
if (expectedResponse == null) { if (expectedResponse == null) {
log.debug("[{}] Invalid or stale request, response: {}", requestId, String.valueOf(response).replace("\n", " ")); log.debug("[{}] Invalid or stale request, response: {}", requestId, String.valueOf(response).replace("\n", " "));
@ -216,7 +218,7 @@ public class DefaultTbQueueRequestTemplate<Request extends TbQueueMsg, Response
UUID requestId = UUID.randomUUID(); UUID requestId = UUID.randomUUID();
request.getHeaders().put(REQUEST_ID_HEADER, uuidToBytes(requestId)); request.getHeaders().put(REQUEST_ID_HEADER, uuidToBytes(requestId));
request.getHeaders().put(RESPONSE_TOPIC_HEADER, stringToBytes(responseTemplate.getTopic())); request.getHeaders().put(RESPONSE_TOPIC_HEADER, stringToBytes(responseTemplate.getTopic()));
request.getHeaders().put(REQUEST_TIME, longToBytes(getCurrentTimeMs())); request.getHeaders().put(EXPIRE_TS_HEADER, longToBytes(getCurrentTimeMs() + maxRequestTimeout));
long currentClockNs = getCurrentClockNs(); long currentClockNs = getCurrentClockNs();
SettableFuture<Response> future = SettableFuture.create(); SettableFuture<Response> future = SettableFuture.create();
ResponseMetaData<Response> responseMetaData = new ResponseMetaData<>(currentClockNs + requestTimeoutNs, future, currentClockNs, requestTimeoutNs); ResponseMetaData<Response> responseMetaData = new ResponseMetaData<>(currentClockNs + requestTimeoutNs, future, currentClockNs, requestTimeoutNs);

View File

@ -97,8 +97,8 @@ public class DefaultTbQueueResponseTemplate<Request extends TbQueueMsg, Response
requests.forEach(request -> { requests.forEach(request -> {
long currentTime = System.currentTimeMillis(); long currentTime = System.currentTimeMillis();
long requestTime = bytesToLong(request.getHeaders().get(REQUEST_TIME)); long expireTs = bytesToLong(request.getHeaders().get(EXPIRE_TS_HEADER));
if (requestTime + requestTimeout >= currentTime) { if (expireTs >= currentTime) {
byte[] requestIdHeader = request.getHeaders().get(REQUEST_ID_HEADER); byte[] requestIdHeader = request.getHeaders().get(REQUEST_ID_HEADER);
if (requestIdHeader == null) { if (requestIdHeader == null) {
log.error("[{}] Missing requestId in header", request); log.error("[{}] Missing requestId in header", request);

View File

@ -21,6 +21,7 @@ const TIMEOUT_ERROR = 2;
const UNRECOGNIZED = -1; const UNRECOGNIZED = -1;
const config = require('config'), const config = require('config'),
Long = require('long'),
logger = require('../config/logger')._logger('JsInvokeMessageProcessor'), logger = require('../config/logger')._logger('JsInvokeMessageProcessor'),
Utils = require('./utils'), Utils = require('./utils'),
JsExecutor = require('./jsExecutor'); JsExecutor = require('./jsExecutor');
@ -49,6 +50,7 @@ JsInvokeMessageProcessor.prototype.onJsInvokeMessage = function (message) {
var tStart = performance.now(); var tStart = performance.now();
let requestId; let requestId;
let responseTopic; let responseTopic;
let expireTs;
let headers; let headers;
let request; let request;
let buf; let buf;
@ -59,6 +61,20 @@ JsInvokeMessageProcessor.prototype.onJsInvokeMessage = function (message) {
requestId = Utils.UUIDFromBuffer(buf); requestId = Utils.UUIDFromBuffer(buf);
buf = Buffer.from(headers.data['responseTopic']); buf = Buffer.from(headers.data['responseTopic']);
responseTopic = buf.toString('utf8'); responseTopic = buf.toString('utf8');
buf = Buffer.from(headers.data['expireTs']);
expireTs = Long.fromBytes(buf, false, false).toNumber();
const now = Date.now();
// if (logger.isDebugEnabled()) {
// logger.debug('expireTs is %s, buf is %s. Now is %s, ms to expire left %s', expireTs, buf.toString('hex'), now, expireTs - now)
// }
if (expireTs && expireTs <= now) {
if (logger.isDebugEnabled()) {
logger.debug('Message expired! expireTs is %s, buf is %s. Now is %s, ms to expire left %s', expireTs, buf.toString('hex'), now, expireTs - now)
}
return;
}
logger.debug('[%s] Received request, responseTopic: [%s]', requestId, responseTopic); logger.debug('[%s] Received request, responseTopic: [%s]', requestId, responseTopic);
@ -140,7 +156,7 @@ JsInvokeMessageProcessor.prototype.processInvokeRequest = function (requestId, r
(result) => { (result) => {
var invokeResponse = createInvokeResponse(result, true); var invokeResponse = createInvokeResponse(result, true);
logger.debug('[%s] Sending success invoke response, scriptId: [%s]', requestId, scriptId); logger.debug('[%s] Sending success invoke response, scriptId: [%s]', requestId, scriptId);
this.sendResponse(requestId, responseTopic, headers, scriptId, null, invokeResponse); this.sendResponse(requestId, responseTopic, headers, scriptId, undefined, invokeResponse);
}, },
(err) => { (err) => {
var errorCode; var errorCode;
@ -151,14 +167,14 @@ JsInvokeMessageProcessor.prototype.processInvokeRequest = function (requestId, r
} }
var invokeResponse = createInvokeResponse("", false, errorCode, err); var invokeResponse = createInvokeResponse("", false, errorCode, err);
logger.debug('[%s] Sending failed invoke response, scriptId: [%s], errorCode: [%s]', requestId, scriptId, errorCode); logger.debug('[%s] Sending failed invoke response, scriptId: [%s], errorCode: [%s]', requestId, scriptId, errorCode);
this.sendResponse(requestId, responseTopic, headers, scriptId, null, invokeResponse); this.sendResponse(requestId, responseTopic, headers, scriptId, undefined, invokeResponse);
} }
) )
}, },
(err) => { (err) => {
var invokeResponse = createInvokeResponse("", false, COMPILATION_ERROR, err); var invokeResponse = createInvokeResponse("", false, COMPILATION_ERROR, err);
logger.debug('[%s] Sending failed invoke response, scriptId: [%s], errorCode: [%s]', requestId, scriptId, COMPILATION_ERROR); logger.debug('[%s] Sending failed invoke response, scriptId: [%s], errorCode: [%s]', requestId, scriptId, COMPILATION_ERROR);
this.sendResponse(requestId, responseTopic, headers, scriptId, null, invokeResponse); this.sendResponse(requestId, responseTopic, headers, scriptId, undefined, invokeResponse);
} }
); );
} }
@ -176,7 +192,7 @@ JsInvokeMessageProcessor.prototype.processReleaseRequest = function (requestId,
} }
var releaseResponse = createReleaseResponse(scriptId, true); var releaseResponse = createReleaseResponse(scriptId, true);
logger.debug('[%s] Sending success release response, scriptId: [%s]', requestId, scriptId); logger.debug('[%s] Sending success release response, scriptId: [%s]', requestId, scriptId);
this.sendResponse(requestId, responseTopic, headers, scriptId, null, null, releaseResponse); this.sendResponse(requestId, responseTopic, headers, scriptId, undefined, undefined, releaseResponse);
} }
JsInvokeMessageProcessor.prototype.sendResponse = function (requestId, responseTopic, headers, scriptId, compileResponse, invokeResponse, releaseResponse) { JsInvokeMessageProcessor.prototype.sendResponse = function (requestId, responseTopic, headers, scriptId, compileResponse, invokeResponse, releaseResponse) {
@ -276,7 +292,7 @@ function createReleaseResponse(scriptId, success) {
function parseJsErrorDetails(err) { function parseJsErrorDetails(err) {
if (!err) { if (!err) {
return ''; return undefined;
} }
var details = err.name + ': ' + err.message; var details = err.name + ': ' + err.message;
if (err.stack) { if (err.stack) {

View File

@ -65,15 +65,15 @@ async function pushMessageToSendLater(message) {
function sendLoopWithLinger() { function sendLoopWithLinger() {
if (sendLoopInstance) { if (sendLoopInstance) {
clearTimeout(sendLoopInstance); clearTimeout(sendLoopInstance);
} else { // } else {
logger.debug("Starting new send loop with linger [%s]", linger) // logger.debug("Starting new send loop with linger [%s]", linger)
} }
sendLoopInstance = setTimeout(sendMessagesAsBatch, linger); sendLoopInstance = setTimeout(sendMessagesAsBatch, linger);
} }
async function sendMessagesAsBatch(isImmediately) { async function sendMessagesAsBatch(isImmediately) {
if (sendLoopInstance) { if (sendLoopInstance) {
logger.debug("sendMessagesAsBatch: Clear sendLoop scheduler. Starting new send loop with linger [%s]", linger); // logger.debug("sendMessagesAsBatch: Clear sendLoop scheduler. Starting new send loop with linger [%s]", linger);
clearTimeout(sendLoopInstance); clearTimeout(sendLoopInstance);
} }
sendLoopInstance = null; sendLoopInstance = null;

View File

@ -16,6 +16,7 @@
package org.thingsboard.rule.engine.transform; package org.thingsboard.rule.engine.transform;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.thingsboard.rule.engine.api.TbContext; import org.thingsboard.rule.engine.api.TbContext;
import org.thingsboard.rule.engine.api.TbNode; import org.thingsboard.rule.engine.api.TbNode;
@ -49,7 +50,7 @@ public abstract class TbAbstractTransformNode implements TbNode {
withCallback(transform(ctx, msg), withCallback(transform(ctx, msg),
m -> transformSuccess(ctx, msg, m), m -> transformSuccess(ctx, msg, m),
t -> transformFailure(ctx, msg, t), t -> transformFailure(ctx, msg, t),
ctx.getDbCallbackExecutor()); MoreExecutors.directExecutor());
} }
protected void transformFailure(TbContext ctx, TbMsg msg, Throwable t) { protected void transformFailure(TbContext ctx, TbMsg msg, Throwable t) {