rapns_rails_2 3.4.3 → 3.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/CHANGELOG.md CHANGED
@@ -1,5 +1,6 @@
1
- ## 3.4.2 (unreleased)
1
+ ## 3.5.0 (unreleased)
2
2
  * Fix sqlite3 support (#160).
3
+ * Drop support for Ruby 1.8.
3
4
 
4
5
  ## 3.4.1 (Aug 30, 2013)
5
6
  * Silence unintended airbrake_notify deprecation warning (#158).
data/README.md CHANGED
@@ -11,7 +11,7 @@
11
11
  * Run as a daemon or inside an [existing processs](https://github.com/ileitch/rapns/wiki/Embedding-API).
12
12
  * Use in a scheduler for low-workload deployments ([Push API](https://github.com/ileitch/rapns/wiki/Push-API)).
13
13
  * Reflection API for fine-grained instrumentation and error handling ([Reflection API](https://github.com/ileitch/rapns/wiki/Reflection-API)).
14
- * Works with MRI, JRuby, Rubinius 1.8 and 1.9.
14
+ * Works with MRI, JRuby, Rubinius 1.9, 2.0.
15
15
  * Built with love.
16
16
 
17
17
  ### Who uses Rapns?
data/config/database.yml CHANGED
@@ -15,7 +15,7 @@ jdbcpostgresql:
15
15
  password: ""
16
16
 
17
17
  mysql2:
18
- adapter: mysql
18
+ adapter: mysql2
19
19
  database: rapns_test
20
20
  host: localhost
21
21
  username: rapns_test
@@ -71,7 +71,7 @@ Rapns.reflect do |on|
71
71
  # on.gcm_canonical_id do |old_id, canonical_id|
72
72
  # end
73
73
 
74
- # Called when the GCM returns a failure that indicates an invalid tegistration id.
74
+ # Called when the GCM returns a failure that indicates an invalid registration id.
75
75
  # You will need to delete the registration_id from your records.
76
76
  # on.gcm_invalid_registration_id do |app, error, registration_id|
77
77
  # end
@@ -3,7 +3,7 @@ module Rapns
3
3
  class DeviceTokenFormatValidator < ActiveModel::Validator
4
4
 
5
5
  def validate(record)
6
- if record.device_token !~ /^[a-z0-9]{64}$/
6
+ if record.device_token !~ /^[a-z0-9]{64}$/i
7
7
  record.errors.add(:device_token, "is invalid")
8
8
  end
9
9
  end
@@ -9,7 +9,7 @@ module Rapns
9
9
 
10
10
  CONFIG_ATTRS = [:foreground, :push_poll, :feedback_poll, :embedded,
11
11
  :airbrake_notify, :check_for_errors, :pid_file, :batch_size,
12
- :push, :store, :logger, :batch_storage_updates, :udp_wake_host, :udp_wake_port]
12
+ :push, :store, :logger, :batch_storage_updates, :wakeup]
13
13
 
14
14
  class ConfigurationWithoutDefaults < Struct.new(*CONFIG_ATTRS)
15
15
  end
@@ -51,15 +51,15 @@ module Rapns
51
51
  end
52
52
 
53
53
  def self.interruptible_sleeper
54
- unless @interruptible_sleeper
55
- @interruptible_sleeper = InterruptibleSleep.new
56
- if Rapns.config.udp_wake_host && Rapns.config.udp_wake_port
57
- @interruptible_sleeper.enable_wake_on_udp Rapns.config.udp_wake_host, Rapns.config.udp_wake_port
58
- end
54
+ return @interruptible_sleeper if @interruptible_sleeper
55
+
56
+ @interruptible_sleeper = InterruptibleSleep.new
57
+ if Rapns.config.wakeup
58
+ @interruptible_sleeper.enable_wake_on_udp Rapns.config.wakeup[:bind], Rapns.config.wakeup[:port]
59
59
  end
60
+
60
61
  @interruptible_sleeper
61
62
  end
62
-
63
63
  end
64
64
  end
65
65
  end
@@ -46,6 +46,9 @@ module Rapns
46
46
 
47
47
  def ok(response)
48
48
  body = multi_json_load(response.body)
49
+
50
+ handle_canonical_ids(response, body)
51
+
49
52
  if body['failure'].to_i == 0
50
53
  mark_delivered
51
54
  Rapns.logger.info("[#{@app.name}] #{@notification.id} sent to #{@notification.registration_ids.join(', ')}")
@@ -54,7 +57,6 @@ module Rapns
54
57
  handle_errors(response, body)
55
58
  end
56
59
 
57
- handle_canonical_ids(response, body)
58
60
  end
59
61
 
60
62
  def handle_errors(response, body)
@@ -63,9 +65,10 @@ module Rapns
63
65
  body['results'].each_with_index do |result, i|
64
66
  errors[i] = result['error'] if result['error'] && ! INVALID_REGISTRATION_ID_STATES.include?(result['error'])
65
67
  end
66
- return if errors.empty?
67
68
 
68
- if body['success'].to_i == 0 && errors.values.all? { |error| UNAVAILABLE_STATES.include?(error) }
69
+ if errors.empty?
70
+ all_errors_were_invalid_registration_ids(response)
71
+ elsif body['success'].to_i == 0 && errors.values.all? { |error| UNAVAILABLE_STATES.include?(error) }
69
72
  all_devices_unavailable(response)
70
73
  elsif errors.values.any? { |error| UNAVAILABLE_STATES.include?(error) }
71
74
  some_devices_unavailable(response, errors)
@@ -117,6 +120,10 @@ module Rapns
117
120
  Rapns.logger.warn("All recipients unavailable. " + retry_message)
118
121
  end
119
122
 
123
+ def all_errors_were_invalid_registration_ids(response)
124
+ mark_failed(nil, "All registration IDs were invalid.")
125
+ end
126
+
120
127
  def some_devices_unavailable(response, errors)
121
128
  unavailable_idxs = errors.find_all { |i, error| UNAVAILABLE_STATES.include?(error) }.map(&:first)
122
129
  new_notification = create_new_notification(response, unavailable_idxs)
@@ -32,4 +32,21 @@ module Rapns
32
32
  end
33
33
 
34
34
  end
35
+
36
+ # Call this from a client application after saving a Notification to the database to wakeup the Rapns
37
+ # Daemon to deliver the notification immediately.
38
+ def self.wakeup
39
+ notifier.notify
40
+ end
41
+
42
+ # Default notifier instance. This uses the :connect, :port values in Rapns.config.wakeup to connect to the
43
+ # wakeup socket in the Rapns Daemon. It will fall back to :host, :port if :connect is not specified.
44
+ def self.notifier
45
+ unless @notifier
46
+ if Rapns.config.wakeup
47
+ @notifier = Notifier.new(Rapns.config.wakeup[:connect] || Rapns.config.wakeup[:host], Rapns.config.wakeup[:port])
48
+ end
49
+ end
50
+ @notifier
51
+ end
35
52
  end
data/lib/rapns/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Rapns
2
- VERSION = '3.4.3'
2
+ VERSION = '3.5.0'
3
3
  end
data/lib/rapns_rails_2.rb CHANGED
@@ -34,6 +34,7 @@ require 'rapns/embed'
34
34
  require 'rapns/push'
35
35
  require 'rapns/apns_feedback'
36
36
  require 'rapns/upgraded'
37
+ require 'rapns/notifier'
37
38
 
38
39
  require 'rapns/apns/binary_notification_validator'
39
40
  require 'rapns/apns/device_token_format_validator'
@@ -4,6 +4,6 @@ describe Rapns::Apns::Feedback do
4
4
  it "should validate the format of the device_token" do
5
5
  notification = Rapns::Apns::Feedback.new(:device_token => "{$%^&*()}")
6
6
  notification.valid?.should be_false
7
- notification.errors[:device_token].include?("is invalid").should be_true
7
+ notification.errors[:device_token].should include("is invalid")
8
8
  end
9
9
  end
@@ -5,77 +5,85 @@ describe Rapns::Daemon::Feeder do
5
5
  :push_poll => 0,
6
6
  :embedded => false,
7
7
  :push => false,
8
- :udp_wake_host => nil,
9
- :udp_wake_port => nil) }
8
+ :wakeup => nil) }
10
9
  let!(:app) { Rapns::Apns::App.create!(:name => 'my_app', :environment => 'development', :certificate => TEST_CERT) }
11
10
  let(:notification) { Rapns::Apns::Notification.create!(:device_token => "a" * 64, :app => app) }
12
11
  let(:logger) { double }
12
+ let(:interruptible_sleep) { double(:sleep => nil, :interrupt_sleep => nil) }
13
13
 
14
14
  before do
15
15
  Rapns.stub(:config => config,:logger => logger)
16
16
  Rapns::Daemon.stub(:store => double(:deliverable_notifications => [notification]))
17
17
  Rapns::Daemon::Feeder.stub(:stop? => true)
18
18
  Rapns::Daemon::AppRunner.stub(:enqueue => nil, :idle => [double(:app => app)])
19
+ Rapns::Daemon::InterruptibleSleep.stub(:new => interruptible_sleep)
20
+ Rapns::Daemon::Feeder.instance_variable_set('@interruptible_sleeper', nil)
19
21
  end
20
22
 
21
- def start
23
+ def start_and_stop
22
24
  Rapns::Daemon::Feeder.start
25
+ Rapns::Daemon::Feeder.stop
23
26
  end
24
27
 
25
28
  it "starts the loop in a new thread if embedded" do
26
29
  config.stub(:embedded => true)
27
30
  Thread.should_receive(:new).and_yield
28
31
  Rapns::Daemon::Feeder.should_receive(:feed_forever)
29
- start
32
+ start_and_stop
30
33
  end
31
34
 
32
35
  it 'loads deliverable notifications' do
33
36
  Rapns::Daemon.store.should_receive(:deliverable_notifications).with([app])
34
- start
37
+ start_and_stop
35
38
  end
36
39
 
37
40
  it 'does not attempt to load deliverable notifications if there are no idle runners' do
38
41
  Rapns::Daemon::AppRunner.stub(:idle => [])
39
42
  Rapns::Daemon.store.should_not_receive(:deliverable_notifications)
40
- start
43
+ start_and_stop
41
44
  end
42
45
 
43
46
  it 'enqueues notifications without looping if in push mode' do
44
47
  config.stub(:push => true)
45
48
  Rapns::Daemon::Feeder.should_not_receive(:feed_forever)
46
49
  Rapns::Daemon::Feeder.should_receive(:enqueue_notifications)
47
- start
50
+ start_and_stop
48
51
  end
49
52
 
50
53
  it "enqueues the notifications" do
51
54
  Rapns::Daemon::AppRunner.should_receive(:enqueue).with([notification])
52
- start
55
+ start_and_stop
53
56
  end
54
57
 
55
58
  it "logs errors" do
56
59
  e = StandardError.new("bork")
57
60
  Rapns::Daemon.store.stub(:deliverable_notifications).and_raise(e)
58
61
  Rapns.logger.should_receive(:error).with(e)
59
- start
62
+ start_and_stop
60
63
  end
61
64
 
62
65
  it "interrupts sleep when stopped" do
63
66
  Rapns::Daemon::Feeder.should_receive(:interrupt_sleep)
64
- Rapns::Daemon::Feeder.stop
67
+ start_and_stop
65
68
  end
66
69
 
67
70
  it "enqueues notifications when started" do
68
71
  Rapns::Daemon::Feeder.should_receive(:enqueue_notifications).at_least(:once)
69
72
  Rapns::Daemon::Feeder.stub(:loop).and_yield
70
- start
73
+ start_and_stop
71
74
  end
72
75
 
73
76
  it "sleeps for the given period" do
74
77
  config.stub(:push_poll => 2)
75
- sleeper = double(:sleep => true)
76
- sleeper.should_receive(:sleep).with(2)
77
- Rapns::Daemon::Feeder.stub(:interruptible_sleeper => sleeper)
78
- Rapns::Daemon::Feeder.stub(:loop).and_yield
79
- Rapns::Daemon::Feeder.start
78
+ interruptible_sleep.should_receive(:sleep).with(2)
79
+ start_and_stop
80
+ end
81
+
82
+ it "creates the wakeup socket" do
83
+ bind = '127.0.0.1'
84
+ port = 12345
85
+ config.stub(:wakeup => { :bind => bind, :port => port})
86
+ interruptible_sleep.should_receive(:enable_wake_on_udp).with(bind, port)
87
+ start_and_stop
80
88
  end
81
89
  end
@@ -110,7 +110,7 @@ describe Rapns::Daemon::Gcm::Delivery do
110
110
  perform
111
111
  end
112
112
 
113
- it 'does not retry, raise or marks a notification as failed for invalid ids.' do
113
+ it 'does marks a notification as failed if any ids are invalid.' do
114
114
  body = {
115
115
  'failure' => 1,
116
116
  'success' => 2,
@@ -122,7 +122,7 @@ describe Rapns::Daemon::Gcm::Delivery do
122
122
  ]}
123
123
 
124
124
  response.stub(:body => MultiJson.dump(body))
125
- batch.should_not_receive(:mark_failed)
125
+ batch.should_receive(:mark_failed)
126
126
  batch.should_not_receive(:mark_retryable)
127
127
  store.should_not_receive(:create_gcm_notification)
128
128
  perform
@@ -29,4 +29,24 @@ describe Rapns::Notifier do
29
29
  end
30
30
  end
31
31
  end
32
+
33
+ describe "default notifier" do
34
+ it "creates using :connect first" do
35
+ Rapns.config.stub :wakeup => { :connect => '127.0.0.1', :port => 1234 }
36
+ Rapns::Notifier.should_receive(:new).with('127.0.0.1', 1234)
37
+ Rapns.notifier
38
+ end
39
+
40
+ it "creates using :host next" do
41
+ Rapns.config.stub :wakeup => { :host => '127.0.0.1', :port => 1234 }
42
+ Rapns::Notifier.should_receive(:new).with('127.0.0.1', 1234)
43
+ Rapns.notifier
44
+ end
45
+
46
+ it "returns nil when wakeup is not specified" do
47
+ Rapns.config.stub :wakeup => nil
48
+ Rapns::Notifier.should_not_receive(:new)
49
+ Rapns.notifier.should be_nil
50
+ end
51
+ end
32
52
  end
@@ -4,7 +4,6 @@ require 'bundler'
4
4
  Bundler.require(:default)
5
5
 
6
6
  require 'active_record'
7
- require 'database_cleaner'
8
7
 
9
8
  unless ENV['TRAVIS'] && ENV['QUALITY'] == 'false'
10
9
  begin
@@ -53,6 +52,7 @@ require 'generators/templates/add_gcm'
53
52
  migration.up
54
53
  end
55
54
 
55
+ require 'database_cleaner'
56
56
  DatabaseCleaner.strategy = :truncation
57
57
 
58
58
  require 'rapns_rails_2'
metadata CHANGED
@@ -1,52 +1,62 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: rapns_rails_2
3
- version: !ruby/object:Gem::Version
4
- version: 3.4.3
3
+ version: !ruby/object:Gem::Version
4
+ hash: 19
5
+ prerelease:
6
+ segments:
7
+ - 3
8
+ - 5
9
+ - 0
10
+ version: 3.5.0
5
11
  platform: ruby
6
- authors:
12
+ authors:
7
13
  - Ian Leitch
8
14
  - Marc Rohloff
9
15
  autorequire:
10
16
  bindir: bin
11
17
  cert_chain: []
12
- date: 2013-10-02 00:00:00.000000000 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
18
+
19
+ date: 2013-11-20 00:00:00 Z
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
15
22
  name: multi_json
16
- requirement: !ruby/object:Gem::Requirement
17
- requirements:
18
- - - ~>
19
- - !ruby/object:Gem::Version
20
- version: '1.0'
21
- type: :runtime
22
23
  prerelease: false
23
- version_requirements: !ruby/object:Gem::Requirement
24
- requirements:
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
25
27
  - - ~>
26
- - !ruby/object:Gem::Version
27
- version: '1.0'
28
- - !ruby/object:Gem::Dependency
29
- name: net-http-persistent
30
- requirement: !ruby/object:Gem::Requirement
31
- requirements:
32
- - - ! '>='
33
- - !ruby/object:Gem::Version
34
- version: '0'
28
+ - !ruby/object:Gem::Version
29
+ hash: 15
30
+ segments:
31
+ - 1
32
+ - 0
33
+ version: "1.0"
35
34
  type: :runtime
35
+ version_requirements: *id001
36
+ - !ruby/object:Gem::Dependency
37
+ name: net-http-persistent
36
38
  prerelease: false
37
- version_requirements: !ruby/object:Gem::Requirement
38
- requirements:
39
- - - ! '>='
40
- - !ruby/object:Gem::Version
41
- version: '0'
39
+ requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ hash: 3
45
+ segments:
46
+ - 0
47
+ version: "0"
48
+ type: :runtime
49
+ version_requirements: *id002
42
50
  description: Professional grade APNs and GCM for Ruby with Rails 2 compatibility
43
- email:
51
+ email:
44
52
  - port001@gmail.com
45
- executables:
53
+ executables:
46
54
  - rapns
47
55
  extensions: []
56
+
48
57
  extra_rdoc_files: []
49
- files:
58
+
59
+ files:
50
60
  - CHANGELOG.md
51
61
  - LICENSE
52
62
  - README.md
@@ -160,28 +170,38 @@ files:
160
170
  - bin/rapns
161
171
  homepage: https://github.com/marcrohloff/rapns_rails_2
162
172
  licenses: []
163
- metadata: {}
173
+
164
174
  post_install_message:
165
175
  rdoc_options: []
166
- require_paths:
176
+
177
+ require_paths:
167
178
  - lib
168
- required_ruby_version: !ruby/object:Gem::Requirement
169
- requirements:
170
- - - ! '>='
171
- - !ruby/object:Gem::Version
172
- version: '0'
173
- required_rubygems_version: !ruby/object:Gem::Requirement
174
- requirements:
175
- - - ! '>='
176
- - !ruby/object:Gem::Version
177
- version: '0'
179
+ required_ruby_version: !ruby/object:Gem::Requirement
180
+ none: false
181
+ requirements:
182
+ - - ">="
183
+ - !ruby/object:Gem::Version
184
+ hash: 3
185
+ segments:
186
+ - 0
187
+ version: "0"
188
+ required_rubygems_version: !ruby/object:Gem::Requirement
189
+ none: false
190
+ requirements:
191
+ - - ">="
192
+ - !ruby/object:Gem::Version
193
+ hash: 3
194
+ segments:
195
+ - 0
196
+ version: "0"
178
197
  requirements: []
198
+
179
199
  rubyforge_project:
180
- rubygems_version: 2.0.2
200
+ rubygems_version: 1.8.4
181
201
  signing_key:
182
- specification_version: 4
202
+ specification_version: 3
183
203
  summary: Professional grade APNs and GCM for Ruby
184
- test_files:
204
+ test_files:
185
205
  - config/database.yml
186
206
  - spec/support/cert_with_password.pem
187
207
  - spec/support/cert_without_password.pem
checksums.yaml DELETED
@@ -1,15 +0,0 @@
1
- ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- ODdlNDhlOTIzODkyMDZiODdiNzIwYjAyNDJlNjkzZDYyMmYyZDhjNQ==
5
- data.tar.gz: !binary |-
6
- NDlhMWY3NGRmOTUwMmQ1NGRjMjg2MjE2ZDY5NmYwNWE5NjgyZWM1MA==
7
- !binary "U0hBNTEy":
8
- metadata.gz: !binary |-
9
- MTkzNDAxZTZmNWM4YTg3OTEzYWJhM2Q1YmE3MzBhZjg0YjUxYWJmMjAwYWMz
10
- NGZmMGM0Mzk4MDM1MGU3OTFjZWVlNThhZTg1MDhiMmRmNDFhZjk3ZjcxYTA4
11
- OTllMzFjM2NkZWRmYmVhZTlmOTkwYzlhMGI3NmVkZjQ1NjRiMTE=
12
- data.tar.gz: !binary |-
13
- YzQ3ZmMzMzU1MzFmYzczZGI4M2FlYWRjMTY3Y2NmNmJlOTY5Y2UxMWNhODUz
14
- NTlmY2QwNTEyMmM0MWVkNGExNGJiNjdlYmViNjY3MzkyOWFhM2M3ZWUwY2Jm
15
- M2Q0ODNlNmJiMmU1MDI2Mjc3ZGIzYjE1ZWQ1YjgxZmZiNGY3MzU=