https://github.com/flyclops/gocm
Super-simple async GCM notification send service written in Go
https://github.com/flyclops/gocm
Last synced: about 1 year ago
JSON representation
Super-simple async GCM notification send service written in Go
- Host: GitHub
- URL: https://github.com/flyclops/gocm
- Owner: Flyclops
- License: mit
- Created: 2014-03-10T18:13:44.000Z (over 12 years ago)
- Default Branch: master
- Last Pushed: 2014-07-17T17:06:16.000Z (almost 12 years ago)
- Last Synced: 2024-06-19T00:22:06.482Z (about 2 years ago)
- Language: Go
- Homepage: http://tech.flyclops.com/gocm-super-simple-asynchronous-gcm-listener-in-go-403
- Size: 402 KB
- Stars: 45
- Watchers: 6
- Forks: 7
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
GoCM
====
Super-simple asynchronous Google Cloud Messaging (GCM) notification send service written in Go
[](https://travis-ci.org/Flyclops/GoCM)
Motivation
-----------
The world already has [pyapns](https://github.com/samuraisam/pyapns) for asynchronous sending of Apple Push Notifications. We needed similar async functionality for Google Cloud Messages that we use for push notifications on Android.
Since we're (slowly) moving most of our backend codebase to [Go](http://golang.org), any new code is written in Go.
[pyapns](https://github.com/samuraisam/pyapns) is so nice because [Apple Push Notification Services](https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/ApplePushService.html) require a long-open socket through which all messages are sent. This minimizes the number of handshakes that need to take place, and gives the app an open pipe through which to dump messages.
GCM, however, is a RESTful service (as of the writing of this README, the "send" URL is https://android.googleapis.com/gcm/send), that requires one HTTP connection per message sent. It does support multicasting to up to 1000 devices at once, but the message must be identical to all devices.
In our testing, from API servers running on AWS EC2 c1.medium cloud servers, sending a single APNS push notification takes < 10ms on an open socket, while sending a single GCM notification can take between 150-250ms. Since we send hundreds of notifications per second, this became unacceptable.
The service
------------
In order to not reinvent the wheel, we started with [Alex Lockwood's](https://github.com/alexjlockwood) open source GCM package for Go, called simply [gcm](https://github.com/alexjlockwood/gcm). Surrounding that, we instantiate a standard web server that takes an ```-apikey``` argument (and also configurable ```-ipaddress``` and ```-port``` arguments if the defaults are not desired) and listens for incoming POST requests.
The POST request should include two key-value pairs, ```tokens``` (an array of GCM device tokens) and ```payload``` (the JSON packet to send to GCM).
The server returns immediately, while pushing the main bulk of the work on to a new goroutine.
Functions:
- Send GCM messages (retries any message twice (TODO, make configurable?))
- Keep a run report for the process
- Report [canonical IDs from GCM](http://developer.android.com/google/gcm/adv.html#canonical)
- Report [NotRegistered tokens](http://developer.android.com/google/gcm/http.html#error_codes)
Example
--------
Start the server
```bash
./GoCM --apikey
```
Send a message...
...via ```curl```:
```bash
curl -d "tokens=&tokens=&payload={\"title\": \"This is the title\", \"subtitle\": \"This is the subtitle\", \"tickerText\": \"This is the ticker text\", \"datestamp\": \"2014-03-07T18:01:04.702100\"}" localhost:5601/gcm/send
```
...via `python`
```python
import requests
GCM_SEND_ENDPOINT = 'http://localhost:5601/gcm/send'
token = ""
message = {
'title': 'This is the title',
'subtitle': 'This is the subtitle',
'tickerText': 'This is the ticker text',
'datestamp': '2014-03-07T18:01:04.702100'
}
data = {
'tokens': [token],
'payload': json.dumps(message)
}
response = requests.post(GCM_SEND_ENDPOINT, data=data)
```
Get back a run report of attempts, failures, and required changes:
```bash
curl localhost:5601/gcm/report
```
Result like: ```{"attempts":0,"failures":0,"pending":0,"canonicals":0,"notregistered":0}```
("attempts," "failures," "notregistered", and "canonicals" is a running total for the running process, while "pending" is the number of messages waiting to finish transmitting successfully. Great for watching via Graphite graphs or the like.)
Get back a list of push tokens that require updating (call if ```canonicals``` in above results > 0):
```bash
curl localhost:5601/gcm/report/canonical
```
Results like: ```{"canonical_replacements":null}```
Or: ```{"canonical_replacements": [{"original": "", "canonical": ""}]}```
_Read more on Canonical IDs in GCM via the [offical documentation](http://developer.android.com/google/gcm/adv.html#canonical)_
Get back a list of push tokens that should be purged from your database (app was uninstalled, etc.)
```bash
curl localhost:5601/gcm/report/notregistered
```
Results like ```{"tokens": ["token1", "token2", ...]}```
TODO
-----------
- Perhaps make runnable on a UNIX socket