I am constantly learning as I write and refactor my code. It’s what makes code I wrote a week ago look awkward and clunky next to my daily output.
Last August I wrote a python script to manage push notifications for Prose, my App.net client. Today, I still barely have a grasp of python, yet when the script began crashing I looked at it again and saw flaws I would never have seen back in August.
I knew I needed to make something more future proof, and quickly. The Python script was terrible for a few reasons and my new solution needed to solve these problems:
- The Python script was like a good stew. It was a single massive pot full of model objects, networking functions, and confusingly named variables. It was awful.
- The script used synchronous functions exclusively. I don’t even know how this was possible.
- At the time, I had a significant amount of help writing the script so I didn’t fully understand the API endpoints or native python functions I was calling. I didn’t understand why things were crashing.
- There isn’t a user friendly or transparent way of keeping a python script running indefinitely. My solution involved the crontab and was hacky at best.
- When my script inevitably crashed, it didn’t cry out in pain before giving up the ghost. My only feedback was mentions that wouldn’t make it to me.
I had a vague idea that Node was great for server side applications but after I heard Casey Liss talk about his experience with it I became curious.
When I started looking past my own hipster-esque preconceptions of Node I found that many of my problems are solved by the language or community surrounding it.
The New Script
Delivering push notifications to users involves two steps: Fetching and monitoring a long lived HTTP connection and transmitting the received data to Parse for delivery to devices.
I decided to separate these two tasks into two different modules; with my first I learned the ins and outs of Node. It’s simple but it can:
- Handle authentication.
- Create, delete, and fetch both filter and app stream objects.
- Monitor a fetched app stream with a simple callback.
My second module transforms JSON response envelopes (as described in the docs) into native objects, assembles the proper APNS payload, and then delivers the payload to Parse. This whole process is quite specific to my use case so I opted not to publish the module.
When these modules were tested and complete I combined them into a very manageable script that is a mere 54 lines long.
Concise code is great but what about performance? Well, Node’s
http modules both employ network request functions that take callbacks making it near impossible to block the main process. As an added bonus, if the script ever fails and is run again, it receives the unconsumed notifications from the stream and can handle the excess response envelopes as fast as they come in. I’ve seen my script simultaneously deal with 12+ response envelopes easily.
At this point I’ve become familiar with Node and the necessary App.net endpoints and have modular code executing asynchronously. My first three problems are solved.
Keeping my script up and running was the easiest problem to solve. One Google search and two lines of code was all it took. Check out the
forever module, it’s really cool and provides great extensibility and a super simple CLI.
I’m not accustomed to working with headless environments, error reporting on a server has always baffled me. To solve my final problem my new script sends me a notification every time it’s started. Encapsulating code into separate modules allowed me to add this functionality with just two lines of code.
After the first day of playing with Node I could see its potential. The language is simple, easy to read, surrounded by a large community, and the built in tools make it extensible.
I haven’t had a single crash since the script was first put into a production environment and I’m ecstatic about those results. It doesn’t matter if the Node community is a bunch of hipsters like I originally assumed because Node is useful. I now have another tool in my tool belt and the confidence to use it.
If you want to play around with App.net’s App Streams, check out my first module on Github. It’s my first Node project, please don’t hesitate to point out errors or optimisations. If you have any questions, I’m @shawnthroop on all the things.