Class: APN::Sender

Inherits:
Resque::Worker show all
Includes:
Connection::Base
Defined in:
lib/apn/sender.rb

Overview

Subclass of Resque::Worker which initializes a single TCP socket on creation to communicate with Apple’s Push Notification servers. Shares this socket with each child process forked off by Resque to complete a job. Socket is closed in the before_unregister_worker callback, which gets called on normal or exceptional exits.

End result: single persistent TCP connection to Apple, so they don’t ban you for frequently opening and closing connections, which they apparently view as a DOS attack.

Accepts :environment (production vs anything else) and :cert_path options on initialization. If called in a Rails context, will default to RAILS_ENV and RAILS_ROOT/config/certs. :environment will default to development.

APN::Sender expects two files to exist in the specified :cert_path directory: apn_production.pem and apn_development.pem.

If a socket error is encountered, will teardown the connection and retry again twice before admitting defeat.

Constant Summary collapse

TIMES_TO_RETRY_SOCKET_ERROR =
2

Instance Attribute Summary

Attributes included from Connection::Base

#logger, #opts

Instance Method Summary collapse

Methods included from Connection::Base

#initialize, #resque_log, #socket

Methods inherited from Resque::Worker

#unregister_worker, #unregister_worker_without_before_hook

Instance Method Details

#send_to_apple(notification, attempt = 0) ⇒ Object

Send a raw string over the socket to Apple’s servers (presumably already formatted by APN::Notification)



20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/apn/sender.rb', line 20

def send_to_apple( notification, attempt = 0 )
  if attempt > TIMES_TO_RETRY_SOCKET_ERROR
    log_and_die("Error with connection to #{apn_host} (retried #{TIMES_TO_RETRY_SOCKET_ERROR} times): #{error}")
  end
  
  self.socket.write( notification.to_s )
rescue SocketError => error
  log(:error, "Error with connection to #{apn_host} (attempt #{attempt}): #{error}")
  
  # Try reestablishing the connection
  teardown_connection
  setup_connection
  send_to_apple(notification, attempt + 1)
end