We are using Cloud Function to process images and sending a notification to PubSub once processing is complete. The function is built using nodejs 8 [beta]
Here's the snippet:
const PubSubMessage = require('#google-cloud/pubsub');
const pubsub = new PubSubMessage();
const htmlData = JSON.stringify({ url: url, html: Buffer.from(html).toString('base64') });
const htmlDataBuffer = Buffer.from(htmlData);
pubsub
.topic("projects/<project-id>/topics/<name>")
.publisher()
.publish(htmlDataBuffer)
.then(messageId => {
console.log('Message ${messageId} published.');
})
.catch(err => {
console.error('ERROR in sending to pubsub:', err);
console.log('ERROR in sending to pubsub:', err);
});
The message does get published to the PubSub queue, however, it is pushed ~90 seconds after the image processing is complete.
Any idea why pushing message to PubSub might be taking so long?
-anurag
Related
I'm using GCP PubSub (push subscription to be precisely), and Cloud Run to execute subscribed messages.
Recently I've noticed that Cloud Run executes a same message for five times.
I see there is a retry policy for a subscription which its message has been unhandled (or mishandled), but Cloud Run clearly is giving 200 OK response.
So it seems that sending 200 OK response is not enough, but I cannot find a way to send ack sign properly.
Here's the code to publish message.
function publish(message: string) {
const pubsub = new PubSub({ projectId: 'my-project' });
const dataBuffer = Buffer.from(message);
const topicName = 'my-topic';
pubsub
.topic(topicName)
.publish(dataBuffer)
.then((messageId) => {
console.log(`Message ${messageId} published`);
})
.catch((err) => {
console.log(err);
});
}
publish(JSON.stringify({ foo : 'bar' }));
And here's the code of Cloud Run.
// express app
app.post('/run', async (req, res) => {
try {
const body = req.body.message ? Buffer.from(req.body.message.data, 'base64').toString() : req.body;
// req.body came out to be "{"foo":"bar"}"
const deliveredMessage = JSON.parse(body);
// do something
// Do I have to do something like message.ack() here?
return res.status(200).end();
} catch (e) {
return res.status(502).end();
}
});
These are example responses of Cloud Run retrying.
Here's a graph of unacked messages at that time.
Is your cloud run app running when you did the post?
Because there is a timeout for the messages waiting in the queue, maybe pub/sub is resending the messages before you start to consuming it.
Another thing you can try is putting the response at the first line, like:
app.post('/run', async (req, res) => {
try {
res.status(200)
...
I need a way to get notified when the task finished rather it failed or Load complete
const dms : AWS.DMS;
const params = {
StartReplicationTaskType: "reload-target",
ReplicationTaskArn:
"MyArn",
};
dms.startReplicationTask(
params,
(err: AWS.AWSError, data: AWS.DMS.StartReplicationTaskResponse) => {
if (err) {
console.log("failed_with_error", err);
}
if (data) {
console.log("success ", data);
}
}
);
after the task started I got response on the data object with status: starting
but it's not updated with the other status.
I tried waitFor to track status changing but its not working
create event subscription under DMS --> Event subscriptions
then create Lambda function triggered by that event subscription
I have a SeedIndicatorInformationSQS-dev.fifo queue (FiFo) that connects to a SeedIndicatorInformationSQS-dev-d13dfe0 lambda. I'd like to send a message within the SeedIndicatorInformationSQS-dev-d13dfe0 lambda to the EvaluationConfigSQS-dev standard queue. But no messages are being sent/received. Whereas if I try sending it from a non-SQS connected lambda (via AppSync) it works.
The SeedIndicatorInformationSQS-dev-d13dfe0 lambda has the following permissions:
I have checked:
That the lambda has the right access to send SQS messages (you can see it there).
That the EvaluationConfigSQS-devstandard queue is correctly configured as I've successfully sent messages to it from another lambda (non-SQS).
That the SQS URL is correct.
That no errors are shown in the console.
That async/await are correctly placed (I've tried both with and without them)
Here's the CloudWatch log for the SeedIndicatorInformationSQS-dev-d13dfe0lambda trying to dispatch the content: Successfully sent to the right URL, JSON parsed to string, but nothing.
Here's the CloudWatch Log: You can see. SeedIndicatorInformationSQS-dev-d13dfe0 successfully receives the message from another lambda function and processes it, but no further messages are sent.
No errors reported within SeedIndicatorInformationSQS-dev-d13dfe0
No logs within EvaluationConfigSQS-dev
But, if I try to send it within a non-SQS lambda, it works.
Received event:
This is the classes-dev-eefa2af lambda that sends successfully to EvaluationConfigSQS-dev (and coincidentally is the one which triggers the SeedIndicatorInfromationSQS-dev.fifo SQS.
Here are the permissions for EvaluationConfigSQS-dev-6da8b90 (lambda that the EvaluationConfigSQS-dev standard queue triggers)
By any chance, do I need to add special permissions to the SeedIndicatorInformatioNSQS-dev.fifo queue?
Here's the JS that gets dispatched (I'm using a mediator pattern, and it's successfully getting dispatched, you can see it in the logs above "Dispatching CREATED_INSTITUTION_CLASS". I have also managed to print the URL and verified that it's actually the one that corresponds to it.
export async function institutionClassCreatedEventHandler(
evt: InstitutionClassCreatedEvent
) {
const json = JSON.stringify({
...evt,
type: "CLASS_CREATED",
});
sqsDispatchMessage(
"InstitutionClassCreatedEvent",
evt.tenantId + evt.subject.id,
json,
Config.SQS.evaluationConfigSQS.url,
false
);
}
Here's the sqsDispatchMessage function. As you can see, there's a catch block that will print me whenever there's an error (and it works). But so far, no error has been recorded.
export async function sqsDispatchMessage(
eventName: string,
uniqueId: string,
jsonObjStringifiedToSend: string,
sqsURL: string,
isFifoQueue: boolean = true
) {
try {
await sqs
.sendMessage({
MessageAttributes: {
EventName: {
DataType: "String",
StringValue: eventName,
},
},
...(isFifoQueue && { MessageGroupId: eventName }),
MessageBody: jsonObjStringifiedToSend,
QueueUrl: sqsURL,
...(isFifoQueue && { MessageDeduplicationId: uniqueId }),
})
.promise();
} catch (e) {
console.error(`Error While Sending the ${eventName}`);
console.error(e.message);
console.log(jsonObjStringifiedToSend);
}
}
Any ideas? Is it even possible?
The problem was in my dispatcher:
It used to be like this:
export async function dispatchOfEvents({
type,
evtArgs,
}: MediatorEvents): Promise<void> {
logTime(type);
(events as any)[type].forEach((evt: Function) => {
evt(evtArgs);
});
}
I changed it to:
export async function dispatchOfEvents({
type,
evtArgs,
}: MediatorEvents): Promise<void> {
logTime(type);
const evts: Promise<any>[] = [];
for (const evt of (events as any)[type]) {
evts.push(evt(evtArgs));
}
await Promise.all(evts);
}
I am using AWS Websocket api-gateway. I am sending message to connected client by aws:execute-api:region:account-id:api-id/stage-name/POST/#connections.However, the message is getting delayed somehow and the UI won't be able to receive the chat message immediately. I don't why any suggestion where getting something wrong????
One thing very exceptional, when I am sending message, last message getting time.
Example : If I sent one message that take much time. If I send 1st message, as I sent second message, First message will received to client immediately but now 2nd second message take much time. SO basically when I am sending nth message, then every nth message will deliver to client when (n+1)th message sent and (n+1)th messages takes much time to deliver.
Your help much appreciated!!!
This is only Code Snippet which I have
import * as AWS from 'aws-sdk';
export class AWSWebsocketGateway {
websocketInstance;
constructor() {
AWS.config.update({
accessKeyId: <accessKeyId>,
secretAccessKey: <secretAccessKey>,
region: <region>
});
this.websocketInstance = new AWS.ApiGatewayManagementApi({
endpoint: <webSocketDomainName> + <webSocketStage>
});
}
sendMessage(connection, messageObject, callback: Function) {
messageObject = JSON.stringify(messageObject);
this.websocketInstance.postToConnection({ ConnectionId: connection, Data: JSON.stringify(messageObject) }, function (error, data) {
console.log('Error', error, 'Send Message...', data);
return callback(error, data);
});
}
}
I retrieving connection Id from DB in one query and calling this function in loop to send message.
For anyone else who get's bitten by this one ->
You need to wait for the API call to return it's result before finishing the lambda's execution.
E.g. this won't work
module.exports.ping = async (event) => {
... //setting up api gateway, etc
apig.postToConnection({ ConnectionId: connectionId, Data: JSON.stringify(message) }, (err, res) => {})
return {
statusCode: 200
}
}
But this will:
module.exports.ping = async (event) => {
... //setting up api gateway, etc
await apig.postToConnection({ ConnectionId: connectionId, Data: JSON.stringify(message) }).promise();
return {
statusCode: 200
}
}
Any async code that is executing after the return of the lambda appears to be paused til that handler is run again, which is why you see the delayed n+ issue you outlined above.
I have and preordered AWS snowball that has been ordered with all its events raised.
I need to know what the event is that is running (it will send a lambda when its shipped and when it arrives back to amazon, how can i get different operations for this?)
The Examples are too simple
my lambda is
var http = require('http');
exports.handler = function(event, context) {
var httpOptions = {
host: "myip",
port: '80',
path: "/createFirs",
method: "GET"
};
if (false) {
http.get(httpOptions, function(response) {
response.on('data', function (chunk) {
console.log(chunk);
//context.done(null, chunk);
context.succeed(event);
});
response.on('error', function(err) {
console.log(err);
context.done(err, null);
});
});
} else {
context.done(new Error("snowball lambda isn't complete yet"));
}
};
Information about AWS Import/Export Snowball jobs is available via the DescribeJob API.
There are also notifications generated by Snowball that are sent via Amazon SNS. Notifications include:
In transit
Delivered
Importing
Completed
You can subscribe an AWS Lambda function to an Amazon SNS topic, so that the Lambda function is called when the Snowball notification is received.