rpush 8.0.0 → 9.1.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.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +20 -6
  3. data/README.md +8 -65
  4. data/lib/generators/templates/rpush.rb +9 -16
  5. data/lib/rpush/client/active_model/fcm/notification.rb +1 -0
  6. data/lib/rpush/client/active_model.rb +0 -4
  7. data/lib/rpush/client/active_record/notification.rb +2 -0
  8. data/lib/rpush/client/active_record.rb +0 -3
  9. data/lib/rpush/client/redis.rb +0 -3
  10. data/lib/rpush/configuration.rb +2 -19
  11. data/lib/rpush/daemon/service_config_methods.rb +0 -2
  12. data/lib/rpush/daemon/store/active_record.rb +2 -14
  13. data/lib/rpush/daemon/store/interface.rb +2 -2
  14. data/lib/rpush/daemon/store/redis.rb +2 -11
  15. data/lib/rpush/daemon.rb +0 -10
  16. data/lib/rpush/reflection_collection.rb +1 -2
  17. data/lib/rpush/version.rb +2 -2
  18. data/lib/rpush.rb +0 -1
  19. data/spec/functional/cli_spec.rb +41 -15
  20. data/spec/functional/embed_spec.rb +57 -26
  21. data/spec/functional/retry_spec.rb +21 -4
  22. data/spec/functional/synchronization_spec.rb +1 -1
  23. data/spec/functional_spec_helper.rb +0 -6
  24. data/spec/spec_helper.rb +17 -7
  25. data/spec/unit/client/active_record/shared/app.rb +1 -1
  26. data/spec/unit/client/shared/fcm/notification.rb +6 -1
  27. data/spec/unit/daemon/shared/store.rb +0 -42
  28. metadata +61 -61
  29. data/lib/rpush/apns_feedback.rb +0 -18
  30. data/lib/rpush/client/active_model/gcm/app.rb +0 -19
  31. data/lib/rpush/client/active_model/gcm/expiry_collapse_key_mutual_inclusion_validator.rb +0 -14
  32. data/lib/rpush/client/active_model/gcm/notification.rb +0 -62
  33. data/lib/rpush/client/active_record/gcm/app.rb +0 -11
  34. data/lib/rpush/client/active_record/gcm/notification.rb +0 -11
  35. data/lib/rpush/client/redis/gcm/app.rb +0 -11
  36. data/lib/rpush/client/redis/gcm/notification.rb +0 -11
  37. data/lib/rpush/daemon/apns/delivery.rb +0 -43
  38. data/lib/rpush/daemon/apns/feedback_receiver.rb +0 -91
  39. data/lib/rpush/daemon/apns.rb +0 -17
  40. data/lib/rpush/daemon/dispatcher/apns_tcp.rb +0 -152
  41. data/lib/rpush/daemon/dispatcher/tcp.rb +0 -22
  42. data/lib/rpush/daemon/gcm/delivery.rb +0 -241
  43. data/lib/rpush/daemon/gcm.rb +0 -9
  44. data/lib/rpush/daemon/tcp_connection.rb +0 -190
  45. data/spec/functional/apns_spec.rb +0 -162
  46. data/spec/functional/gcm_priority_spec.rb +0 -40
  47. data/spec/functional/gcm_spec.rb +0 -46
  48. data/spec/functional/new_app_spec.rb +0 -44
  49. data/spec/unit/apns_feedback_spec.rb +0 -39
  50. data/spec/unit/client/active_record/gcm/app_spec.rb +0 -6
  51. data/spec/unit/client/active_record/gcm/notification_spec.rb +0 -14
  52. data/spec/unit/client/redis/gcm/app_spec.rb +0 -5
  53. data/spec/unit/client/redis/gcm/notification_spec.rb +0 -5
  54. data/spec/unit/client/shared/gcm/app.rb +0 -4
  55. data/spec/unit/client/shared/gcm/notification.rb +0 -77
  56. data/spec/unit/daemon/apns/delivery_spec.rb +0 -108
  57. data/spec/unit/daemon/apns/feedback_receiver_spec.rb +0 -137
  58. data/spec/unit/daemon/dispatcher/tcp_spec.rb +0 -32
  59. data/spec/unit/daemon/gcm/delivery_spec.rb +0 -387
  60. data/spec/unit/daemon/tcp_connection_spec.rb +0 -293
@@ -1,44 +0,0 @@
1
- require 'functional_spec_helper'
2
-
3
- describe 'New app loading' do
4
- let(:timeout) { 10 }
5
- let(:app) { create_app }
6
- let(:tcp_socket) { double(TCPSocket, setsockopt: nil, close: nil) }
7
- let(:ssl_socket) { double(OpenSSL::SSL::SSLSocket, :sync= => nil, connect: nil, write: nil, flush: nil, read: nil, close: nil) }
8
- let(:io_double) { double(select: nil) }
9
-
10
- before do
11
- stub_tcp_connection
12
- end
13
-
14
- def create_app
15
- app = Rpush::Apns::App.new
16
- app.certificate = TEST_CERT
17
- app.name = 'test'
18
- app.environment = 'sandbox'
19
- app.save!
20
- app
21
- end
22
-
23
- def create_notification
24
- notification = Rpush::Apns::Notification.new
25
- notification.app = app
26
- notification.alert = 'test'
27
- notification.device_token = 'a' * 108
28
- notification.save!
29
- notification
30
- end
31
-
32
- def stub_tcp_connection
33
- allow_any_instance_of(Rpush::Daemon::TcpConnection).to receive_messages(connect_socket: [tcp_socket, ssl_socket])
34
- allow_any_instance_of(Rpush::Daemon::TcpConnection).to receive_messages(setup_ssl_context: double.as_null_object)
35
- stub_const('Rpush::Daemon::TcpConnection::IO', io_double)
36
- end
37
-
38
- it 'delivers a notification successfully' do
39
- notification = create_notification
40
- Rpush.push
41
- notification.reload
42
- expect(notification.delivered).to eq(true)
43
- end
44
- end
@@ -1,39 +0,0 @@
1
- require 'unit_spec_helper'
2
-
3
- describe Rpush, 'apns_feedback' do
4
- let!(:apns_app) { Rpush::Apns::App.create!(apns_app_params) }
5
- let(:apns_app_params) do
6
- {
7
- name: 'test',
8
- environment: 'production',
9
- certificate: TEST_CERT
10
- }
11
- end
12
- let!(:gcm_app) { Rpush::Gcm::App.create!(name: 'MyApp', auth_key: 'abc123') }
13
-
14
- let(:receiver) { double(check_for_feedback: nil) }
15
-
16
- before do
17
- allow(Rpush::Daemon::Apns::FeedbackReceiver).to receive(:new) { receiver }
18
- end
19
-
20
- it 'initializes the daemon' do
21
- expect(Rpush::Daemon).to receive(:common_init)
22
- Rpush.apns_feedback
23
- end
24
-
25
- it 'checks feedback for each app' do
26
- expect(Rpush::Daemon::Apns::FeedbackReceiver).to receive(:new).with(apns_app).and_return(receiver)
27
- expect(receiver).to receive(:check_for_feedback)
28
- Rpush.apns_feedback
29
- end
30
-
31
- context 'feedback disabled' do
32
- let(:apns_app_params) { super().merge(feedback_enabled: false) }
33
-
34
- it 'does not initialize feedback receiver' do
35
- expect(Rpush::Daemon::Apns::FeedbackReceiver).not_to receive(:new)
36
- Rpush.apns_feedback
37
- end
38
- end
39
- end
@@ -1,6 +0,0 @@
1
- require 'unit_spec_helper'
2
-
3
- describe Rpush::Client::ActiveRecord::Gcm::App do
4
- it_behaves_like 'Rpush::Client::Gcm::App'
5
- it_behaves_like 'Rpush::Client::ActiveRecord::App'
6
- end if active_record?
@@ -1,14 +0,0 @@
1
- require 'unit_spec_helper'
2
-
3
- describe Rpush::Client::ActiveRecord::Gcm::Notification do
4
- it_behaves_like 'Rpush::Client::Gcm::Notification'
5
- it_behaves_like 'Rpush::Client::ActiveRecord::Notification'
6
-
7
- subject(:notification) { described_class.new }
8
- let(:app) { Rpush::Gcm::App.create!(name: 'test', auth_key: 'abc') }
9
-
10
- it 'accepts non-booleans as a truthy value' do
11
- notification.dry_run = 'Not a boolean'
12
- expect(notification.as_json['dry_run']).to eq true
13
- end
14
- end if active_record?
@@ -1,5 +0,0 @@
1
- require 'unit_spec_helper'
2
-
3
- describe Rpush::Client::Redis::Gcm::App do
4
- it_behaves_like 'Rpush::Client::Gcm::App'
5
- end if redis?
@@ -1,5 +0,0 @@
1
- require 'unit_spec_helper'
2
-
3
- describe Rpush::Client::Redis::Gcm::Notification do
4
- it_behaves_like 'Rpush::Client::Gcm::Notification'
5
- end if redis?
@@ -1,4 +0,0 @@
1
- require 'unit_spec_helper'
2
-
3
- shared_examples 'Rpush::Client::Gcm::App' do
4
- end
@@ -1,77 +0,0 @@
1
- require 'unit_spec_helper'
2
-
3
- shared_examples 'Rpush::Client::Gcm::Notification' do
4
- let(:app) { Rpush::Gcm::App.create!(name: 'test', auth_key: 'abc') }
5
- let(:notification) { described_class.new }
6
-
7
- it "has a 'data' payload limit of 4096 bytes" do
8
- notification.data = { key: "a" * 4096 }
9
- expect(notification.valid?).to be_falsey
10
- expect(notification.errors[:base]).to eq ["Notification payload data cannot be larger than 4096 bytes."]
11
- end
12
-
13
- it 'limits the number of registration ids to 1000' do
14
- notification.registration_ids = ['a'] * (1000 + 1)
15
- expect(notification.valid?).to be_falsey
16
- expect(notification.errors[:base]).to eq ["Number of registration_ids cannot be larger than 1000."]
17
- end
18
-
19
- it 'validates expiry is present if collapse_key is set' do
20
- notification.collapse_key = 'test'
21
- notification.expiry = nil
22
- expect(notification.valid?).to be_falsey
23
- expect(notification.errors[:expiry]).to eq ['must be set when using a collapse_key']
24
- end
25
-
26
- it 'includes time_to_live in the payload' do
27
- notification.expiry = 100
28
- expect(notification.as_json['time_to_live']).to eq 100
29
- end
30
-
31
- it 'includes content_available in the payload' do
32
- notification.content_available = true
33
- expect(notification.as_json['content_available']).to eq true
34
- end
35
-
36
- it 'includes mutable_content in the payload' do
37
- notification.mutable_content = true
38
- expect(notification.as_json['mutable_content']).to eq true
39
- end
40
-
41
- it 'sets the priority to high when set to high' do
42
- notification.priority = 'high'
43
- expect(notification.as_json['priority']).to eq 'high'
44
- end
45
-
46
- it 'sets the priority to normal when set to normal' do
47
- notification.priority = 'normal'
48
- expect(notification.as_json['priority']).to eq 'normal'
49
- end
50
-
51
- it 'validates the priority is either "normal" or "high"' do
52
- notification.priority = 'invalid'
53
- expect(notification.errors[:priority]).to eq ['must be one of either "normal" or "high"']
54
- end
55
-
56
- it 'excludes the priority if it is not defined' do
57
- expect(notification.as_json).not_to have_key 'priority'
58
- end
59
-
60
- it 'includes the notification payload if defined' do
61
- notification.notification = { key: 'any key is allowed' }
62
- expect(notification.as_json).to have_key 'notification'
63
- end
64
-
65
- it 'excludes the notification payload if undefined' do
66
- expect(notification.as_json).not_to have_key 'notification'
67
- end
68
-
69
- it 'includes the dry_run payload if defined' do
70
- notification.dry_run = true
71
- expect(notification.as_json['dry_run']).to eq true
72
- end
73
-
74
- it 'excludes the dry_run payload if undefined' do
75
- expect(notification.as_json).not_to have_key 'dry_run'
76
- end
77
- end
@@ -1,108 +0,0 @@
1
- require 'unit_spec_helper'
2
-
3
- describe Rpush::Daemon::Apns::Delivery do
4
- let(:app) { double(name: 'MyApp') }
5
- let(:notification1) { double.as_null_object }
6
- let(:notification2) { double.as_null_object }
7
- let(:batch) { double(mark_all_failed: nil, mark_all_delivered: nil, all_processed: nil) }
8
- let(:logger) { double(error: nil, info: nil) }
9
- let(:connection) { double(select: false, write: nil, reconnect: nil, close: nil, connect: nil) }
10
- let(:delivery) { Rpush::Daemon::Apns::Delivery.new(app, connection, batch) }
11
-
12
- before do
13
- allow(batch).to receive(:each_notification) do |&blk|
14
- [notification1, notification2].each(&blk)
15
- end
16
- allow(Rpush).to receive_messages(logger: logger)
17
- end
18
-
19
- it 'writes the binary batch' do
20
- allow(notification1).to receive_messages(to_binary: 'binary1')
21
- allow(notification2).to receive_messages(to_binary: 'binary2')
22
- expect(connection).to receive(:write).with('binary1binary2')
23
- delivery.perform
24
- end
25
-
26
- it 'logs the notification deliveries' do
27
- allow(notification1).to receive_messages(id: 666, device_token: 'abc123')
28
- allow(notification2).to receive_messages(id: 42, device_token: 'abc456')
29
- expect(logger).to receive(:info).with('[MyApp] 666 sent to abc123')
30
- expect(logger).to receive(:info).with('[MyApp] 42 sent to abc456')
31
- delivery.perform
32
- end
33
-
34
- it 'marks all notifications as delivered' do
35
- expect(delivery).to receive(:mark_batch_delivered)
36
- delivery.perform
37
- end
38
-
39
- it 'notifies the batch all notifications have been processed' do
40
- expect(batch).to receive(:all_processed)
41
- delivery.perform
42
- end
43
-
44
- describe 'when an error is raised' do
45
- it 'marks all notifications as failed' do
46
- error = StandardError.new
47
- allow(connection).to receive(:write).and_raise(error)
48
- expect(delivery).to receive(:mark_batch_failed).with(error)
49
- expect { delivery.perform }.to raise_error(error)
50
- end
51
- end
52
-
53
- # describe "when delivery fails" do
54
- # before { connection.stub(select: true, read: [8, 4, 69].pack("ccN")) }
55
- #
56
- # it "marks the notification as failed" do
57
- # delivery.should_receive(:mark_failed).with(4, "Unable to deliver notification 69, received error 4 (Missing payload)")
58
- # perform
59
- # end
60
- #
61
- # it "logs the delivery error" do
62
- # # checking for the doublebed error doesn't work in jruby, but checking
63
- # # for the exception by class does.
64
- #
65
- # # error = Rpush::DeliveryError.new(4, 12, "Missing payload")
66
- # # Rpush::DeliveryError.stub(new: error)
67
- # # expect { delivery.perform }.to raise_error(error)
68
- #
69
- # expect { delivery.perform }.to raise_error(Rpush::DeliveryError)
70
- # end
71
- #
72
- # it "reads 6 bytes from the socket" do
73
- # connection.should_receive(:read).with(6).and_return(nil)
74
- # perform
75
- # end
76
- #
77
- # it "does not attempt to read from the socket if the socket was not selected for reading after the timeout" do
78
- # connection.stub(select: nil)
79
- # connection.should_not_receive(:read)
80
- # perform
81
- # end
82
- #
83
- # it "reconnects the socket" do
84
- # connection.should_receive(:reconnect)
85
- # perform
86
- # end
87
- #
88
- # it "logs that the connection is being reconnected" do
89
- # Rpush.logger.should_receive(:error).with("[MyApp] Error received, reconnecting...")
90
- # perform
91
- # end
92
- #
93
- # context "when the APNs disconnects without returning an error" do
94
- # before do
95
- # connection.stub(read: nil)
96
- # end
97
- #
98
- # it 'raises a DisconnectError error if the connection is closed without an error being returned' do
99
- # expect { delivery.perform }.to raise_error(Rpush::DisconnectionError)
100
- # end
101
- #
102
- # it 'marks the notification as failed' do
103
- # delivery.should_receive(:mark_failed).with(nil, "The APNs disconnected without returning an error. This may indicate you are using an invalid certificate for the host.")
104
- # perform
105
- # end
106
- # end
107
- # end
108
- end
@@ -1,137 +0,0 @@
1
- require 'unit_spec_helper'
2
- require 'rpush/daemon/store/active_record'
3
-
4
- describe Rpush::Daemon::Apns::FeedbackReceiver, 'check_for_feedback' do
5
- let(:host) { 'feedback.push.apple.com' }
6
- let(:port) { 2196 }
7
- let(:frequency) { 60 }
8
- let(:certificate) { double }
9
- let(:password) { double }
10
- let(:feedback_enabled) { true }
11
- let(:app) do
12
- double(
13
- name: 'my_app',
14
- password: password,
15
- certificate: certificate,
16
- feedback_enabled: feedback_enabled,
17
- environment: 'production'
18
- )
19
- end
20
- let(:connection) { double(connect: nil, read: nil, close: nil) }
21
- let(:logger) { double(error: nil, info: nil) }
22
- let(:receiver) { Rpush::Daemon::Apns::FeedbackReceiver.new(app) }
23
- let(:feedback) { double }
24
- let(:sleeper) { double(Rpush::Daemon::InterruptibleSleep, sleep: nil, stop: nil) }
25
- let(:store) { double(Rpush::Daemon::Store::ActiveRecord, create_apns_feedback: feedback, release_connection: nil) }
26
-
27
- before do
28
- Rpush.config.apns.feedback_receiver.frequency = frequency
29
- allow(Rpush::Daemon::InterruptibleSleep).to receive_messages(new: sleeper)
30
- allow(Rpush).to receive_messages(logger: logger)
31
- allow(Rpush::Daemon::TcpConnection).to receive_messages(new: connection)
32
- receiver.instance_variable_set("@stop", false)
33
- allow(Rpush::Daemon).to receive_messages(store: store)
34
- end
35
-
36
- def double_connection_read_with_tuple
37
- def connection.read(*)
38
- unless @called
39
- @called = true
40
- "N\xE3\x84\r\x00 \x83OxfU\xEB\x9F\x84aJ\x05\xAD}\x00\xAF1\xE5\xCF\xE9:\xC3\xEA\a\x8F\x1D\xA4M*N\xB0\xCE\x17"
41
- end
42
- end
43
- end
44
-
45
- it 'initializes the sleeper with the feedback polling frequency' do
46
- expect(Rpush::Daemon::InterruptibleSleep).to receive_messages(new: sleeper)
47
- Rpush::Daemon::Apns::FeedbackReceiver.new(app)
48
- end
49
-
50
- it 'instantiates a new connection' do
51
- expect(Rpush::Daemon::TcpConnection).to receive(:new).with(app, host, port)
52
- receiver.check_for_feedback
53
- end
54
-
55
- it 'connects to the feeback service' do
56
- expect(connection).to receive(:connect)
57
- receiver.check_for_feedback
58
- end
59
-
60
- it 'closes the connection' do
61
- expect(connection).to receive(:close)
62
- receiver.check_for_feedback
63
- end
64
-
65
- it 'reads from the connection' do
66
- expect(connection).to receive(:read).with(38)
67
- receiver.check_for_feedback
68
- end
69
-
70
- it 'logs the feedback' do
71
- double_connection_read_with_tuple
72
- expect(Rpush.logger).to receive(:info).with("[my_app] [FeedbackReceiver] Delivery failed at 2011-12-10 16:08:45 UTC for 834f786655eb9f84614a05ad7d00af31e5cfe93ac3ea078f1da44d2a4eb0ce17.")
73
- receiver.check_for_feedback
74
- end
75
-
76
- it 'creates the feedback' do
77
- expect(Rpush::Daemon.store).to receive(:create_apns_feedback).with(Time.at(1_323_533_325), '834f786655eb9f84614a05ad7d00af31e5cfe93ac3ea078f1da44d2a4eb0ce17', app)
78
- double_connection_read_with_tuple
79
- receiver.check_for_feedback
80
- end
81
-
82
- it 'logs errors' do
83
- error = StandardError.new('bork!')
84
- allow(connection).to receive(:read).and_raise(error)
85
- expect(Rpush.logger).to receive(:error).with(error)
86
- receiver.check_for_feedback
87
- end
88
-
89
- describe 'start' do
90
- before do
91
- allow(Thread).to receive(:new).and_yield
92
- allow(receiver).to receive(:loop).and_yield
93
- end
94
-
95
- it 'sleeps' do
96
- allow(receiver).to receive(:check_for_feedback)
97
- expect(sleeper).to receive(:sleep).at_least(:once)
98
- receiver.start
99
- end
100
-
101
- it 'checks for feedback when started' do
102
- expect(receiver).to receive(:check_for_feedback).at_least(:once)
103
- receiver.start
104
- end
105
-
106
- context 'with feedback_enabled false' do
107
- let(:feedback_enabled) { false }
108
-
109
- it 'does not check for feedback when started' do
110
- expect(receiver).not_to receive(:check_for_feedback)
111
- receiver.start
112
- end
113
- end
114
- end
115
-
116
- describe 'stop' do
117
- it 'interrupts sleep when stopped' do
118
- allow(receiver).to receive(:check_for_feedback)
119
- expect(sleeper).to receive(:stop)
120
- receiver.stop
121
- end
122
-
123
- it 'releases the store connection' do
124
- allow(Thread).to receive(:new).and_yield
125
- allow(receiver).to receive(:loop).and_yield
126
- expect(Rpush::Daemon.store).to receive(:release_connection)
127
- receiver.start
128
- receiver.stop
129
- end
130
- end
131
-
132
- it 'reflects feedback was received' do
133
- double_connection_read_with_tuple
134
- expect(receiver).to receive(:reflect).with(:apns_feedback, feedback)
135
- receiver.check_for_feedback
136
- end
137
- end
@@ -1,32 +0,0 @@
1
- require 'unit_spec_helper'
2
-
3
- describe Rpush::Daemon::Dispatcher::Tcp do
4
- let(:app) { double }
5
- let(:delivery) { double(perform: nil) }
6
- let(:delivery_class) { double(new: delivery) }
7
- let(:notification) { double }
8
- let(:batch) { double }
9
- let(:connection) { double(Rpush::Daemon::TcpConnection, connect: nil) }
10
- let(:host) { 'localhost' }
11
- let(:port) { 1234 }
12
- let(:host_proc) { proc { [host, port] } }
13
- let(:queue_payload) { Rpush::Daemon::QueuePayload.new(batch, notification) }
14
- let(:dispatcher) { Rpush::Daemon::Dispatcher::Tcp.new(app, delivery_class, host: host_proc) }
15
-
16
- before { allow(Rpush::Daemon::TcpConnection).to receive_messages(new: connection) }
17
-
18
- describe 'dispatch' do
19
- it 'delivers the notification' do
20
- expect(delivery_class).to receive(:new).with(app, connection, notification, batch).and_return(delivery)
21
- expect(delivery).to receive(:perform)
22
- dispatcher.dispatch(queue_payload)
23
- end
24
- end
25
-
26
- describe 'cleanup' do
27
- it 'closes the connection' do
28
- expect(connection).to receive(:close)
29
- dispatcher.cleanup
30
- end
31
- end
32
- end