Wednesday, December 19, 2012

Possible reasons that your apn_on_rails may not work

There were several times that user reported that the Push Notification not working. That's always my first response: "It should be working. No way it is not working. I just fixed it few days ago, and it was working !"

I found the need to share all the errors I saw, and also as a checklist reference for my future projects.

1. I was using the wrong fork of http://github.com/XXX/apn_on_rails 

  There are bugs in the master github repository PRX/apn_on_rails. And in some forks, you should put the .pem file path as the configatron.apn.cert, while in some other branches, configatron.apn.cert is actually asking for file content:

    configatron.apn.cert = File.join(Rails.root, 'config', 'certs', 'apn_dev.pem')
    configatron.apn.cert = File.read(File.join(Rails.root, 'config', 'certs', 'apn_dev.pem'))

  There are some more other fixes loosely exist in some forks and I have no idea which one is the best, so ... I forked one more for myself. https://github.com/3dd13/apn_on_rails


2. apn push token I collected from 2 mobile apps are the same

I was setting up two mobile apps push notification by one backend server, and user is using both mobile apps. I knew that I had to use two different .pem cert file to push to the two different apps, but sometimes one of them was not working and sometimes it pushed messages to the wrong mobile apps.

After tracing all the code, finally, I found out that the apn_token from the 2 mobile apps I collected are actually the same. And the APN::Device instance did not create with the correct app:

    device = APN::Device.find_or_create_by_token(apn_token)

so this is my fix:

    device = APN::Device.find_or_create_by_token_and_app_id(self.apn_token, apn_app.id)


3. I submitted the apn token with incorrect format

I solved this issue few months ago, but recently after I rewrite some code and this bug dragged me crazy ... once again.

the apn push token you collected from mobile is in this format:

    00ea74e76a873e8e9c14c2dd2afe3b42abb35148e94042811e2b6985072641f2

but actually, apn_on_rails is expecting this:

    00ea74e7 6a873e8e 9c14c2dd 2afe3b42 abb35148 e9404281 1e2b6985 072641f2

I wrote a method to convert that:

4. I setup the staging with production push cert with sandbox apn host

One of my early chore was setting up apn push cert, so to do it quick (and dirty), I was using development .pem cert file on both my dev machine and so-called production. But later when I was switching the production cert to the real production cert, It did not work.

At that moment of time, what drove me crazy was that no error was thrown and the "sent_at" attribute of the APN::Notification is correctly updated.

So, we keep checking everything again and again, generating certs for several times, restarting servers, clearing up database records. AND ... the real bug is actually the incorrect configatron.apn.host

gateway.push.apple.com should be used for production, and gateway.sandbox.push.apple.com should be used for development


5. Used production for staging (on heroku) Procfile

Push messages are sent out in worker threads (by sidekiq), and workers are started using Procfile:

    worker: bundle exec sidekiq -e production -C config/sidekiq.yml

obviously, this Procfile won't work for staging or development machine, the correct one should be:

    worker: bundle exec sidekiq -e $RACK_ENV -C config/sidekiq.yml


6. Errno::ENAMETOOLONG File name too long

There were something like that in the log

    Errno::ENAMETOOLONG
    WARN: File name too long - Bag Attributes

actually, this is not an error, just a warning. However, it fills up my logentries page which makes it hard to debug.

This one was caused by some strange bug (perhaps not a bug, but I don't understand why). It is related to the configatron.apn.cert path issue I was talking about.

In the same function, configatron.apn.cert was treated as both path and file content. If you want to know the details, check out the commit I made to fix it:
https://github.com/3dd13/apn_on_rails/commit/0b60b26b38540d0c59a6cd21068d6b2f9a6cf139