ably-rest 1.1.2 → 1.2.2
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.
- checksums.yaml +4 -4
- data/.travis.yml +3 -0
- data/CHANGELOG.md +1 -1
- data/MAINTAINERS.md +1 -0
- data/README.md +4 -2
- data/ably-rest.gemspec +15 -18
- data/lib/ably-rest.rb +2 -0
- data/lib/submodules/ably-ruby/.github/workflows/check.yml +50 -0
- data/lib/submodules/ably-ruby/CHANGELOG.md +200 -0
- data/lib/submodules/ably-ruby/COPYRIGHT +1 -0
- data/lib/submodules/ably-ruby/LICENSE +172 -11
- data/lib/submodules/ably-ruby/MAINTAINERS.md +1 -0
- data/lib/submodules/ably-ruby/README.md +24 -22
- data/lib/submodules/ably-ruby/SPEC.md +1020 -929
- data/lib/submodules/ably-ruby/UPDATING.md +30 -0
- data/lib/submodules/ably-ruby/ably.gemspec +16 -23
- data/lib/submodules/ably-ruby/lib/ably/agent.rb +3 -0
- data/lib/submodules/ably-ruby/lib/ably/auth.rb +20 -10
- data/lib/submodules/ably-ruby/lib/ably/exceptions.rb +8 -2
- data/lib/submodules/ably-ruby/lib/ably/logger.rb +4 -4
- data/lib/submodules/ably-ruby/lib/ably/models/channel_details.rb +59 -0
- data/lib/submodules/ably-ruby/lib/ably/models/channel_metrics.rb +84 -0
- data/lib/submodules/ably-ruby/lib/ably/models/channel_occupancy.rb +43 -0
- data/lib/submodules/ably-ruby/lib/ably/models/channel_options.rb +97 -0
- data/lib/submodules/ably-ruby/lib/ably/models/channel_status.rb +53 -0
- data/lib/submodules/ably-ruby/lib/ably/models/connection_details.rb +8 -0
- data/lib/submodules/ably-ruby/lib/ably/models/delta_extras.rb +29 -0
- data/lib/submodules/ably-ruby/lib/ably/models/device_details.rb +1 -1
- data/lib/submodules/ably-ruby/lib/ably/models/error_info.rb +6 -2
- data/lib/submodules/ably-ruby/lib/ably/models/idiomatic_ruby_wrapper.rb +4 -0
- data/lib/submodules/ably-ruby/lib/ably/models/message.rb +28 -3
- data/lib/submodules/ably-ruby/lib/ably/models/presence_message.rb +14 -0
- data/lib/submodules/ably-ruby/lib/ably/models/protocol_message.rb +31 -14
- data/lib/submodules/ably-ruby/lib/ably/models/token_details.rb +7 -2
- data/lib/submodules/ably-ruby/lib/ably/models/token_request.rb +1 -1
- data/lib/submodules/ably-ruby/lib/ably/modules/ably.rb +11 -1
- data/lib/submodules/ably-ruby/lib/ably/modules/channels_collection.rb +22 -2
- data/lib/submodules/ably-ruby/lib/ably/modules/conversions.rb +34 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/auth.rb +2 -2
- data/lib/submodules/ably-ruby/lib/ably/realtime/channel/channel_manager.rb +19 -7
- data/lib/submodules/ably-ruby/lib/ably/realtime/channel/channel_properties.rb +24 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/channel/channel_state_machine.rb +10 -1
- data/lib/submodules/ably-ruby/lib/ably/realtime/channel/publisher.rb +6 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/channel.rb +56 -28
- data/lib/submodules/ably-ruby/lib/ably/realtime/channels.rb +1 -1
- data/lib/submodules/ably-ruby/lib/ably/realtime/client/incoming_message_dispatcher.rb +14 -6
- data/lib/submodules/ably-ruby/lib/ably/realtime/client.rb +9 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/connection/connection_manager.rb +13 -4
- data/lib/submodules/ably-ruby/lib/ably/realtime/connection/connection_state_machine.rb +4 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/connection/websocket_transport.rb +67 -1
- data/lib/submodules/ably-ruby/lib/ably/realtime/connection.rb +6 -5
- data/lib/submodules/ably-ruby/lib/ably/realtime/presence.rb +0 -14
- data/lib/submodules/ably-ruby/lib/ably/rest/channel.rb +44 -29
- data/lib/submodules/ably-ruby/lib/ably/rest/client.rb +60 -29
- data/lib/submodules/ably-ruby/lib/ably/rest/middleware/encoder.rb +1 -1
- data/lib/submodules/ably-ruby/lib/ably/rest/middleware/exceptions.rb +1 -1
- data/lib/submodules/ably-ruby/lib/ably/rest/middleware/external_exceptions.rb +1 -1
- data/lib/submodules/ably-ruby/lib/ably/rest/middleware/fail_if_unsupported_mime_type.rb +5 -2
- data/lib/submodules/ably-ruby/lib/ably/rest/middleware/logger.rb +1 -1
- data/lib/submodules/ably-ruby/lib/ably/rest/middleware/parse_json.rb +1 -1
- data/lib/submodules/ably-ruby/lib/ably/rest/middleware/parse_message_pack.rb +1 -1
- data/lib/submodules/ably-ruby/lib/ably/util/crypto.rb +1 -1
- data/lib/submodules/ably-ruby/lib/ably/version.rb +2 -14
- data/lib/submodules/ably-ruby/lib/ably.rb +1 -0
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/auth_spec.rb +4 -4
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/channel_history_spec.rb +25 -0
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/channel_spec.rb +476 -21
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/channels_spec.rb +59 -7
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/client_spec.rb +72 -16
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_failures_spec.rb +85 -13
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_spec.rb +301 -34
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/message_spec.rb +77 -0
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/presence_history_spec.rb +3 -59
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/presence_spec.rb +84 -158
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/push_admin_spec.rb +3 -19
- data/lib/submodules/ably-ruby/spec/acceptance/rest/auth_spec.rb +24 -75
- data/lib/submodules/ably-ruby/spec/acceptance/rest/base_spec.rb +8 -4
- data/lib/submodules/ably-ruby/spec/acceptance/rest/channel_spec.rb +141 -10
- data/lib/submodules/ably-ruby/spec/acceptance/rest/channels_spec.rb +23 -6
- data/lib/submodules/ably-ruby/spec/acceptance/rest/client_spec.rb +146 -47
- data/lib/submodules/ably-ruby/spec/acceptance/rest/message_spec.rb +61 -3
- data/lib/submodules/ably-ruby/spec/acceptance/rest/push_admin_spec.rb +3 -19
- data/lib/submodules/ably-ruby/spec/lib/unit/models/channel_options_spec.rb +52 -0
- data/lib/submodules/ably-ruby/spec/run_parallel_tests +2 -7
- data/lib/submodules/ably-ruby/spec/shared/client_initializer_behaviour.rb +131 -8
- data/lib/submodules/ably-ruby/spec/shared/model_behaviour.rb +1 -1
- data/lib/submodules/ably-ruby/spec/spec_helper.rb +12 -2
- data/lib/submodules/ably-ruby/spec/support/serialization_helper.rb +21 -0
- data/lib/submodules/ably-ruby/spec/support/test_app.rb +3 -3
- data/lib/submodules/ably-ruby/spec/unit/logger_spec.rb +6 -14
- data/lib/submodules/ably-ruby/spec/unit/models/channel_details_spec.rb +30 -0
- data/lib/submodules/ably-ruby/spec/unit/models/channel_metrics_spec.rb +42 -0
- data/lib/submodules/ably-ruby/spec/unit/models/channel_occupancy_spec.rb +17 -0
- data/lib/submodules/ably-ruby/spec/unit/models/channel_status_spec.rb +36 -0
- data/lib/submodules/ably-ruby/spec/unit/models/delta_extras_spec.rb +14 -0
- data/lib/submodules/ably-ruby/spec/unit/models/error_info_spec.rb +17 -1
- data/lib/submodules/ably-ruby/spec/unit/models/message_spec.rb +97 -0
- data/lib/submodules/ably-ruby/spec/unit/models/presence_message_spec.rb +49 -0
- data/lib/submodules/ably-ruby/spec/unit/models/protocol_message_spec.rb +125 -27
- data/lib/submodules/ably-ruby/spec/unit/models/token_details_spec.rb +14 -0
- data/lib/submodules/ably-ruby/spec/unit/realtime/channel_spec.rb +3 -2
- data/lib/submodules/ably-ruby/spec/unit/realtime/channels_spec.rb +53 -15
- data/lib/submodules/ably-ruby/spec/unit/realtime/client_spec.rb +19 -6
- data/lib/submodules/ably-ruby/spec/unit/realtime/incoming_message_dispatcher_spec.rb +38 -0
- data/lib/submodules/ably-ruby/spec/unit/rest/channel_spec.rb +44 -1
- data/lib/submodules/ably-ruby/spec/unit/rest/channels_spec.rb +81 -14
- data/lib/submodules/ably-ruby/spec/unit/rest/client_spec.rb +47 -0
- data/spec/spec_helper.rb +5 -0
- data/spec/unit/client_spec.rb +30 -0
- metadata +88 -25
- data/lib/submodules/ably-ruby/.travis.yml +0 -19
|
@@ -77,18 +77,6 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
|
77
77
|
end
|
|
78
78
|
end
|
|
79
79
|
end
|
|
80
|
-
|
|
81
|
-
context 'with implicit authorisation' do
|
|
82
|
-
let(:client_options) { default_options.merge(client_id: 'force_token_auth') }
|
|
83
|
-
|
|
84
|
-
it 'uses the token created by the implicit authorisation' do
|
|
85
|
-
expect(client.rest_client.auth).to receive(:request_token).once.and_call_original
|
|
86
|
-
|
|
87
|
-
connection.once(:connected) do
|
|
88
|
-
stop_reactor
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
end
|
|
92
80
|
end
|
|
93
81
|
|
|
94
82
|
context 'that expire' do
|
|
@@ -134,7 +122,7 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
|
134
122
|
end
|
|
135
123
|
end
|
|
136
124
|
|
|
137
|
-
context 'with immediately expired token' do
|
|
125
|
+
context 'with immediately expired token and no fallback hosts' do
|
|
138
126
|
let(:ttl) { 0.001 }
|
|
139
127
|
let(:auth_requests) { [] }
|
|
140
128
|
let(:token_callback) do
|
|
@@ -143,7 +131,7 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
|
143
131
|
Ably::Rest::Client.new(default_options).auth.request_token(ttl: ttl).token
|
|
144
132
|
end
|
|
145
133
|
end
|
|
146
|
-
let(:client_options) { default_options.merge(auth_callback: token_callback) }
|
|
134
|
+
let(:client_options) { default_options.merge(auth_callback: token_callback, fallback_hosts: []) }
|
|
147
135
|
|
|
148
136
|
it 'renews the token on connect, and makes one immediate subsequent attempt to obtain a new token (#RSA4b)' do
|
|
149
137
|
started_at = Time.now.to_f
|
|
@@ -158,7 +146,7 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
|
158
146
|
end
|
|
159
147
|
|
|
160
148
|
context 'when disconnected_retry_timeout is 0.5 seconds' do
|
|
161
|
-
let(:client_options) { default_options.merge(disconnected_retry_timeout: 0.5, auth_callback: token_callback) }
|
|
149
|
+
let(:client_options) { default_options.merge(disconnected_retry_timeout: 0.5, auth_callback: token_callback, fallback_hosts: []) }
|
|
162
150
|
|
|
163
151
|
it 'renews the token on connect, and continues to attempt renew based on the retry schedule' do
|
|
164
152
|
disconnect_count = 0
|
|
@@ -184,7 +172,7 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
|
184
172
|
end
|
|
185
173
|
|
|
186
174
|
context 'using implicit token auth' do
|
|
187
|
-
let(:client_options) { default_options.merge(use_token_auth: true, default_token_params: { ttl: ttl }) }
|
|
175
|
+
let(:client_options) { default_options.merge(use_token_auth: true, default_token_params: { ttl: ttl }, fallback_hosts: []) }
|
|
188
176
|
|
|
189
177
|
before do
|
|
190
178
|
stub_const 'Ably::Models::TokenDetails::TOKEN_EXPIRY_BUFFER', -10 # ensure client lib thinks token is still valid
|
|
@@ -453,7 +441,9 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
|
453
441
|
end
|
|
454
442
|
end
|
|
455
443
|
|
|
456
|
-
context '#connect' do
|
|
444
|
+
context '#connect with no fallbacks' do
|
|
445
|
+
let(:client_options) { default_options.merge(fallback_hosts: []) }
|
|
446
|
+
|
|
457
447
|
it 'returns a SafeDeferrable that catches exceptions in callbacks and logs them' do
|
|
458
448
|
expect(connection.connect).to be_a(Ably::Util::SafeDeferrable)
|
|
459
449
|
stop_reactor
|
|
@@ -492,6 +482,138 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
|
492
482
|
end
|
|
493
483
|
end
|
|
494
484
|
|
|
485
|
+
context "when can't connect to host" do
|
|
486
|
+
let(:client_options) { super().merge(realtime_host: 'non-existent.ably.io') }
|
|
487
|
+
|
|
488
|
+
it 'logs error on failed connection attempt' do
|
|
489
|
+
logger_expectation = lambda do |*args, &block|
|
|
490
|
+
error_message = "Connection to non-existent.ably.io:443 failed"
|
|
491
|
+
expect(args.concat([block ? block.call : nil]).join(',')).to include(error_message)
|
|
492
|
+
stop_reactor
|
|
493
|
+
end
|
|
494
|
+
|
|
495
|
+
expect(connection.logger).to receive(:warn, &logger_expectation).at_least(:once)
|
|
496
|
+
|
|
497
|
+
connection.on(:connected) do
|
|
498
|
+
raise "Connection should not succeed"
|
|
499
|
+
end
|
|
500
|
+
|
|
501
|
+
connection.connect
|
|
502
|
+
end
|
|
503
|
+
end
|
|
504
|
+
|
|
505
|
+
context 'when explicitly reconnecting disconnected/suspended connection in retry (#RTN11c)' do
|
|
506
|
+
let(:close_connection_proc) do
|
|
507
|
+
lambda do
|
|
508
|
+
EventMachine.add_timer(0.001) do
|
|
509
|
+
if connection.transport.nil?
|
|
510
|
+
close_connection_proc.call
|
|
511
|
+
else
|
|
512
|
+
connection.transport.close_connection_after_writing
|
|
513
|
+
end
|
|
514
|
+
end
|
|
515
|
+
end
|
|
516
|
+
end
|
|
517
|
+
|
|
518
|
+
context 'when suspended' do
|
|
519
|
+
let(:suspended_retry_timeout) { 60 }
|
|
520
|
+
let(:client_options) do
|
|
521
|
+
default_options.merge(
|
|
522
|
+
disconnected_retry_timeout: 0.02,
|
|
523
|
+
suspended_retry_timeout: suspended_retry_timeout,
|
|
524
|
+
connection_state_ttl: 0
|
|
525
|
+
)
|
|
526
|
+
end
|
|
527
|
+
|
|
528
|
+
it 'reconnects immediately' do
|
|
529
|
+
connection.once(:connecting) { close_connection_proc.call }
|
|
530
|
+
|
|
531
|
+
connection.on(:suspended) do |connection_state_change|
|
|
532
|
+
if connection_state_change.retry_in.zero?
|
|
533
|
+
# Exhausting immediate retries
|
|
534
|
+
connection.once(:connecting) { close_connection_proc.call }
|
|
535
|
+
else
|
|
536
|
+
suspended_at = Time.now.to_f
|
|
537
|
+
connection.on(:connected) do
|
|
538
|
+
expect(connection_state_change.retry_in).to eq(suspended_retry_timeout)
|
|
539
|
+
expect(connection.state).to eq(:connected)
|
|
540
|
+
expect(Time.now.to_f).to be_within(4).of(suspended_at)
|
|
541
|
+
stop_reactor
|
|
542
|
+
end
|
|
543
|
+
end
|
|
544
|
+
|
|
545
|
+
connection.connect
|
|
546
|
+
end
|
|
547
|
+
|
|
548
|
+
connection.connect
|
|
549
|
+
end
|
|
550
|
+
end
|
|
551
|
+
|
|
552
|
+
context 'when disconnected' do
|
|
553
|
+
let(:retry_timeout) { 60 }
|
|
554
|
+
let(:client_options) do
|
|
555
|
+
default_options.merge(
|
|
556
|
+
disconnected_retry_timeout: retry_timeout,
|
|
557
|
+
suspended_retry_timeout: retry_timeout,
|
|
558
|
+
connection_state_ttl: 0
|
|
559
|
+
)
|
|
560
|
+
end
|
|
561
|
+
|
|
562
|
+
it 'reconnects immediately' do
|
|
563
|
+
connection.once(:connected) do
|
|
564
|
+
connection.on(:disconnected) do |connection_state_change|
|
|
565
|
+
disconnected_at = Time.now.to_f
|
|
566
|
+
connection.on(:connected) do
|
|
567
|
+
if connection_state_change.retry_in.zero?
|
|
568
|
+
# Exhausting immediate retries
|
|
569
|
+
close_connection_proc.call
|
|
570
|
+
else
|
|
571
|
+
expect(connection_state_change.retry_in).to eq(retry_timeout)
|
|
572
|
+
expect(connection.state).to eq(:connected)
|
|
573
|
+
expect(Time.now.to_f).to be_within(4).of(disconnected_at)
|
|
574
|
+
stop_reactor
|
|
575
|
+
end
|
|
576
|
+
end
|
|
577
|
+
connection.connect
|
|
578
|
+
end
|
|
579
|
+
|
|
580
|
+
close_connection_proc.call
|
|
581
|
+
end
|
|
582
|
+
|
|
583
|
+
connection.connect
|
|
584
|
+
end
|
|
585
|
+
end
|
|
586
|
+
end
|
|
587
|
+
|
|
588
|
+
context 'when reconnecting a failed connection' do
|
|
589
|
+
let(:channel) { client.channel(random_str) }
|
|
590
|
+
let(:client_options) { default_options.merge(log_level: :none) }
|
|
591
|
+
|
|
592
|
+
it 'transitions all channels state to initialized and cleares error_reason' do
|
|
593
|
+
connection.on(:failed) do |connection_state_change|
|
|
594
|
+
expect(connection.error_reason).to be_a(Ably::Exceptions::BaseAblyException)
|
|
595
|
+
expect(channel.error_reason).to be_a(Ably::Exceptions::BaseAblyException)
|
|
596
|
+
expect(channel).to be_failed
|
|
597
|
+
|
|
598
|
+
connection.on(:connected) do
|
|
599
|
+
expect(connection.error_reason).to eq(nil)
|
|
600
|
+
expect(channel).to be_initialized
|
|
601
|
+
expect(channel.error_reason).to eq(nil)
|
|
602
|
+
stop_reactor
|
|
603
|
+
end
|
|
604
|
+
|
|
605
|
+
connection.connect
|
|
606
|
+
end
|
|
607
|
+
|
|
608
|
+
connection.connect do
|
|
609
|
+
channel.attach do
|
|
610
|
+
error = Ably::Exceptions::ConnectionFailed.new('forced failure', 500, 50000)
|
|
611
|
+
client.connection.manager.error_received_from_server error
|
|
612
|
+
end
|
|
613
|
+
end
|
|
614
|
+
end
|
|
615
|
+
end
|
|
616
|
+
|
|
495
617
|
context 'with invalid auth details' do
|
|
496
618
|
let(:client_options) { default_options.merge(key: 'this.is:invalid', log_level: :none) }
|
|
497
619
|
|
|
@@ -703,6 +825,18 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
|
703
825
|
end
|
|
704
826
|
|
|
705
827
|
context '#close' do
|
|
828
|
+
let(:close_connection_proc) do
|
|
829
|
+
lambda do
|
|
830
|
+
EventMachine.add_timer(0.001) do
|
|
831
|
+
if connection.transport.nil?
|
|
832
|
+
close_connection_proc.call
|
|
833
|
+
else
|
|
834
|
+
connection.transport.close_connection_after_writing
|
|
835
|
+
end
|
|
836
|
+
end
|
|
837
|
+
end
|
|
838
|
+
end
|
|
839
|
+
|
|
706
840
|
it 'returns a SafeDeferrable that catches exceptions in callbacks and logs them' do
|
|
707
841
|
connection.connect do
|
|
708
842
|
expect(connection.close).to be_a(Ably::Util::SafeDeferrable)
|
|
@@ -764,6 +898,56 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
|
764
898
|
end
|
|
765
899
|
end
|
|
766
900
|
|
|
901
|
+
context ':connecting RTN12f' do
|
|
902
|
+
context ":connected does not arrive when trying to close" do
|
|
903
|
+
it 'moves to closed' do
|
|
904
|
+
connection.on(:closed) do |state_change|
|
|
905
|
+
state_changes = connection.state_history.map { |t| t[:state].to_sym }
|
|
906
|
+
|
|
907
|
+
expect(state_changes).to eq([:connecting, :closing, :closed])
|
|
908
|
+
stop_reactor
|
|
909
|
+
end
|
|
910
|
+
|
|
911
|
+
connection.on(:connecting) do
|
|
912
|
+
connection.close
|
|
913
|
+
connection.__outgoing_protocol_msgbus__.unsubscribe
|
|
914
|
+
end
|
|
915
|
+
|
|
916
|
+
connection.connect
|
|
917
|
+
end
|
|
918
|
+
end
|
|
919
|
+
|
|
920
|
+
context ":connected arrive when trying to close" do
|
|
921
|
+
let(:protocol_message_attributes) do
|
|
922
|
+
{
|
|
923
|
+
action: Ably::Models::ProtocolMessage::ACTION.Connected.to_i,
|
|
924
|
+
connection_serial: 55,
|
|
925
|
+
connection_details: {
|
|
926
|
+
max_idle_interval: 2 * 1000
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
end
|
|
930
|
+
|
|
931
|
+
it 'moves to connected and then to closed' do
|
|
932
|
+
connection.on(:closed) do |state_change|
|
|
933
|
+
state_changes = connection.state_history.map { |t| t[:state].to_sym }
|
|
934
|
+
|
|
935
|
+
expect(state_changes).to eq([:connecting, :connected, :closing, :closed])
|
|
936
|
+
stop_reactor
|
|
937
|
+
end
|
|
938
|
+
|
|
939
|
+
connection.on(:connecting) do
|
|
940
|
+
connection.__outgoing_protocol_msgbus__.unsubscribe
|
|
941
|
+
|
|
942
|
+
connection.__incoming_protocol_msgbus__.publish :protocol_message, Ably::Models::ProtocolMessage.new(protocol_message_attributes)
|
|
943
|
+
connection.close
|
|
944
|
+
end
|
|
945
|
+
|
|
946
|
+
connection.connect
|
|
947
|
+
end
|
|
948
|
+
end
|
|
949
|
+
end
|
|
950
|
+
|
|
767
951
|
context ':connected' do
|
|
768
952
|
it 'changes the connection state to :closing and waits for the server to confirm connection is :closed with a ProtocolMessage' do
|
|
769
953
|
connection.on(:connected) do
|
|
@@ -810,6 +994,81 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
|
810
994
|
end
|
|
811
995
|
end
|
|
812
996
|
end
|
|
997
|
+
|
|
998
|
+
context ':suspended RTN12d' do
|
|
999
|
+
let(:suspended_retry_timeout) { 60 }
|
|
1000
|
+
let(:client_options) do
|
|
1001
|
+
default_options.merge(
|
|
1002
|
+
disconnected_retry_timeout: 0.02,
|
|
1003
|
+
suspended_retry_timeout: suspended_retry_timeout,
|
|
1004
|
+
connection_state_ttl: 0
|
|
1005
|
+
)
|
|
1006
|
+
end
|
|
1007
|
+
|
|
1008
|
+
it 'immediatly closes connection' do
|
|
1009
|
+
connection.on(:connecting) { close_connection_proc.call }
|
|
1010
|
+
connection.on(:suspended) do |connection_state_change|
|
|
1011
|
+
if connection_state_change.retry_in.zero?
|
|
1012
|
+
# Exhausting immediate retries
|
|
1013
|
+
connection.once(:connecting) { close_connection_proc.call }
|
|
1014
|
+
else
|
|
1015
|
+
suspended_at = Time.now.to_f
|
|
1016
|
+
connection.on(:closed) do
|
|
1017
|
+
expect(connection_state_change.retry_in).to eq(suspended_retry_timeout)
|
|
1018
|
+
expect(connection.state).to eq(:closed)
|
|
1019
|
+
expect(Time.now.to_f).to be_within(4).of(suspended_at)
|
|
1020
|
+
stop_reactor
|
|
1021
|
+
end
|
|
1022
|
+
|
|
1023
|
+
connection.close
|
|
1024
|
+
end
|
|
1025
|
+
|
|
1026
|
+
connection.connect
|
|
1027
|
+
end
|
|
1028
|
+
|
|
1029
|
+
connection.connect
|
|
1030
|
+
end
|
|
1031
|
+
end
|
|
1032
|
+
|
|
1033
|
+
context ':disconnected RTN12d' do
|
|
1034
|
+
let(:retry_timeout) { 60 }
|
|
1035
|
+
let(:client_options) do
|
|
1036
|
+
default_options.merge(
|
|
1037
|
+
disconnected_retry_timeout: retry_timeout,
|
|
1038
|
+
suspended_retry_timeout: retry_timeout,
|
|
1039
|
+
connection_state_ttl: 0
|
|
1040
|
+
)
|
|
1041
|
+
end
|
|
1042
|
+
|
|
1043
|
+
it 'immediatly closes connection' do
|
|
1044
|
+
connection.once(:connected) do
|
|
1045
|
+
connection.on(:disconnected) do |connection_state_change|
|
|
1046
|
+
disconnected_at = Time.now.to_f
|
|
1047
|
+
connection.on(:connected) do
|
|
1048
|
+
if connection_state_change.retry_in.zero?
|
|
1049
|
+
# Exhausting immediate retries
|
|
1050
|
+
close_connection_proc.call
|
|
1051
|
+
else
|
|
1052
|
+
connection.once(:closed) do
|
|
1053
|
+
expect(connection_state_change.retry_in).to eq(retry_timeout)
|
|
1054
|
+
expect(connection.state).to eq(:closed)
|
|
1055
|
+
expect(Time.now.to_f).to be_within(4).of(disconnected_at)
|
|
1056
|
+
stop_reactor
|
|
1057
|
+
end
|
|
1058
|
+
|
|
1059
|
+
connection.close
|
|
1060
|
+
end
|
|
1061
|
+
end
|
|
1062
|
+
|
|
1063
|
+
connection.connect
|
|
1064
|
+
end
|
|
1065
|
+
|
|
1066
|
+
close_connection_proc.call
|
|
1067
|
+
end
|
|
1068
|
+
|
|
1069
|
+
connection.connect
|
|
1070
|
+
end
|
|
1071
|
+
end
|
|
813
1072
|
end
|
|
814
1073
|
end
|
|
815
1074
|
|
|
@@ -1179,6 +1438,7 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
|
1179
1438
|
host: 'this.host.does.not.exist.com'
|
|
1180
1439
|
)
|
|
1181
1440
|
)
|
|
1441
|
+
allow(client).to receive(:fallback_hosts).and_return([])
|
|
1182
1442
|
|
|
1183
1443
|
connection.transition_state_machine! :disconnected
|
|
1184
1444
|
end
|
|
@@ -1463,7 +1723,7 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
|
1463
1723
|
let(:client_options) { default_options.merge(tls: true) }
|
|
1464
1724
|
|
|
1465
1725
|
it 'uses TLS for the Internet check to https://internet-up.ably-realtime.com/is-the-internet-up.txt' do
|
|
1466
|
-
expect(EventMachine::HttpRequest).to receive(:new).with('https://internet-up.ably-realtime.com/is-the-internet-up.txt').and_return(http_request)
|
|
1726
|
+
expect(EventMachine::HttpRequest).to receive(:new).with('https://internet-up.ably-realtime.com/is-the-internet-up.txt', { tls: { verify_peer: true } }).and_return(http_request)
|
|
1467
1727
|
connection.internet_up?
|
|
1468
1728
|
stop_reactor
|
|
1469
1729
|
end
|
|
@@ -1473,7 +1733,7 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
|
1473
1733
|
let(:client_options) { default_options.merge(tls: false, use_token_auth: true) }
|
|
1474
1734
|
|
|
1475
1735
|
it 'uses TLS for the Internet check to http://internet-up.ably-realtime.com/is-the-internet-up.txt' do
|
|
1476
|
-
expect(EventMachine::HttpRequest).to receive(:new).with('http://internet-up.ably-realtime.com/is-the-internet-up.txt').and_return(http_request)
|
|
1736
|
+
expect(EventMachine::HttpRequest).to receive(:new).with('http://internet-up.ably-realtime.com/is-the-internet-up.txt', { tls: { verify_peer: true } }).and_return(http_request)
|
|
1477
1737
|
connection.internet_up?
|
|
1478
1738
|
stop_reactor
|
|
1479
1739
|
end
|
|
@@ -1487,7 +1747,7 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
|
1487
1747
|
let(:client_options) { default_options.merge(tls: true) }
|
|
1488
1748
|
|
|
1489
1749
|
it 'checks the Internet up URL over TLS' do
|
|
1490
|
-
expect(EventMachine::HttpRequest).to receive(:new).with("https:#{Ably::INTERNET_CHECK.fetch(:url)}").and_return(double('request', get: EventMachine::DefaultDeferrable.new))
|
|
1750
|
+
expect(EventMachine::HttpRequest).to receive(:new).with("https:#{Ably::INTERNET_CHECK.fetch(:url)}", { tls: { verify_peer: true } }).and_return(double('request', get: EventMachine::DefaultDeferrable.new))
|
|
1491
1751
|
connection.internet_up?
|
|
1492
1752
|
stop_reactor
|
|
1493
1753
|
end
|
|
@@ -1497,7 +1757,7 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
|
1497
1757
|
let(:client_options) { default_options.merge(tls: false, use_token_auth: true) }
|
|
1498
1758
|
|
|
1499
1759
|
it 'checks the Internet up URL over TLS' do
|
|
1500
|
-
expect(EventMachine::HttpRequest).to receive(:new).with("http:#{Ably::INTERNET_CHECK.fetch(:url)}").and_return(double('request', get: EventMachine::DefaultDeferrable.new))
|
|
1760
|
+
expect(EventMachine::HttpRequest).to receive(:new).with("http:#{Ably::INTERNET_CHECK.fetch(:url)}", { tls: { verify_peer: true } }).and_return(double('request', get: EventMachine::DefaultDeferrable.new))
|
|
1501
1761
|
connection.internet_up?
|
|
1502
1762
|
stop_reactor
|
|
1503
1763
|
end
|
|
@@ -1843,38 +2103,45 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
|
1843
2103
|
it 'sends the protocol version param v (#G4, #RTN2f)' do
|
|
1844
2104
|
expect(EventMachine).to receive(:connect) do |host, port, transport, object, url|
|
|
1845
2105
|
uri = URI.parse(url)
|
|
1846
|
-
expect(CGI::parse(uri.query)['v'][0]).to eql('1.
|
|
2106
|
+
expect(CGI::parse(uri.query)['v'][0]).to eql('1.2')
|
|
1847
2107
|
stop_reactor
|
|
1848
2108
|
end
|
|
1849
2109
|
client
|
|
1850
2110
|
end
|
|
1851
2111
|
|
|
1852
|
-
it 'sends the lib version param
|
|
2112
|
+
it 'sends the lib version param agent (#RCS7d)' do
|
|
1853
2113
|
expect(EventMachine).to receive(:connect) do |host, port, transport, object, url|
|
|
1854
2114
|
uri = URI.parse(url)
|
|
1855
|
-
expect(CGI::parse(uri.query)['
|
|
2115
|
+
expect(CGI::parse(uri.query)['agent'][0]).to match(/^ably-ruby\/\d\.\d\.\d ruby\/\d\.\d\.\d$/)
|
|
1856
2116
|
stop_reactor
|
|
1857
2117
|
end
|
|
1858
2118
|
client
|
|
1859
2119
|
end
|
|
2120
|
+
end
|
|
1860
2121
|
|
|
1861
|
-
|
|
1862
|
-
|
|
2122
|
+
context 'transport_params (#RTC1f)' do
|
|
2123
|
+
let(:client_options) { default_options.merge(transport_params: { 'extra_param' => 'extra_param' }) }
|
|
1863
2124
|
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
2125
|
+
it 'pases transport_params to query' do
|
|
2126
|
+
expect(EventMachine).to receive(:connect) do |host, port, transport, object, url|
|
|
2127
|
+
uri = URI.parse(url)
|
|
2128
|
+
expect(CGI::parse(uri.query)['extra_param'][0]).to eq('extra_param')
|
|
2129
|
+
stop_reactor
|
|
2130
|
+
end
|
|
1867
2131
|
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
end
|
|
2132
|
+
client
|
|
2133
|
+
end
|
|
1871
2134
|
|
|
1872
|
-
|
|
2135
|
+
context 'when changing default param' do
|
|
2136
|
+
let(:client_options) { default_options.merge(transport_params: { v: '1.0' }) }
|
|
2137
|
+
|
|
2138
|
+
it 'overrides default param (#RTC1f1)' do
|
|
1873
2139
|
expect(EventMachine).to receive(:connect) do |host, port, transport, object, url|
|
|
1874
2140
|
uri = URI.parse(url)
|
|
1875
|
-
expect(CGI::parse(uri.query)['
|
|
2141
|
+
expect(CGI::parse(uri.query)['v'][0]).to eq('1.0')
|
|
1876
2142
|
stop_reactor
|
|
1877
2143
|
end
|
|
2144
|
+
|
|
1878
2145
|
client
|
|
1879
2146
|
end
|
|
1880
2147
|
end
|
|
@@ -75,6 +75,83 @@ describe 'Ably::Realtime::Channel Message', :event_machine do
|
|
|
75
75
|
end
|
|
76
76
|
end
|
|
77
77
|
|
|
78
|
+
context 'a single Message object (#RSL1a)' do
|
|
79
|
+
let(:name) { random_str }
|
|
80
|
+
let(:data) { random_str }
|
|
81
|
+
let(:message) { Ably::Models::Message.new(name: name, data: data) }
|
|
82
|
+
|
|
83
|
+
it 'publishes the message' do
|
|
84
|
+
channel.attach
|
|
85
|
+
channel.publish(message)
|
|
86
|
+
channel.subscribe do |msg|
|
|
87
|
+
expect(msg.name).to eq(message.name)
|
|
88
|
+
expect(msg.data).to eq(message.data)
|
|
89
|
+
stop_reactor
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
context 'an array of Message objects (#RSL1a)' do
|
|
95
|
+
let(:data) { random_str }
|
|
96
|
+
let(:message1) { Ably::Models::Message.new(name: random_str, data: data) }
|
|
97
|
+
let(:message2) { Ably::Models::Message.new(name: random_str, data: data) }
|
|
98
|
+
let(:message3) { Ably::Models::Message.new(name: random_str, data: data) }
|
|
99
|
+
|
|
100
|
+
it 'publishes three messages' do
|
|
101
|
+
channel.attach
|
|
102
|
+
channel.publish([message1, message2, message3])
|
|
103
|
+
counter = 0
|
|
104
|
+
channel.subscribe do |message|
|
|
105
|
+
counter += 1
|
|
106
|
+
expect(message.data).to eq(data)
|
|
107
|
+
expect(message.name).to eq(message1.name) if counter == 1
|
|
108
|
+
expect(message.name).to eq(message2.name) if counter == 2
|
|
109
|
+
if counter == 3
|
|
110
|
+
expect(message.name).to eq(message3.name)
|
|
111
|
+
stop_reactor
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
context 'an array of hashes (#RSL1a)' do
|
|
118
|
+
let(:data) { random_str }
|
|
119
|
+
let(:message1) { { name: random_str, data: data } }
|
|
120
|
+
let(:message2) { { name: random_str, data: data } }
|
|
121
|
+
let(:message3) { { name: random_str, data: data } }
|
|
122
|
+
|
|
123
|
+
it 'publishes three messages' do
|
|
124
|
+
channel.attach
|
|
125
|
+
channel.publish([message1, message2, message3])
|
|
126
|
+
counter = 0
|
|
127
|
+
channel.subscribe do |message|
|
|
128
|
+
counter += 1
|
|
129
|
+
expect(message.data).to eq(data)
|
|
130
|
+
expect(message.name).to eq(message1[:name]) if counter == 1
|
|
131
|
+
expect(message.name).to eq(message2[:name]) if counter == 2
|
|
132
|
+
if counter == 3
|
|
133
|
+
expect(message.name).to eq(message3[:name])
|
|
134
|
+
stop_reactor
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
context 'a name with data payload (#RSL1a, #RSL1b)' do
|
|
141
|
+
let(:name) { random_str }
|
|
142
|
+
let(:data) { random_str }
|
|
143
|
+
|
|
144
|
+
it 'publishes a message' do
|
|
145
|
+
channel.attach
|
|
146
|
+
channel.publish(name, data)
|
|
147
|
+
channel.subscribe do |message|
|
|
148
|
+
expect(message.name).to eql(name)
|
|
149
|
+
expect(message.data).to eq(data)
|
|
150
|
+
stop_reactor
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
78
155
|
context 'with supported extra payload content type (#RTL6h, #RSL6a2)' do
|
|
79
156
|
let(:channel) { client.channel("pushenabled:#{random_str}") }
|
|
80
157
|
|
|
@@ -20,7 +20,7 @@ describe Ably::Realtime::Presence, 'history', :event_machine do
|
|
|
20
20
|
|
|
21
21
|
it 'provides up to the moment presence history' do
|
|
22
22
|
presence_client_one.enter(data) do
|
|
23
|
-
presence_client_one.leave
|
|
23
|
+
presence_client_one.subscribe(:leave) do
|
|
24
24
|
presence_client_one.history do |history_page|
|
|
25
25
|
expect(history_page).to be_a(Ably::Models::PaginatedResult)
|
|
26
26
|
expect(history_page.items.count).to eql(2)
|
|
@@ -36,6 +36,8 @@ describe Ably::Realtime::Presence, 'history', :event_machine do
|
|
|
36
36
|
stop_reactor
|
|
37
37
|
end
|
|
38
38
|
end
|
|
39
|
+
|
|
40
|
+
presence_client_one.leave(leave_data)
|
|
39
41
|
end
|
|
40
42
|
end
|
|
41
43
|
|
|
@@ -52,63 +54,5 @@ describe Ably::Realtime::Presence, 'history', :event_machine do
|
|
|
52
54
|
|
|
53
55
|
presence_client_one.enter(data)
|
|
54
56
|
end
|
|
55
|
-
|
|
56
|
-
context 'with option until_attach: true' do
|
|
57
|
-
let(:event) { random_str }
|
|
58
|
-
let(:presence_data_before_attach) { random_str }
|
|
59
|
-
let(:presence_data_after_attach) { random_str }
|
|
60
|
-
|
|
61
|
-
it 'retrieves all presence messages before channel was attached' do
|
|
62
|
-
presence_client_two.enter(presence_data_before_attach) do
|
|
63
|
-
presence_client_one.enter(presence_data_after_attach) do
|
|
64
|
-
presence_client_one.history(until_attach: true) do |presence_page|
|
|
65
|
-
expect(presence_page.items.count).to eql(1)
|
|
66
|
-
expect(presence_page.items.first.data).to eql(presence_data_before_attach)
|
|
67
|
-
stop_reactor
|
|
68
|
-
end
|
|
69
|
-
end
|
|
70
|
-
end
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
context 'and two pages of messages' do
|
|
74
|
-
let(:wildcard_token) { lambda { |token_params| Ably::Rest::Client.new(default_options).auth.request_token(client_id: '*') } }
|
|
75
|
-
let(:client_one) { auto_close Ably::Realtime::Client.new(default_options.merge(auth_callback: wildcard_token)) }
|
|
76
|
-
let(:client_two) { auto_close Ably::Realtime::Client.new(default_options.merge(auth_callback: wildcard_token)) }
|
|
77
|
-
|
|
78
|
-
# TODO: Remove retry logic when presence history regression fixed
|
|
79
|
-
# https://github.com/ably/realtime/issues/1707
|
|
80
|
-
#
|
|
81
|
-
it 'retrieves two pages of messages before channel was attached', retry: 10, :retry_wait => 5 do
|
|
82
|
-
when_all(*10.times.map { |i| presence_client_two.enter_client("client:#{i}", presence_data_before_attach) }) do
|
|
83
|
-
when_all(*10.times.map { |i| presence_client_one.enter_client("client:#{i}", presence_data_after_attach) }) do
|
|
84
|
-
presence_client_one.history(until_attach: true, limit: 5) do |presence_page|
|
|
85
|
-
expect(presence_page.items.count).to eql(5)
|
|
86
|
-
expect(presence_page.items.map(&:data).uniq.first).to eql(presence_data_before_attach)
|
|
87
|
-
|
|
88
|
-
presence_page.next do |presence_next_page|
|
|
89
|
-
expect(presence_next_page.items.count).to eql(5)
|
|
90
|
-
expect(presence_next_page.items.map(&:data).uniq.first).to eql(presence_data_before_attach)
|
|
91
|
-
if presence_next_page.has_next?
|
|
92
|
-
presence_next_page.next do |last|
|
|
93
|
-
expect(last.items.count).to eql(0)
|
|
94
|
-
end
|
|
95
|
-
else
|
|
96
|
-
expect(presence_next_page).to be_last
|
|
97
|
-
end
|
|
98
|
-
stop_reactor
|
|
99
|
-
end
|
|
100
|
-
end
|
|
101
|
-
end
|
|
102
|
-
end
|
|
103
|
-
end
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
it 'fails with an exception unless state is attached' do
|
|
107
|
-
presence_client_one.history(until_attach: true).errback do |error|
|
|
108
|
-
expect(error.message).to match(/not attached/)
|
|
109
|
-
stop_reactor
|
|
110
|
-
end
|
|
111
|
-
end
|
|
112
|
-
end
|
|
113
57
|
end
|
|
114
58
|
end
|