@webda/gcp
Version:
Webda GCP Services implementation
133 lines • 3.93 kB
JavaScript
import { PubSub } from "@google-cloud/pubsub";
import { CancelablePromise, Queue, QueueParameters } from "@webda/core";
/**
* GCPQueue Parameters
*/
export class GCPQueueParameters extends QueueParameters {
}
/**
* GCP Queue implementation on top of Pub/Sub
*
* @WebdaModda GoogleCloudQueue
*/
export default class GCPQueue extends Queue {
constructor() {
super(...arguments);
this.messages = {};
}
/**
* @override
*/
loadParameters(params) {
return new GCPQueueParameters(params);
}
/**
* @override
*/
async init() {
await super.init();
this.pubsub = new PubSub();
this.projectId = this.pubsub.auth.getProjectId();
return this;
}
/**
* The queue size is not available within this service
*
* @returns
*/
async size() {
return 0;
}
/**
* Acknowledge a message
* @param id
*/
async deleteMessage(id) {
await this.pubsub.auth.request({
method: "POST",
url: `https://pubsub.googleapis.com/v1/projects/${await this.projectId}/subscriptions/${this.parameters.subscription}:acknowledge`,
body: JSON.stringify({
ackIds: [id]
})
});
this.messages[id].ack();
delete this.messages[id];
}
/**
* Send a message to the queue
* @param msg
*/
async sendMessage(msg) {
await this.pubsub.topic(this.parameters.topic).publishMessage({ data: Buffer.from(JSON.stringify(msg)) });
}
/**
* Retrieve just one message from the queue
* @param proto
* @returns
*/
async receiveMessage(proto) {
let timeoutId;
let errorHandler;
let msgHandler;
const subscription = this.pubsub.subscription(this.parameters.subscription, {
flowControl: {
maxMessages: 1
}
});
try {
return await new Promise((resolve, reject) => {
if (this.parameters.timeout) {
timeoutId = setTimeout(() => resolve([]), this.parameters.timeout);
}
errorHandler = err => {
reject(err);
};
msgHandler = (message) => {
this.messages[message.ackId] = message;
resolve([
{
Message: this.unserialize(message.data.toString(), proto),
ReceiptHandle: message.ackId
}
]);
};
subscription.on("error", errorHandler);
subscription.on("message", msgHandler);
});
}
finally {
subscription.close();
if (timeoutId) {
clearTimeout(timeoutId);
}
}
}
/**
* Work a queue calling the callback with every Event received
* If the callback is called without exception the `deleteMessage` is called
* @param callback
* @param eventPrototype
*/
consume(callback, eventPrototype) {
const subscription = this.pubsub.subscription(this.parameters.subscription, {
flowControl: {
maxMessages: this.getMaxConsumers()
}
});
return new CancelablePromise(async () => {
subscription.on("message", async (message) => {
try {
await callback(this.unserialize(message.data.toString(), eventPrototype));
message.ack();
}
catch (err) {
this.log("ERROR", `Message ${message.ackId}`, err);
}
});
}, async () => {
subscription.close();
});
}
}
export { GCPQueue };
//# sourceMappingURL=queue.js.map