September 27, 2019

Sending FCM Push Notifications with Andpush Gem

Recently, I had migrated from GCM (Google Cloud Messaging) to FCM (Firebase Cloud Messaging) because GCM was ending its life.

At first, I found fcm gem which supports FCM. I changed my application code to use the gem and I deployed the new version since it was working nicely on the staging. However, as time goes, I realized that FCM notification sometimes stops working when the application runs on multiple threads. And it’s turned out that the latest released version of fcm gem does not support multi-threaded applications as of today. That’s why I decided to use another library and that’s where Andpush gem comes into play.

Andpush gem is a fast HTTP client library for FCM. The README says it’s 3.7 times faster than fcm gem even in single-threaded environments. Thanks for net-http-persistent, it reuses HTTP connection and we can reduce extra TCP round-trip. The API is quite simple. Here is an example code from the README:

require 'andpush'

server_key   = "..."
device_token = "..."

client  = Andpush.new(server_key, pool_size: 25)
payload = {
  to: device_token,
  notification: {
    title: "Update",
    body: "Your weekly summary is ready"
  },
  data: { extra: "data" }
}

response = client.push(payload)

headers = response.headers
headers['Retry-After'] # => returns 'Retry-After'

json = response.json
json[:canonical_ids] # => 0
json[:failure]       # => 0
json[:multicast_id]  # => 8478364278516813477

result = json[:results].first
result[:message_id]      # => "0:1489498959348701%3b8aef473b8aef47"
result[:error]           # => nil, "InvalidRegistration" or something else
result[:registration_id] # => nil

Compared to fcm gem, it does not have any API to create notification key. Originally I had used this function to send a message to multiple devices. However, multicasting a message can be done by passing multiple device tokens registration_ids: instead of passing a single device token to to:.

--- before      2019-09-27 20:14:19.632608083 +0900
+++ after       2019-09-27 20:15:44.175032158 +0900
@@ -1,6 +1,6 @@
 client  = Andpush.new(server_key, pool_size: 25)
 payload = {
-  to: device_token,
+  registration_ids: device_tokens,
   notification: {
     title: "Update",
     body: "Your weekly summary is ready"

Now I do not have to create notification keys.

I confirmed it works well on the staging environment. However, the app was always working fine on the staging environment even with fcm gem. I will update if I found any problems on production environment. Incidentally, this gem supports HTTP/2 experimentally. I also will report if I have time to try it.

© Hibariya 2020

Powered by Hugo & Kiss.