JS executor code refactor
This commit is contained in:
parent
99b53f8c08
commit
7019b98c00
@ -20,7 +20,7 @@
|
||||
"config": "^3.3.7",
|
||||
"express": "^4.18.1",
|
||||
"js-yaml": "^4.1.0",
|
||||
"kafkajs": "^2.0.2",
|
||||
"kafkajs": "^2.1.0",
|
||||
"long": "^5.2.0",
|
||||
"uuid-parse": "^1.1.0",
|
||||
"uuid-random": "^1.3.2",
|
||||
|
||||
@ -54,11 +54,12 @@ export class AwsSqsTemplate implements IQueue {
|
||||
FifoQueue: 'true'
|
||||
};
|
||||
|
||||
name = 'AWS SQS';
|
||||
|
||||
constructor() {
|
||||
}
|
||||
|
||||
async init() {
|
||||
try {
|
||||
this.sqsClient = new SQSClient({
|
||||
apiVersion: '2012-11-05',
|
||||
credentials: {
|
||||
@ -124,11 +125,6 @@ export class AwsSqsTemplate implements IQueue {
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e: any) {
|
||||
this.logger.error('Failed to start ThingsBoard JavaScript Executor Microservice: %s', e.message);
|
||||
this.logger.error(e.stack);
|
||||
await this.destroy(-1);
|
||||
}
|
||||
}
|
||||
|
||||
async send(responseTopic: string, scriptId: string, rawResponse: Buffer, headers: any): Promise<any> {
|
||||
@ -185,15 +181,8 @@ export class AwsSqsTemplate implements IQueue {
|
||||
return result.QueueUrl || '';
|
||||
}
|
||||
|
||||
static async build(): Promise<AwsSqsTemplate> {
|
||||
const queue = new AwsSqsTemplate();
|
||||
await queue.init();
|
||||
return queue;
|
||||
}
|
||||
|
||||
async destroy(status: number): Promise<void> {
|
||||
async destroy(): Promise<void> {
|
||||
this.stopped = true;
|
||||
this.logger.info('Exiting with status: %d ...', status);
|
||||
this.logger.info('Stopping AWS SQS resources...');
|
||||
if (this.sqsClient) {
|
||||
this.logger.info('Stopping AWS SQS client...');
|
||||
@ -208,6 +197,5 @@ export class AwsSqsTemplate implements IQueue {
|
||||
}
|
||||
}
|
||||
this.logger.info('AWS SQS resources stopped.')
|
||||
process.exit(status);
|
||||
}
|
||||
}
|
||||
|
||||
@ -51,11 +51,12 @@ export class KafkaTemplate implements IQueue {
|
||||
private batchMessages: TopicMessages[] = [];
|
||||
private sendLoopInstance: NodeJS.Timeout;
|
||||
|
||||
name = 'Kafka';
|
||||
|
||||
constructor() {
|
||||
}
|
||||
|
||||
async init(): Promise<void> {
|
||||
try {
|
||||
const kafkaBootstrapServers: string = config.get('kafka.bootstrap.servers');
|
||||
const requestTopic: string = config.get('request_topic');
|
||||
const useConfluent = config.get('kafka.use_confluent_cloud');
|
||||
@ -121,7 +122,7 @@ export class KafkaTemplate implements IQueue {
|
||||
this.logger.error(`Got consumer CRASH event, should restart: ${e.payload.restart}`);
|
||||
if (!e.payload.restart) {
|
||||
this.logger.error('Going to exit due to not retryable error!');
|
||||
await this.destroy(-1);
|
||||
await this.destroy();
|
||||
}
|
||||
});
|
||||
|
||||
@ -146,13 +147,7 @@ export class KafkaTemplate implements IQueue {
|
||||
messageProcessor.onJsInvokeMessage(msg);
|
||||
},
|
||||
});
|
||||
|
||||
} catch (e: any) {
|
||||
this.logger.error('Failed to start ThingsBoard JavaScript Executor Microservice: %s', e.message);
|
||||
this.logger.error(e.stack);
|
||||
await this.destroy(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async send(responseTopic: string, scriptId: string, rawResponse: Buffer, headers: any): Promise<any> {
|
||||
this.logger.debug('Pending queue response, scriptId: [%s]', scriptId);
|
||||
@ -232,15 +227,7 @@ export class KafkaTemplate implements IQueue {
|
||||
}, this.linger);
|
||||
}
|
||||
|
||||
static async build(): Promise<KafkaTemplate> {
|
||||
const queue = new KafkaTemplate();
|
||||
await queue.init();
|
||||
return queue;
|
||||
}
|
||||
|
||||
|
||||
async destroy(status: number): Promise<void> {
|
||||
this.logger.info('Exiting with status: %d ...', status);
|
||||
async destroy(): Promise<void> {
|
||||
this.logger.info('Stopping Kafka resources...');
|
||||
|
||||
if (this.kafkaAdmin) {
|
||||
@ -267,7 +254,6 @@ export class KafkaTemplate implements IQueue {
|
||||
}
|
||||
}
|
||||
this.logger.info('Kafka resources stopped.');
|
||||
process.exit(status);
|
||||
}
|
||||
|
||||
private async disconnectProducer(): Promise<void> {
|
||||
@ -287,4 +273,5 @@ export class KafkaTemplate implements IQueue {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -34,11 +34,12 @@ export class PubSubTemplate implements IQueue {
|
||||
private topics: string[] = [];
|
||||
private subscriptions: string[] = [];
|
||||
|
||||
name = 'Pub/Sub';
|
||||
|
||||
constructor() {
|
||||
}
|
||||
|
||||
async init() {
|
||||
try {
|
||||
this.pubSubClient = new PubSub({
|
||||
projectId: this.projectId,
|
||||
credentials: this.credentials
|
||||
@ -77,12 +78,6 @@ export class PubSubTemplate implements IQueue {
|
||||
};
|
||||
|
||||
subscription.on('message', messageHandler);
|
||||
|
||||
} catch (e: any) {
|
||||
this.logger.error('Failed to start ThingsBoard JavaScript Executor Microservice: %s', e.message);
|
||||
this.logger.error(e.stack);
|
||||
await this.destroy(-1);
|
||||
}
|
||||
}
|
||||
|
||||
async send(responseTopic: string, scriptId: string, rawResponse: Buffer, headers: any): Promise<any> {
|
||||
@ -146,14 +141,7 @@ export class PubSubTemplate implements IQueue {
|
||||
}
|
||||
}
|
||||
|
||||
static async build(): Promise<PubSubTemplate> {
|
||||
const queue = new PubSubTemplate();
|
||||
await queue.init();
|
||||
return queue;
|
||||
}
|
||||
|
||||
async destroy(status: number): Promise<void> {
|
||||
this.logger.info('Exiting with status: %d ...', status);
|
||||
async destroy(): Promise<void> {
|
||||
this.logger.info('Stopping Pub/Sub resources...');
|
||||
if (this.pubSubClient) {
|
||||
this.logger.info('Stopping Pub/Sub client...');
|
||||
@ -168,7 +156,6 @@ export class PubSubTemplate implements IQueue {
|
||||
}
|
||||
}
|
||||
this.logger.info('Pub/Sub resources stopped.');
|
||||
process.exit(status);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -15,7 +15,8 @@
|
||||
///
|
||||
|
||||
export interface IQueue {
|
||||
name: string;
|
||||
init(): Promise<void>;
|
||||
send(responseTopic: string, scriptId: string, rawResponse: Buffer, headers: any): Promise<any>;
|
||||
destroy(status: number): Promise<void>;
|
||||
destroy(): Promise<void>;
|
||||
}
|
||||
|
||||
@ -44,11 +44,12 @@ export class RabbitMqTemplate implements IQueue {
|
||||
private stopped = false;
|
||||
private topics: string[] = [];
|
||||
|
||||
name = 'RabbitMQ';
|
||||
|
||||
constructor() {
|
||||
}
|
||||
|
||||
async init(): Promise<void> {
|
||||
try {
|
||||
const url = `amqp://${this.username}:${this.password}@${this.host}:${this.port}${this.vhost}`;
|
||||
this.connection = await amqp.connect(url);
|
||||
this.channel = await this.connection.createConfirmChannel();
|
||||
@ -73,11 +74,6 @@ export class RabbitMqTemplate implements IQueue {
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e: any) {
|
||||
this.logger.error('Failed to start ThingsBoard JavaScript Executor Microservice: %s', e.message);
|
||||
this.logger.error(e.stack);
|
||||
await this.destroy(-1);
|
||||
}
|
||||
}
|
||||
|
||||
async send(responseTopic: string, scriptId: string, rawResponse: Buffer, headers: any): Promise<any> {
|
||||
@ -112,14 +108,7 @@ export class RabbitMqTemplate implements IQueue {
|
||||
return this.channel.assertQueue(topic, this.queueOptions);
|
||||
}
|
||||
|
||||
static async build(): Promise<RabbitMqTemplate> {
|
||||
const queue = new RabbitMqTemplate();
|
||||
await queue.init();
|
||||
return queue;
|
||||
}
|
||||
|
||||
async destroy(status: number) {
|
||||
this.logger.info('Exiting with status: %d ...', status);
|
||||
async destroy() {
|
||||
this.logger.info('Stopping RabbitMQ resources...');
|
||||
|
||||
if (this.channel) {
|
||||
@ -144,7 +133,6 @@ export class RabbitMqTemplate implements IQueue {
|
||||
}
|
||||
}
|
||||
this.logger.info('RabbitMQ resources stopped.')
|
||||
process.exit(status);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -44,11 +44,12 @@ export class ServiceBusTemplate implements IQueue {
|
||||
private receiver: ServiceBusReceiver;
|
||||
private senderMap = new Map<string, ServiceBusSender>();
|
||||
|
||||
name = 'Azure Service Bus';
|
||||
|
||||
constructor() {
|
||||
}
|
||||
|
||||
async init() {
|
||||
try {
|
||||
const connectionString = `Endpoint=sb://${this.namespaceName}.servicebus.windows.net/;SharedAccessKeyName=${this.sasKeyName};SharedAccessKey=${this.sasKey}`;
|
||||
this.sbClient = new ServiceBusClient(connectionString)
|
||||
this.serviceBusService = new ServiceBusAdministrationClient(connectionString);
|
||||
@ -79,11 +80,6 @@ export class ServiceBusTemplate implements IQueue {
|
||||
this.logger.error('Failed to receive message from queue.', error);
|
||||
};
|
||||
this.receiver.subscribe({processMessage: messageHandler, processError: errorHandler})
|
||||
} catch (e: any) {
|
||||
this.logger.error('Failed to start ThingsBoard JavaScript Executor Microservice: %s', e.message);
|
||||
this.logger.error(e.stack);
|
||||
await this.destroy(-1);
|
||||
}
|
||||
}
|
||||
|
||||
async send(responseTopic: string, scriptId: string, rawResponse: Buffer, headers: any): Promise<any> {
|
||||
@ -133,14 +129,7 @@ export class ServiceBusTemplate implements IQueue {
|
||||
}
|
||||
}
|
||||
|
||||
static async build(): Promise<ServiceBusTemplate> {
|
||||
const queue = new ServiceBusTemplate();
|
||||
await queue.init();
|
||||
return queue;
|
||||
}
|
||||
|
||||
async destroy(status: number) {
|
||||
this.logger.info('Exiting with status: %d ...', status);
|
||||
async destroy() {
|
||||
this.logger.info('Stopping Azure Service Bus resources...')
|
||||
if (this.receiver) {
|
||||
this.logger.info('Stopping Service Bus Receiver...');
|
||||
@ -181,6 +170,5 @@ export class ServiceBusTemplate implements IQueue {
|
||||
}
|
||||
}
|
||||
this.logger.info('Azure Service Bus resources stopped.')
|
||||
process.exit(status);
|
||||
}
|
||||
}
|
||||
|
||||
@ -30,50 +30,57 @@ logger.info('===CONFIG BEGIN===');
|
||||
logger.info(JSON.stringify(config, null, 4));
|
||||
logger.info('===CONFIG END===');
|
||||
|
||||
const serviceType = config.get('queue_type');
|
||||
const serviceType: string = config.get('queue_type');
|
||||
const httpPort = Number(config.get('http_port'));
|
||||
let queues: IQueue | null;
|
||||
let httpServer: HttpServer | null;
|
||||
|
||||
(async () => {
|
||||
logger.info('Starting ThingsBoard JavaScript Executor Microservice...');
|
||||
switch (serviceType) {
|
||||
case 'kafka':
|
||||
logger.info('Starting Kafka template...');
|
||||
queues = await KafkaTemplate.build();
|
||||
logger.info('Kafka template started.');
|
||||
break;
|
||||
case 'pubsub':
|
||||
logger.info('Starting Pub/Sub template...')
|
||||
queues = await PubSubTemplate.build();
|
||||
logger.info('Pub/Sub template started.')
|
||||
break;
|
||||
case 'aws-sqs':
|
||||
logger.info('Starting AWS SQS template...')
|
||||
queues = await AwsSqsTemplate.build();
|
||||
logger.info('AWS SQS template started.')
|
||||
break;
|
||||
case 'rabbitmq':
|
||||
logger.info('Starting RabbitMQ template...')
|
||||
queues = await RabbitMqTemplate.build();
|
||||
logger.info('RabbitMQ template started.')
|
||||
break;
|
||||
case 'service-bus':
|
||||
logger.info('Starting Azure Service Bus template...')
|
||||
queues = await ServiceBusTemplate.build();
|
||||
logger.info('Azure Service Bus template started.')
|
||||
break;
|
||||
default:
|
||||
logger.error('Unknown service type: ', serviceType);
|
||||
process.exit(-1);
|
||||
try {
|
||||
queues = await createQueue(serviceType);
|
||||
logger.info(`Starting ${queues.name} template...`);
|
||||
await queues.init();
|
||||
logger.info(`${queues.name} template started.`);
|
||||
httpServer = new HttpServer(httpPort);
|
||||
} catch (e: any) {
|
||||
logger.error('Failed to start ThingsBoard JavaScript Executor Microservice: %s', e.message);
|
||||
logger.error(e.stack);
|
||||
await exit(-1);
|
||||
}
|
||||
|
||||
httpServer = new HttpServer(httpPort);
|
||||
})();
|
||||
|
||||
async function createQueue(serviceType: string): Promise<IQueue> {
|
||||
switch (serviceType) {
|
||||
case 'kafka':
|
||||
return new KafkaTemplate();
|
||||
case 'pubsub':
|
||||
return new PubSubTemplate();
|
||||
case 'aws-sqs':
|
||||
return new AwsSqsTemplate();
|
||||
case 'rabbitmq':
|
||||
return new RabbitMqTemplate();
|
||||
case 'service-bus':
|
||||
return new ServiceBusTemplate();
|
||||
default:
|
||||
throw new Error('Unknown service type: ' + serviceType);
|
||||
}
|
||||
}
|
||||
|
||||
[`SIGINT`, `SIGUSR1`, `SIGUSR2`, `uncaughtException`, `SIGTERM`].forEach((eventType) => {
|
||||
process.on(eventType, async () => {
|
||||
logger.info(`${eventType} signal received`);
|
||||
await exit(0);
|
||||
})
|
||||
})
|
||||
|
||||
process.on('exit', (code: number) => {
|
||||
logger.info(`ThingsBoard JavaScript Executor Microservice has been stopped. Exit code: ${code}.`);
|
||||
});
|
||||
|
||||
async function exit(status: number) {
|
||||
logger.info('Exiting with status: %d ...', status);
|
||||
if (httpServer) {
|
||||
const _httpServer = httpServer;
|
||||
httpServer = null;
|
||||
@ -82,11 +89,7 @@ let httpServer: HttpServer | null;
|
||||
if (queues) {
|
||||
const _queues = queues;
|
||||
queues = null;
|
||||
await _queues.destroy(0);
|
||||
await _queues.destroy();
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
process.on('exit', (code: number) => {
|
||||
logger.info(`JavaScript Executor Microservice has been stopped. Exit code: ${code}.`);
|
||||
});
|
||||
process.exit(status);
|
||||
}
|
||||
|
||||
@ -2670,10 +2670,10 @@ jws@^4.0.0:
|
||||
jwa "^2.0.0"
|
||||
safe-buffer "^5.0.1"
|
||||
|
||||
kafkajs@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/kafkajs/-/kafkajs-2.0.2.tgz#cdfc8f57aa4fd69f6d9ca1cce4ee89bbc2a3a1f9"
|
||||
integrity sha512-g6CM3fAenofOjR1bfOAqeZUEaSGhNtBscNokybSdW1rmIKYNwBPC9xQzwulFJm36u/xcxXUiCl/L/qfslapihA==
|
||||
kafkajs@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/kafkajs/-/kafkajs-2.1.0.tgz#32ede4e8080cc75586c5e4406eeb582fa73f7b1e"
|
||||
integrity sha512-6IYiOdGWvFPbSbVB+AV3feT+A7vzw5sXm7Ze4QTfP7FRNdY8pGcpiNPvD2lfgYFD8Dm9KbMgBgTt2mf8KaIkzw==
|
||||
|
||||
keyv@^3.0.0:
|
||||
version "3.1.0"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user