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 {
protected static final String REQUEST_ID_HEADER = "requestId";
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) {
ByteBuffer buf = ByteBuffer.allocate(16);

View File

@ -56,6 +56,7 @@ public class DefaultTbQueueRequestTemplate<Request extends TbQueueMsg, Response
final boolean internalExecutor;
final ExecutorService executor;
final long maxRequestTimeoutNs;
final long maxRequestTimeout;
final long maxPendingRequests;
final long pollInterval;
volatile boolean stopped = false;
@ -76,6 +77,7 @@ public class DefaultTbQueueRequestTemplate<Request extends TbQueueMsg, Response
this.requestTemplate = requestTemplate;
this.responseTemplate = responseTemplate;
this.maxRequestTimeoutNs = TimeUnit.MILLISECONDS.toNanos(maxRequestTimeout);
this.maxRequestTimeout = maxRequestTimeout;
this.maxPendingRequests = maxPendingRequests;
this.pollInterval = pollInterval;
this.internalExecutor = (executor == null);
@ -170,7 +172,7 @@ public class DefaultTbQueueRequestTemplate<Request extends TbQueueMsg, Response
log.error("[{}] Missing requestId in header and body", response);
} else {
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);
if (expectedResponse == null) {
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();
request.getHeaders().put(REQUEST_ID_HEADER, uuidToBytes(requestId));
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();
SettableFuture<Response> future = SettableFuture.create();
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 -> {
long currentTime = System.currentTimeMillis();
long requestTime = bytesToLong(request.getHeaders().get(REQUEST_TIME));
if (requestTime + requestTimeout >= currentTime) {
long expireTs = bytesToLong(request.getHeaders().get(EXPIRE_TS_HEADER));
if (expireTs >= currentTime) {
byte[] requestIdHeader = request.getHeaders().get(REQUEST_ID_HEADER);
if (requestIdHeader == null) {
log.error("[{}] Missing requestId in header", request);

View File

@ -21,6 +21,7 @@ const TIMEOUT_ERROR = 2;
const UNRECOGNIZED = -1;
const config = require('config'),
Long = require('long'),
logger = require('../config/logger')._logger('JsInvokeMessageProcessor'),
Utils = require('./utils'),
JsExecutor = require('./jsExecutor');
@ -49,6 +50,7 @@ JsInvokeMessageProcessor.prototype.onJsInvokeMessage = function (message) {
var tStart = performance.now();
let requestId;
let responseTopic;
let expireTs;
let headers;
let request;
let buf;
@ -59,6 +61,20 @@ JsInvokeMessageProcessor.prototype.onJsInvokeMessage = function (message) {
requestId = Utils.UUIDFromBuffer(buf);
buf = Buffer.from(headers.data['responseTopic']);
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);
@ -140,7 +156,7 @@ JsInvokeMessageProcessor.prototype.processInvokeRequest = function (requestId, r
(result) => {
var invokeResponse = createInvokeResponse(result, true);
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) => {
var errorCode;
@ -151,14 +167,14 @@ JsInvokeMessageProcessor.prototype.processInvokeRequest = function (requestId, r
}
var invokeResponse = createInvokeResponse("", false, errorCode, err);
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) => {
var invokeResponse = createInvokeResponse("", false, COMPILATION_ERROR, err);
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);
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) {
@ -276,7 +292,7 @@ function createReleaseResponse(scriptId, success) {
function parseJsErrorDetails(err) {
if (!err) {
return '';
return undefined;
}
var details = err.name + ': ' + err.message;
if (err.stack) {

View File

@ -65,15 +65,15 @@ async function pushMessageToSendLater(message) {
function sendLoopWithLinger() {
if (sendLoopInstance) {
clearTimeout(sendLoopInstance);
} else {
logger.debug("Starting new send loop with linger [%s]", linger)
// } else {
// logger.debug("Starting new send loop with linger [%s]", linger)
}
sendLoopInstance = setTimeout(sendMessagesAsBatch, linger);
}
async function sendMessagesAsBatch(isImmediately) {
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);
}
sendLoopInstance = null;

View File

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