@cn-shell/aws-utils
Version:
A Cloud Native extension for AWS
200 lines (199 loc) • 5.74 kB
JavaScript
"use strict";
var __importDefault =
(this && this.__importDefault) ||
function(mod) {
return mod && mod.__esModule ? mod : { default: mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Receiver = exports.Sender = void 0;
// imports here
const aws_base_1 = require("./aws-base");
const sqs_1 = __importDefault(require("aws-sdk/clients/sqs"));
// import AWS from "aws-sdk/global";
// AWS.config.logger = console;
// SQS consts here
const SQS_API_VER = "2012-11-05";
const MIN_BATCH_SIZE = 10;
// Class Sender here
class Sender extends aws_base_1.Base {
// Constructor here
constructor(name, opts) {
super(name, opts);
this._queue = opts.queue;
this._fifo = opts.fifo === undefined ? false : opts.fifo; // default to false
this.info("Queue: %s", this._queue);
// Create AWS service objects
this._sqs = new sqs_1.default({
region: this._region,
apiVersion: SQS_API_VER,
});
}
// Public and Private methods here
async start() {
return true;
}
async injectMessage(msg) {
let parsed = JSON.parse(msg);
return await this.sendMessage(parsed.msg, parsed.attribs);
}
async sendMessage(msg, attribs, msgGroupID) {
if (this._playbackFile !== "") {
this.writePlayback(
JSON.stringify({ msg, attribs }),
aws_base_1.Base.RecordTypes.SQS_SENDER,
);
}
let params = {
QueueUrl: this._queue,
MessageBody: msg,
MessageAttributes: attribs,
};
if (this._fifo) {
if (msgGroupID !== undefined) {
params.MessageGroupId = msgGroupID;
} else {
params.MessageGroupId = this._queue;
}
}
let success = true;
await this._sqs
.sendMessage(params)
.promise()
.catch(e => {
this.error("sendMessage Error: %s", e);
success = false;
});
return success;
}
async stop() {}
async healthCheck() {
return true;
}
}
exports.Sender = Sender;
// Class Receiver here
class Receiver extends aws_base_1.Base {
// Constructor here
constructor(name, opts) {
super(name, opts);
this._queue = opts.queue;
this.info("Queue: %s", this._queue);
this._pollInterval = opts.pollInterval;
this.info("PollInterval (s): %s", this._pollInterval);
this._backoffInterval = opts.backoffInterval;
this.info("BackoffInterval (s): %s", this._backoffInterval);
this._processMessages = opts.msgProcesser;
this._nowReceiving = false;
this._stopNow = false;
// Create AWS service objects
this._sqs = new sqs_1.default({
region: this._region,
apiVersion: SQS_API_VER,
});
}
// Public and Private methods here
async start() {
setImmediate(() => this.startReceiving());
return true;
}
async startReceiving() {
let processed = 0;
this._nowReceiving = true;
const rcvParams = {
QueueUrl: this._queue,
AttributeNames: ["All"],
MaxNumberOfMessages: MIN_BATCH_SIZE,
MessageAttributeNames: ["All"],
WaitTimeSeconds: this._pollInterval,
};
// If we have received msgs and we have not received a stop request
// then keep checking for more msgs
do {
// Check if there are any message in the queue
let data = await this._sqs
.receiveMessage(rcvParams)
.promise()
.catch(e => {
this.error("receiveMessage Error: %s", e);
});
if (
data === null ||
data === undefined ||
data.Messages === undefined ||
data.Messages.length === 0
) {
processed = 0;
} else {
processed = await this.receiveMessage(data.Messages);
}
} while (processed > 0 && !this._stopNow);
// If we have not received a request to stop then backoff for a while
// before checking if anymore msgs have come in
if (!this._stopNow) {
setTimeout(() => this.startReceiving(), this._backoffInterval * 1000);
}
this._nowReceiving = false;
}
async injectMessages(msgs) {
return await this.receiveMessage(JSON.parse(msgs));
}
async receiveMessage(msgs) {
// Check if we are currently recording a playback
if (this._playbackFile !== "") {
this.writePlayback(
JSON.stringify(msgs),
aws_base_1.Base.RecordTypes.SQS_RECEIVER,
);
}
// Process msgs in a batch
let msgsProcessed = await this._processMessages(msgs);
if (msgsProcessed.length === 0) {
return 0;
}
let delParams = {
QueueUrl: this._queue,
Entries: [],
};
// Only delete the messages that have been marked processed
for (let i of msgsProcessed) {
delParams.Entries.push({
Id: `${i}`,
ReceiptHandle: msgs[i].ReceiptHandle,
});
}
// Delete the messages that have been processed
await this._sqs
.deleteMessageBatch(delParams)
.promise()
.catch(e => {
this.error("deleteMessage Error: %s", e);
});
return msgsProcessed.length;
}
async stop() {
this.info("Attempting to stop receiving ..,");
this._stopNow = true;
// Return a promise so that the calling method can use 'await'
return new Promise(resolve => {
this.stopReceiving(resolve);
});
}
stopReceiving(resolve) {
// If we are currently NOT reading from the queue then stop,
// i.e. resolve the promise
if (this._nowReceiving) {
// If we are currently reading from the queue try again in 1000 ms
setTimeout(() => {
this.stopReceiving(resolve);
}, 1000);
} else {
this.info("Stopped receiving!");
this._stopNow = false;
resolve();
}
}
async healthCheck() {
return true;
}
}
exports.Receiver = Receiver;