I'm trying to solidify my understanding of what blocking
means in terms of requests to a web server and when it's smart to hand off requests to a separate worker (i.e. sidekiq).
Consider the following examples:
Login with Facebook
def sign_in
response = Faraday.get("https://graph.facebook.com/me?fields=id,email&access_token=#{some_token}")
user_info = JSON.parse(response.body)
@user = User.find_by(uid: user_info["id"])
...
end
Send push notification through Google Firebase
def send_push_notification
...
fcm = FCM.new(FCM_KEY)
registration_ids = [recipient_token]
resp = fcm.send(registration_ids, data: {body: notification_params[:body]})
...
end
In both examples, the web requests to a 3rd-party service are synchronous and possibly costly. Intuitively, I would try to handle these cases with a separate worker because they block the main application. But, I am not 100% sure what blocking means. Does it mean that when there are 100 users trying to sign_in
and each Faraday.get
call takes 1 second, it will take 100 seconds for all the users to sign in?
Does it mean that when there are 100 users trying to sign_in and each Faraday.get call takes 1 second, it will take 100 seconds for all the users to sign in?
Simplistic answer: yes.
In a very simple scenario, the 1st user will wait 1 second, the 2nd user will wait 2 seconds and so on.
If your application/web server doesn't abort the user request, the 100th user will wait for 100 seconds.
A bit more detailed: depends.
Today, modern web applications (like Puma) have more than 1 process worker running in your machine. This means that your application is able to handle more than 1 request concurrently.
For example: if you have Puma configured to use 2 workers, your application will handle the requests of 2 users at same time.
Thus, the 1st and 2nd users will wait 1 second, the 3rd and 4th users will wait 2 seconds and the 99th and 100th users will wait 50 seconds.
As each Puma process consumes a considerable amount of CPU and memory, you cannot have infinite workers. That's why is very interesting have a background process to send these push notifications.
In Sidekiq (for example) the cost to delegate a job to a worker is extremely slow and thus the users of your website won't be penalized.