apns-ruby 0.0.2 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -13
  3. data/lib/apns/connection.rb +31 -13
  4. metadata +2 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a82816830da1287822fead19cd690a9e6f9a8042
4
- data.tar.gz: cf75ab95b88a81f4b3415182744c3ddf5888e760
3
+ metadata.gz: fb5a30cf2461e888a174d71c290a566c23bd41d7
4
+ data.tar.gz: 0bd5422d9e7656b5937489728528fcc66f11b745
5
5
  SHA512:
6
- metadata.gz: 8426a8e9f97f4ee0ba56d8b619d3c6588ab7e801db21aacad8e4f1a5ba13a2c8fb208a67061189c2a2214d3f24e46641e3c7c19d8727eac80f8af7991878620b
7
- data.tar.gz: 2e4ef8e08692bf8228aa6a280c9f72d28efbda116d84b6e44be8e80db2c1d2bc5d7394afdd638b137aac6867bd57ee80ffacc8452c62c9a79cefba3fae34236b
6
+ metadata.gz: 9e5b3605fdfc3bbd279b93f4ec8348e171a0c5b8be8c371b07a104993d199fbaf8a0580e93e797bbe702dc5b2b4585ac761235aa1fa577ee14e3465d48fa3993
7
+ data.tar.gz: 7285ff7bf0688969409368e5434bc7246e6bd2e9768f8a15d1422ef27b6c4b6d09414a444d7e9c1ac23a5e2c2e7a1cd621b9491e782daea653145cdd5ec02ccf
data/README.md CHANGED
@@ -4,6 +4,8 @@ This gem sends APNS notifications with proper error handling. Most importantly,
4
4
  * Storing notifications in a database, and have a separate process consume them. Worse, only a single consumer is ever allowed.
5
5
  * Opening a new SSL connection for every notification, which typically takes several hundred milliseconds. Imagine how long it would take to send a million notifications.
6
6
 
7
+ As of 2015-03-04, this gem has been powering [PicCollage](http://pic-collage.com/) for more than a year, sending more than 500 notifications per second at peak time, only to be limited by the devices database's throughput.
8
+
7
9
  Example usage:
8
10
  ```
9
11
  pem = path_to_your_pem_file
@@ -27,19 +29,8 @@ n1 = APNS::Notification.new(token, alert: 'hello')
27
29
  ne = APNS::Notification.new('bogustoken', alert: 'error')
28
30
  n2 = APNS::Notification.new(token, alert: 'world')
29
31
  conn.push([n1, ne, n2])
30
- # Should receive only a 'hello' notification on your device
31
-
32
- # Wait for Apple to report an error and close the connection on their side, due to
33
- # the bogus token in the second notification.
34
- # We'll detect this and automatically retry and invoke your error handler.
35
- sleep(7)
36
- conn.push([APNS::Notification.new(token, alert: 'hello world 0')])
37
- sleep(7)
38
- conn.push([APNS::Notification.new(token, alert: 'hello world 1')])
39
-
40
- # 'Invalid token: bogustoken' is printed out
41
- # We should be receiving each and every successful notification with texts:
42
- # 'world', 'hello world 0', and 'hello world 1'.
32
+ # 'Invalid token: bogustoken' is printed out.
33
+ # Moreover, we should be receiving each and every successful notification with texts 'hello' and 'world'.
43
34
  ```
44
35
 
45
36
  A great amount of code in this gem is copied from https://github.com/jpoz/APNS , many thanks to his pioneering work. This work itself is licensed under the MIT license.
@@ -20,6 +20,14 @@ class Connection
20
20
  @host = host
21
21
  @port = port
22
22
 
23
+ # Our current strategy is to read errors emitted by the APNS in a separate
24
+ # thread spawned when we open a new connection (read_errors method).
25
+ # If this thread receives an error information from the @ssl, it turns on
26
+ # the @lock, so that no direct write operation can be performed on the same
27
+ # Connection instance.
28
+ #
29
+ @lock = Mutex.new
30
+
23
31
  @sock, @ssl = open_connection
24
32
  ObjectSpace.define_finalizer(self, self.class.finalize(@sock, @ssl))
25
33
  end
@@ -31,8 +39,8 @@ class Connection
31
39
  end
32
40
 
33
41
  def push ns
34
- # The notification identifier is set to 4 bytes in the APNS protocol. Thus,
35
- # upon hitting this limit, read for failures and restart the counting again.
42
+ # The notification identifier is set to 4 bytes in the APNS protocol.
43
+ # Thus, upon hitting this limit, read for failures and restart the counting again.
36
44
  if @notifications.size + ns.size > MAX_32_BIT - 10
37
45
  code, failed_id = read_failure_info(timeout: 3)
38
46
  if failed_id
@@ -48,7 +56,7 @@ class Connection
48
56
  n.message_identifier = [@notifications.size].pack('N')
49
57
  @notifications.push(n)
50
58
  }
51
- write ns
59
+ @lock.synchronize{ write ns }
52
60
  end
53
61
 
54
62
 
@@ -57,16 +65,6 @@ class Connection
57
65
  def write ns
58
66
  packed = pack_notifications(ns)
59
67
  @ssl.write(packed)
60
- rescue Errno::EPIPE, Errno::ECONNRESET, OpenSSL::SSL::SSLError
61
- code, failed_id = read_failure_info(timeout: 30)
62
- reopen_connection
63
- return unless failed_id # there's nothing we can do
64
-
65
- @error_handler.call(code, @notifications.item_at(failed_id))
66
-
67
- @notifications.delete_where_index_less_than(failed_id+1)
68
- ns = @notifications.items_from(failed_id+1)
69
- retry
70
68
  end
71
69
 
72
70
  def pack_notifications notifications
@@ -105,9 +103,29 @@ class Connection
105
103
  ssl = OpenSSL::SSL::SSLSocket.new(sock,context)
106
104
  ssl.connect
107
105
 
106
+ Thread.new {
107
+ read_errors ssl
108
+ }
109
+
108
110
  return sock, ssl
109
111
  end
110
112
 
113
+ def read_errors ssl
114
+ tuple = ssl.read(6)
115
+
116
+ @lock.synchronize {
117
+ _, code, failed_id = tuple.unpack("ccN")
118
+ reopen_connection
119
+ return unless failed_id # there's nothing we can do
120
+
121
+ @error_handler.call(code, @notifications.item_at(failed_id))
122
+
123
+ @notifications.delete_where_index_less_than(failed_id+1)
124
+ ns = @notifications.items_from(failed_id+1)
125
+ write ns
126
+ }
127
+ end
128
+
111
129
  # Override inspect since we do not want to print out the entire @notifications,
112
130
  # whose size might be over tens of thousands
113
131
  def inspect
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: apns-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - awaw
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-06-05 00:00:00.000000000 Z
11
+ date: 2015-03-04 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: APNS notifications sent properly with correct connection management and
14
14
  error handling
@@ -47,4 +47,3 @@ signing_key:
47
47
  specification_version: 4
48
48
  summary: APNS notifications sent properly
49
49
  test_files: []
50
- has_rdoc: