Independent ordered queues for job that is process exactly same way - queue

I am looking for a queuing tool to help me process jobs in order. I will use an example of user joining a website to help convey the problem, in real life they are more dull jobs which can each take up to 1 minute, there are several thousand users.
user1 - Registration -> Process Payment -> Upload photos -> Resize photos
user2 - Reset password -> Log in -> Upload photos -> Resize photos
The above jobs all need to be processed in order for that user. i.e. you can not process payment before the registration has finished. Each of these jobs is processed in the same way (fire of a http request to an external service).
If user 1 registration takes a long time their is no reason for user 2 to wait for his password reset. If I had multiple workers on a single queue the next job to be popped off could be anything so a users tasks may be processed in the wrong order.
At the moment I have a hacked together system which does this using a redis list but its not ideal and needs improvement. If there is an off the shelf tool or pattern which does this it would be great. I thought I could potentially programataclly create a new queue on rabbitmq for each user but felt it wasn't designed for that so much.

The answer is to use amqp message groups which are supported by some clients, I ended on using fairy as I am using nodejs already.

Related

How to Implement "Your contact just joined app" feature

I am building a mobile app (in flutter firebase, but the answer does not have to be firebase specific). And I would like to implement a feature that notifies users whenever anyone from their contact list joins the app. This seems like a very EXPENSIVE feature.
At the top of my head, I see a lambda/cloud function that is triggered everytime a user joins and then searches a database of users and their respective contacts for the existence of the new user's phone number. To me, this solution does not scale well for two reasons: if the number of total users is in the millions and the number of users joining simultaneously is a lot.
My better solution is to get the user's contacts upon joining and then searching a database of current users contacts for any of the phone numbers of the newly joined user.
Is there a solution better than the second one? If so, what is it? If the second solution is standard, what kind of backend storage mechanism provides the best search and retrieval time for a database of users and their respective contacts?
In the case of large users ill not do first solution because that may slow the sign up process instead i will creat a cron job that runs at a specific time or periodically it will get the list of the latest users signed up that day or that hour whatever you prefer then that cron will check the new user if related to any user in the databases and send a notification right away, or a better solution create a temporary table in a database in another server insert the notification informations into the other server, creat another cron job in the second server it will run at a specific time to sendthe notification

What to do if a RESTful api is only partly successful

In our design we have something of a paradox. We have a database of projects. Each project has a status. We have a REST api to change a project from “Ready” status to “Cleanup” status. Two things must happen.
update the status in the database
send out an email to the approvers
Currently RESTful api does 1, and if that is successful, do 2.
But sometimes the email fails to send. But since (1) is already committed, it is not possible to rollback.
I don't want to send the email prior to commit, because I want to make sure the commit is successful before sending the email.
I thought about undoing step 1, but that is very hard. The status change involves adding new records to the history table, so I need to delete them. And if another person make other changes concurrently, the undo might get messed up.
So what can I do? If (2) fails, should I return “200 OK” to the client?
Seems like the best option is to return “500 Server Error” with error message that says “The project status was changed. However, sending the email to the approvers failed. Please take appropriate action.”
Perhaps I should not try to do 1 + 2 in a single operation? But that just puts the burden on the client, which is worse!
Just some random thoughts:
You can have a notification sent status flag along with a datetime of submission. When an email is successful then it flips, if not then it stays. When changes are submitted then your code iterates through ALL unsent notifications and tries to send. No idea what backend db you are suing but I believe many have the functionality to send emails as well. You could have a scheduled Job (SQL Server Agent for MSSQL) that runs hourly and tries to send if the datetime of the submission is lapsed a certain amount or starts setting off alarms if it fails as well.
If ti is that insanely important then maybe you could integrate a third party service such as sendgrid to run as a backup sending mech. That of course would be more $$ though...
Traditionally I've always separated functions like this into a backend worker process that handles this kind of administrative tasking stuff across many different applications. Some notifications get sent out every morning. Some get sent out every 15 minutes. Some are weekly summaries. If I run into a crash and burn then I light up the event log and we are (lucky/unlucky) enough to have server monitoring tools that alert us on specified application events.

Facebook Messenger Send Api - send to a big amount of users

I have a bot over Facebook which people are subscribing for sports updates.
I have 1,000 - 10,000 users I want to send out an update to.
Currently, in small scales like 20 messages , I would use a Facebook Batch request.
But, i'm not sure what would be the best way to send my messages in a large scale.
My two options are:
Batch - limited to 50 requests per batch request.
I don't really know if I should expect a delay in the execution of the request.
Regular calls - I will iterate through my receivers and send each of them a message separately.
I'm afraid Facebook might block me for thinking i'm spamming, or I will exceed the rate limits.
I have to say I was expecting a more generic method coming from Facebook since they are allowing users to subscribe for update through my bot, hence, I was expecting them to provide a guide on what are the best practices for sending the update users subscribed for.
You should definitely use Facebook Messenger Broadcast API for this. This will broadcast your message to all user subscribed to the bot.
Caveats:
You have to apply for this permission. (pages_messaging and pages_messaging_subscriptions.Takes about 1-2 days, but
can test on Admin/Test users of the app)
Each broadcast has to be a separate broadcast. (e.g. you can't send image and a text together, each has to be its own individual broadcast).
Have some kind of un-subscription option as well. FB user might think you are spamming even if you clearly say in the messages that your bot will send updates.
Use custom labels to create targetted sends. So you can either subdivide who you will send updates to about specific issues or just label people if they unsubscribe to your broadcast or not.
Basic workflow:
Get permission to broadcast.
Create message_creative_id via POST to endpoint
Use message_creative_id to POST a broadcast_messages
On a successful send you will get back broadcast_id

MongoDB Concurrency Issue

I have a scenario for my app which is similar to sending friend request in Facebook.
When user A sends friend request to user B, internally a new friend request document is created. At a later time when user B also wants to send friend request to A, system would find out that a friend request document existed and so they should be friend of each other, no new friend request document would be created.
I'm trying to figure out the case when user A and user B both simultaneously sends friend request to each other which will then create 2 friend request documents and leading to undetermined behaviour...
Thanks for your suggestions.. Really appreciated!
Edit:
A few had suggested to use a request queue to solve this; however,
I'm confused about using queue because i thought it would make my rest api endpoint process requests sequentially. Wouldn't I lose all the benefit of multi-threading by using queue? I can't help but imagine how bad it would be if my service has millions of requests queued and waiting to be executed one by one just due to this issue. Has anyone seen something along similar problems seen in production?
I had similar situation with my client which has concurrent writes in the database, What I have implemented is a Queue service.
Create a request in the queue rather than writing in the database, a separate reader will
read one message from the queue at a time and check if it is valid to write it to
database, write only if there is no previous request.
You can implement your own queue or you can use service like AWS-SQS, rabbitmq, MSMQ etc.
// Specific to your case
In mongodb write operations on a single document are atomic.
mongodb has a feature of unique index.
Hence if you insert the document with an _id(or any other unique index) with person names A and B by creating unique index for both (such as "A_B" by lexicographically sorting the names) before doing insertion. You will inherently be able to insert only one instance of that document.
// General
What essentially we would like to have are transactions but since mongodb doesn't support such, as of now. There are a few tricks to achieve this:
2 phase commits :
https://docs.mongodb.org/v3.0/tutorial/perform-two-phase-commits/
Using an external source to maintain a flag, for example using memcache which supports insertion in transactional manner/Compare and Swap.
Here if you use system calls method in frontend then you should fire one request to frontend from Database when some user like, I send you request then within a sec database send you one system call and your frontend code immediate correct the button text like
"Add a friend" to "incoming request"
or else.
if you are only setting up database then just make a system call which send it to UI when friend request arrives or as you say Document created, the further process will be handled by UI Developer.
Thank you.
if you don't like the answer then I m apologize for that but don't downvote me because I M new in Stack Overflow Community.

Facebook Graph - What is the limit to send private messages from page to users?

I am developing a chat robot that works with private messages on facebook. The person sends a private message to a page that I own, and then I will send an answer for each message.
Everything is working, but I need to be sure facebook won't complain about the amount of messages I will send. This application will receive a lot of interactions at the same time, but in some early tests one of my messages were received like that:
http://cl.ly/image/1C1n0Z2L0R05
I am now using Batch Requests to send all messages, on an interval of 15s.
Do someone know some way to test it with multiple users and multiple messages at the same time? How the process of identification of spam messages work on facebook? How many messages can I send at the same time and in what time range to prevent that kind of behaviour?
Thanks.
There is no set limit or guideline on volume.
But really volume should not be the issue. There's a huge number of factors that is taken into account to determine if a message is spam... too many to discuss here. But you can assume basics: the content of the messages, the volume per user in a given time period, the content variation per user, has this app been flagged as spammy before, by how many users, etc. I would say its reasonable to assume your test user is probably going to be triggered as spammy because you're likely using it far far more than the average user would.
So, in short: it depends entirely on what exactly you're doing every 15 seconds.
Tip (although I cannot verify it): if you are trying to batch send a message to a number of users at once, without them very recently contacting you, you're probably gonna be flagged as spammy.