ably-rest 1.0.5 → 1.1.3
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 +5 -5
- data/.travis.yml +6 -3
- data/CHANGELOG.md +1 -1
- data/LICENSE +1 -1
- data/README.md +26 -7
- data/SPEC.md +2003 -1605
- data/ably-rest.gemspec +4 -2
- data/lib/submodules/ably-ruby/.editorconfig +14 -0
- data/lib/submodules/ably-ruby/.travis.yml +10 -8
- data/lib/submodules/ably-ruby/CHANGELOG.md +97 -1
- data/lib/submodules/ably-ruby/LICENSE +1 -3
- data/lib/submodules/ably-ruby/README.md +12 -7
- data/lib/submodules/ably-ruby/Rakefile +32 -0
- data/lib/submodules/ably-ruby/SPEC.md +1277 -835
- data/lib/submodules/ably-ruby/ably.gemspec +17 -11
- data/lib/submodules/ably-ruby/lib/ably/auth.rb +34 -8
- data/lib/submodules/ably-ruby/lib/ably/exceptions.rb +10 -4
- data/lib/submodules/ably-ruby/lib/ably/logger.rb +8 -2
- data/lib/submodules/ably-ruby/lib/ably/models/channel_state_change.rb +1 -1
- data/lib/submodules/ably-ruby/lib/ably/models/connection_state_change.rb +1 -1
- data/lib/submodules/ably-ruby/lib/ably/models/device_details.rb +87 -0
- data/lib/submodules/ably-ruby/lib/ably/models/device_push_details.rb +86 -0
- data/lib/submodules/ably-ruby/lib/ably/models/error_info.rb +23 -2
- data/lib/submodules/ably-ruby/lib/ably/models/idiomatic_ruby_wrapper.rb +12 -12
- data/lib/submodules/ably-ruby/lib/ably/models/message.rb +6 -4
- data/lib/submodules/ably-ruby/lib/ably/models/presence_message.rb +6 -4
- data/lib/submodules/ably-ruby/lib/ably/models/protocol_message.rb +32 -2
- data/lib/submodules/ably-ruby/lib/ably/models/push_channel_subscription.rb +89 -0
- data/lib/submodules/ably-ruby/lib/ably/modules/async_wrapper.rb +2 -2
- data/lib/submodules/ably-ruby/lib/ably/modules/conversions.rb +2 -2
- data/lib/submodules/ably-ruby/lib/ably/modules/encodeable.rb +2 -2
- data/lib/submodules/ably-ruby/lib/ably/modules/event_emitter.rb +2 -2
- data/lib/submodules/ably-ruby/lib/ably/modules/exception_codes.rb +128 -0
- data/lib/submodules/ably-ruby/lib/ably/modules/model_common.rb +15 -2
- data/lib/submodules/ably-ruby/lib/ably/modules/safe_deferrable.rb +1 -1
- data/lib/submodules/ably-ruby/lib/ably/modules/safe_yield.rb +1 -1
- data/lib/submodules/ably-ruby/lib/ably/modules/state_emitter.rb +5 -5
- data/lib/submodules/ably-ruby/lib/ably/modules/state_machine.rb +2 -2
- data/lib/submodules/ably-ruby/lib/ably/realtime.rb +1 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/auth.rb +2 -2
- data/lib/submodules/ably-ruby/lib/ably/realtime/channel.rb +27 -105
- data/lib/submodules/ably-ruby/lib/ably/realtime/channel/channel_manager.rb +4 -8
- data/lib/submodules/ably-ruby/lib/ably/realtime/channel/channel_state_machine.rb +2 -2
- data/lib/submodules/ably-ruby/lib/ably/realtime/channel/publisher.rb +74 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/channel/push_channel.rb +62 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/client.rb +91 -3
- data/lib/submodules/ably-ruby/lib/ably/realtime/client/incoming_message_dispatcher.rb +9 -4
- data/lib/submodules/ably-ruby/lib/ably/realtime/client/outgoing_message_dispatcher.rb +1 -1
- data/lib/submodules/ably-ruby/lib/ably/realtime/connection.rb +45 -26
- data/lib/submodules/ably-ruby/lib/ably/realtime/connection/connection_manager.rb +25 -9
- data/lib/submodules/ably-ruby/lib/ably/realtime/connection/websocket_transport.rb +2 -2
- data/lib/submodules/ably-ruby/lib/ably/realtime/presence.rb +7 -7
- data/lib/submodules/ably-ruby/lib/ably/realtime/presence/members_map.rb +9 -9
- data/lib/submodules/ably-ruby/lib/ably/realtime/push.rb +40 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/push/admin.rb +61 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/push/channel_subscriptions.rb +108 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/push/device_registrations.rb +105 -0
- data/lib/submodules/ably-ruby/lib/ably/rest.rb +1 -0
- data/lib/submodules/ably-ruby/lib/ably/rest/channel.rb +54 -18
- data/lib/submodules/ably-ruby/lib/ably/rest/channel/push_channel.rb +62 -0
- data/lib/submodules/ably-ruby/lib/ably/rest/client.rb +171 -41
- data/lib/submodules/ably-ruby/lib/ably/rest/middleware/parse_message_pack.rb +17 -1
- data/lib/submodules/ably-ruby/lib/ably/rest/presence.rb +1 -0
- data/lib/submodules/ably-ruby/lib/ably/rest/push.rb +42 -0
- data/lib/submodules/ably-ruby/lib/ably/rest/push/admin.rb +54 -0
- data/lib/submodules/ably-ruby/lib/ably/rest/push/channel_subscriptions.rb +121 -0
- data/lib/submodules/ably-ruby/lib/ably/rest/push/device_registrations.rb +103 -0
- data/lib/submodules/ably-ruby/lib/ably/version.rb +7 -2
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/auth_spec.rb +253 -49
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/channel_history_spec.rb +33 -21
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/channel_spec.rb +180 -62
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/client_spec.rb +155 -2
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_failures_spec.rb +293 -13
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_spec.rb +142 -39
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/message_spec.rb +38 -36
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/presence_history_spec.rb +12 -3
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/presence_spec.rb +207 -173
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/push_admin_spec.rb +736 -0
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/push_spec.rb +27 -0
- data/lib/submodules/ably-ruby/spec/acceptance/rest/auth_spec.rb +62 -51
- data/lib/submodules/ably-ruby/spec/acceptance/rest/base_spec.rb +2 -2
- data/lib/submodules/ably-ruby/spec/acceptance/rest/channel_spec.rb +79 -4
- data/lib/submodules/ably-ruby/spec/acceptance/rest/channels_spec.rb +6 -0
- data/lib/submodules/ably-ruby/spec/acceptance/rest/client_spec.rb +318 -74
- data/lib/submodules/ably-ruby/spec/acceptance/rest/message_spec.rb +158 -6
- data/lib/submodules/ably-ruby/spec/acceptance/rest/push_admin_spec.rb +952 -0
- data/lib/submodules/ably-ruby/spec/acceptance/rest/push_spec.rb +25 -0
- data/lib/submodules/ably-ruby/spec/acceptance/rest/time_spec.rb +1 -1
- data/lib/submodules/ably-ruby/spec/run_parallel_tests +33 -0
- data/lib/submodules/ably-ruby/spec/shared/client_initializer_behaviour.rb +1 -9
- data/lib/submodules/ably-ruby/spec/spec_helper.rb +3 -1
- data/lib/submodules/ably-ruby/spec/support/debug_failure_helper.rb +9 -5
- data/lib/submodules/ably-ruby/spec/support/event_emitter_helper.rb +31 -0
- data/lib/submodules/ably-ruby/spec/support/event_machine_helper.rb +1 -1
- data/lib/submodules/ably-ruby/spec/support/test_app.rb +2 -2
- data/lib/submodules/ably-ruby/spec/support/test_logger_helper.rb +42 -0
- data/lib/submodules/ably-ruby/spec/unit/logger_spec.rb +11 -12
- data/lib/submodules/ably-ruby/spec/unit/models/device_details_spec.rb +102 -0
- data/lib/submodules/ably-ruby/spec/unit/models/device_push_details_spec.rb +101 -0
- data/lib/submodules/ably-ruby/spec/unit/models/error_info_spec.rb +51 -3
- data/lib/submodules/ably-ruby/spec/unit/models/message_spec.rb +17 -2
- data/lib/submodules/ably-ruby/spec/unit/models/presence_message_spec.rb +1 -1
- data/lib/submodules/ably-ruby/spec/unit/models/push_channel_subscription_spec.rb +86 -0
- data/lib/submodules/ably-ruby/spec/unit/modules/async_wrapper_spec.rb +2 -2
- data/lib/submodules/ably-ruby/spec/unit/modules/enum_spec.rb +1 -1
- data/lib/submodules/ably-ruby/spec/unit/modules/event_emitter_spec.rb +3 -3
- data/lib/submodules/ably-ruby/spec/unit/modules/state_emitter_spec.rb +10 -10
- data/lib/submodules/ably-ruby/spec/unit/realtime/channel_spec.rb +1 -1
- data/lib/submodules/ably-ruby/spec/unit/realtime/client_spec.rb +13 -1
- data/lib/submodules/ably-ruby/spec/unit/realtime/connection_spec.rb +2 -2
- data/lib/submodules/ably-ruby/spec/unit/realtime/presence_spec.rb +1 -1
- data/lib/submodules/ably-ruby/spec/unit/realtime/push_channel_spec.rb +36 -0
- data/lib/submodules/ably-ruby/spec/unit/rest/channel_spec.rb +30 -1
- data/lib/submodules/ably-ruby/spec/unit/rest/client_spec.rb +30 -0
- data/lib/submodules/ably-ruby/spec/unit/rest/push_channel_spec.rb +36 -0
- data/lib/submodules/ably-ruby/spec/unit/util/pub_sub_spec.rb +3 -3
- data/spec/spec_helper.rb +1 -0
- metadata +51 -10
@@ -71,7 +71,7 @@ module Ably::Modules
|
|
71
71
|
|
72
72
|
def fallback_logger
|
73
73
|
@fallback_logger ||= ::Logger.new(STDOUT).tap do |logger|
|
74
|
-
logger.formatter =
|
74
|
+
logger.formatter = lambda do |severity, datetime, progname, msg|
|
75
75
|
[
|
76
76
|
"#{datetime.strftime("%Y-%m-%d %H:%M:%S.%L")} #{::Logger::SEV_LABEL[severity]} #{msg}",
|
77
77
|
"Warning: SafeDeferrable expects the method #logger to be defined in the class it is included in, the method was not found in #{self.class}"
|
@@ -29,7 +29,7 @@ module Ably::Modules
|
|
29
29
|
|
30
30
|
def fallback_logger
|
31
31
|
@fallback_logger ||= ::Logger.new(STDOUT).tap do |logger|
|
32
|
-
logger.formatter =
|
32
|
+
logger.formatter = lambda do |severity, datetime, progname, msg|
|
33
33
|
[
|
34
34
|
"#{datetime.strftime("%Y-%m-%d %H:%M:%S.%L")} #{::Logger::SEV_LABEL[severity]} #{msg}",
|
35
35
|
"Warning: SafeYield expects the method #logger to be defined in the class it is included in, the method was not found in #{self.class}"
|
@@ -81,13 +81,13 @@ module Ably::Modules
|
|
81
81
|
failure_block = options.fetch(:else, nil)
|
82
82
|
failure_wrapper = nil
|
83
83
|
|
84
|
-
success_wrapper =
|
84
|
+
success_wrapper = lambda do |*args|
|
85
85
|
yield
|
86
86
|
off(&success_wrapper)
|
87
87
|
off(&failure_wrapper) if failure_wrapper
|
88
88
|
end
|
89
89
|
|
90
|
-
failure_wrapper =
|
90
|
+
failure_wrapper = lambda do |*args|
|
91
91
|
failure_block.call(*args)
|
92
92
|
off(&success_wrapper)
|
93
93
|
off(&failure_wrapper)
|
@@ -119,7 +119,7 @@ module Ably::Modules
|
|
119
119
|
def once_state_changed(options = {}, &block)
|
120
120
|
raise ArgumentError, 'Block required' unless block_given?
|
121
121
|
|
122
|
-
once_block =
|
122
|
+
once_block = lambda do |*args|
|
123
123
|
off(*self.class::STATE.map, &once_block)
|
124
124
|
yield(*args)
|
125
125
|
end
|
@@ -142,7 +142,7 @@ module Ably::Modules
|
|
142
142
|
#
|
143
143
|
def deferrable_for_state_change_to(target_state)
|
144
144
|
Ably::Util::SafeDeferrable.new(logger).tap do |deferrable|
|
145
|
-
fail_proc =
|
145
|
+
fail_proc = lambda do |state_change|
|
146
146
|
deferrable.fail state_change.reason
|
147
147
|
end
|
148
148
|
once_or_if(target_state, else: fail_proc) do
|
@@ -153,7 +153,7 @@ module Ably::Modules
|
|
153
153
|
end
|
154
154
|
|
155
155
|
def self.included(klass)
|
156
|
-
klass.configure_event_emitter coerce_into:
|
156
|
+
klass.configure_event_emitter coerce_into: lambda { |event|
|
157
157
|
# Special case allows EVENT instead of STATE to be emitted
|
158
158
|
# Relies on the assumption that EVENT is a superset of STATE
|
159
159
|
if klass.const_defined?(:EVENT)
|
@@ -23,7 +23,7 @@ module Ably::Modules
|
|
23
23
|
def transition_state(state, *args)
|
24
24
|
unless result = transition_to(state.to_sym, *args)
|
25
25
|
exception = exception_for_state_change_to(state)
|
26
|
-
logger.fatal { "#{self.class}: #{exception.message}" }
|
26
|
+
logger.fatal { "#{self.class}: #{exception.message}\n#{caller[0..20].join("\n")}" }
|
27
27
|
end
|
28
28
|
result
|
29
29
|
end
|
@@ -41,7 +41,7 @@ module Ably::Modules
|
|
41
41
|
# @return [Ably::Exceptions::InvalidStateChange]
|
42
42
|
def exception_for_state_change_to(state)
|
43
43
|
error_message = "#{self.class}: Unable to transition from #{current_state} => #{state}"
|
44
|
-
Ably::Exceptions::InvalidStateChange.new(error_message, nil,
|
44
|
+
Ably::Exceptions::InvalidStateChange.new(error_message, nil, Ably::Exceptions::Codes::CHANNEL_OPERATION_FAILED_INVALID_CHANNEL_STATE)
|
45
45
|
end
|
46
46
|
|
47
47
|
module ClassMethods
|
@@ -233,13 +233,13 @@ module Ably
|
|
233
233
|
# @yield [Hash] Auth params for a new Realtime connection
|
234
234
|
#
|
235
235
|
def auth_params(&success_callback)
|
236
|
-
fail_callback =
|
236
|
+
fail_callback = lambda do |error, deferrable|
|
237
237
|
logger.error { "Failed to authenticate: #{error}" }
|
238
238
|
if error.kind_of?(Ably::Exceptions::BaseAblyException)
|
239
239
|
# Use base exception if it exists carrying forward the status codes
|
240
240
|
deferrable.fail Ably::Exceptions::AuthenticationFailed.new(error.message, nil, nil, error)
|
241
241
|
else
|
242
|
-
deferrable.fail Ably::Exceptions::AuthenticationFailed.new(error.message, 500,
|
242
|
+
deferrable.fail Ably::Exceptions::AuthenticationFailed.new(error.message, 500, Ably::Exceptions::Codes::CLIENT_CONFIGURED_AUTHENTICATION_PROVIDER_REQUEST_FAILED)
|
243
243
|
end
|
244
244
|
end
|
245
245
|
async_wrap(success_callback, fail_callback) do
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'ably/realtime/channel/publisher'
|
2
|
+
|
1
3
|
module Ably
|
2
4
|
module Realtime
|
3
5
|
# The Channel class represents a Channel belonging to this application.
|
@@ -32,6 +34,7 @@ module Ably
|
|
32
34
|
include Ably::Modules::EventMachineHelpers
|
33
35
|
include Ably::Modules::AsyncWrapper
|
34
36
|
include Ably::Modules::MessageEmitter
|
37
|
+
include Ably::Realtime::Channel::Publisher
|
35
38
|
extend Ably::Modules::Enum
|
36
39
|
|
37
40
|
# ChannelState
|
@@ -61,12 +64,17 @@ module Ably
|
|
61
64
|
|
62
65
|
# {Ably::Realtime::Client} associated with this channel
|
63
66
|
# @return [Ably::Realtime::Client]
|
67
|
+
# @api private
|
64
68
|
attr_reader :client
|
65
69
|
|
66
70
|
# Channel name
|
67
71
|
# @return [String]
|
68
72
|
attr_reader :name
|
69
73
|
|
74
|
+
# Push channel used for push notification
|
75
|
+
# @return [Ably::Realtime::Channel::PushChannel]
|
76
|
+
attr_reader :push
|
77
|
+
|
70
78
|
# Channel options configured for this channel, see {#initialize} for channel_options
|
71
79
|
# @return [Hash]
|
72
80
|
attr_reader :options
|
@@ -93,7 +101,7 @@ module Ably
|
|
93
101
|
# @option channel_options [Hash,Ably::Models::CipherParams] :cipher A hash of options or a {Ably::Models::CipherParams} to configure the encryption. *:key* is required, all other options are optional. See {Ably::Util::Crypto#initialize} for a list of +:cipher+ options
|
94
102
|
#
|
95
103
|
def initialize(client, name, channel_options = {})
|
96
|
-
ensure_utf_8
|
104
|
+
name = ensure_utf_8(:name, name)
|
97
105
|
|
98
106
|
update_options channel_options
|
99
107
|
@client = client
|
@@ -103,6 +111,7 @@ module Ably
|
|
103
111
|
@state_machine = ChannelStateMachine.new(self)
|
104
112
|
@state = STATE(state_machine.current_state)
|
105
113
|
@manager = ChannelManager.new(self, client.connection)
|
114
|
+
@push = PushChannel.new(self)
|
106
115
|
|
107
116
|
setup_event_handlers
|
108
117
|
setup_presence
|
@@ -116,7 +125,7 @@ module Ably
|
|
116
125
|
# @param data [String, ByteArray, nil] The message payload unless an Array of [Ably::Model::Message] objects passed in the first argument
|
117
126
|
# @param attributes [Hash, nil] Optional additional message attributes such as :client_id or :connection_id, applied when name attribute is nil or a string
|
118
127
|
#
|
119
|
-
# @yield [Ably::Models::Message,Array<Ably::Models::Message>] On success, will call the block with the {Ably::Models::Message} if a single message is
|
128
|
+
# @yield [Ably::Models::Message,Array<Ably::Models::Message>] On success, will call the block with the {Ably::Models::Message} if a single message is published, or an Array of {Ably::Models::Message} when multiple messages are published
|
120
129
|
# @return [Ably::Util::SafeDeferrable] Deferrable that supports both success (callback) and failure (errback) callbacks
|
121
130
|
#
|
122
131
|
# @example
|
@@ -146,25 +155,30 @@ module Ably
|
|
146
155
|
# end
|
147
156
|
#
|
148
157
|
def publish(name, data = nil, attributes = {}, &success_block)
|
149
|
-
if
|
158
|
+
if suspended? || failed?
|
150
159
|
error = Ably::Exceptions::ChannelInactive.new("Cannot publish messages on a channel in state #{state}")
|
151
160
|
return Ably::Util::SafeDeferrable.new_and_fail_immediately(logger, error)
|
152
161
|
end
|
153
162
|
|
154
163
|
if !connection.can_publish_messages?
|
155
|
-
error = Ably::Exceptions::MessageQueueingDisabled.new("Message cannot be published. Client is
|
164
|
+
error = Ably::Exceptions::MessageQueueingDisabled.new("Message cannot be published. Client is not allowed to queue messages when connection is in state #{connection.state}")
|
156
165
|
return Ably::Util::SafeDeferrable.new_and_fail_immediately(logger, error)
|
157
166
|
end
|
158
167
|
|
159
168
|
messages = if name.kind_of?(Enumerable)
|
160
169
|
name
|
161
170
|
else
|
162
|
-
ensure_utf_8
|
171
|
+
name = ensure_utf_8(:name, name, allow_nil: true)
|
163
172
|
ensure_supported_payload data
|
164
173
|
[{ name: name, data: data }.merge(attributes)]
|
165
174
|
end
|
166
175
|
|
167
|
-
|
176
|
+
if messages.length > Realtime::Connection::MAX_PROTOCOL_MESSAGE_BATCH_SIZE
|
177
|
+
error = Ably::Exceptions::InvalidRequest.new("It is not possible to publish more than #{Realtime::Connection::MAX_PROTOCOL_MESSAGE_BATCH_SIZE} messages with a single publish request.")
|
178
|
+
return Ably::Util::SafeDeferrable.new_and_fail_immediately(logger, error)
|
179
|
+
end
|
180
|
+
|
181
|
+
enqueue_messages_on_connection(client, messages, channel_name, options).tap do |deferrable|
|
168
182
|
deferrable.callback(&success_block) if block_given?
|
169
183
|
end
|
170
184
|
end
|
@@ -291,7 +305,7 @@ module Ably
|
|
291
305
|
# @api private
|
292
306
|
def __incoming_msgbus__
|
293
307
|
@__incoming_msgbus__ ||= Ably::Util::PubSub.new(
|
294
|
-
coerce_into:
|
308
|
+
coerce_into: lambda { |event| Ably::Models::ProtocolMessage::ACTION(event) }
|
295
309
|
)
|
296
310
|
end
|
297
311
|
|
@@ -321,12 +335,6 @@ module Ably
|
|
321
335
|
client.logger
|
322
336
|
end
|
323
337
|
|
324
|
-
# Internal queue used for messages published that cannot yet be enqueued on the connection
|
325
|
-
# @api private
|
326
|
-
def __queue__
|
327
|
-
@queue
|
328
|
-
end
|
329
|
-
|
330
338
|
# As we are using a state machine, do not allow change_state to be used
|
331
339
|
# #transition_state_machine must be used instead
|
332
340
|
private :change_state
|
@@ -339,98 +347,6 @@ module Ably
|
|
339
347
|
end
|
340
348
|
emit_message message.name, message
|
341
349
|
end
|
342
|
-
|
343
|
-
unsafe_on(STATE.Attached) do
|
344
|
-
process_queue
|
345
|
-
end
|
346
|
-
end
|
347
|
-
|
348
|
-
# Queue messages and process queue if channel is attached.
|
349
|
-
# If channel is not yet attached, attempt to attach it before the message queue is processed.
|
350
|
-
# @return [Ably::Util::SafeDeferrable]
|
351
|
-
def queue_messages(raw_messages)
|
352
|
-
messages = Array(raw_messages).map do |raw_msg|
|
353
|
-
create_message(raw_msg).tap do |message|
|
354
|
-
next if message.client_id.nil?
|
355
|
-
if message.client_id == '*'
|
356
|
-
raise Ably::Exceptions::IncompatibleClientId.new('Wildcard client_id is reserved and cannot be used when publishing messages')
|
357
|
-
end
|
358
|
-
if message.client_id && !message.client_id.kind_of?(String)
|
359
|
-
raise Ably::Exceptions::IncompatibleClientId.new('client_id must be a String when publishing messages')
|
360
|
-
end
|
361
|
-
unless client.auth.can_assume_client_id?(message.client_id)
|
362
|
-
raise Ably::Exceptions::IncompatibleClientId.new("Cannot publish with client_id '#{message.client_id}' as it is incompatible with the current configured client_id '#{client.client_id}'")
|
363
|
-
end
|
364
|
-
end
|
365
|
-
end
|
366
|
-
|
367
|
-
__queue__.push(*messages)
|
368
|
-
|
369
|
-
if attached?
|
370
|
-
process_queue
|
371
|
-
else
|
372
|
-
attach
|
373
|
-
end
|
374
|
-
|
375
|
-
if messages.count == 1
|
376
|
-
# A message is a Deferrable so, if publishing only one message, simply return that Deferrable
|
377
|
-
messages.first
|
378
|
-
else
|
379
|
-
deferrable_for_multiple_messages(messages)
|
380
|
-
end
|
381
|
-
end
|
382
|
-
|
383
|
-
# A deferrable object that calls the success callback once all messages are delivered
|
384
|
-
# If any message fails, the errback is called immediately
|
385
|
-
# Only one callback or errback is ever called i.e. if a group of messages all fail, only once
|
386
|
-
# errback will be invoked
|
387
|
-
def deferrable_for_multiple_messages(messages)
|
388
|
-
expected_deliveries = messages.count
|
389
|
-
actual_deliveries = 0
|
390
|
-
failed = false
|
391
|
-
|
392
|
-
Ably::Util::SafeDeferrable.new(logger).tap do |deferrable|
|
393
|
-
messages.each do |message|
|
394
|
-
message.callback do
|
395
|
-
next if failed
|
396
|
-
actual_deliveries += 1
|
397
|
-
deferrable.succeed messages if actual_deliveries == expected_deliveries
|
398
|
-
end
|
399
|
-
message.errback do |error|
|
400
|
-
next if failed
|
401
|
-
failed = true
|
402
|
-
deferrable.fail error, message
|
403
|
-
end
|
404
|
-
end
|
405
|
-
end
|
406
|
-
end
|
407
|
-
|
408
|
-
def messages_in_queue?
|
409
|
-
!__queue__.empty?
|
410
|
-
end
|
411
|
-
|
412
|
-
# Move messages from Channel Queue into Outgoing Connection Queue
|
413
|
-
def process_queue
|
414
|
-
condition = -> { attached? && messages_in_queue? }
|
415
|
-
non_blocking_loop_while(condition) do
|
416
|
-
send_messages_within_protocol_message __queue__.shift(MAX_PROTOCOL_MESSAGE_BATCH_SIZE)
|
417
|
-
end
|
418
|
-
end
|
419
|
-
|
420
|
-
def send_messages_within_protocol_message(messages)
|
421
|
-
connection.send_protocol_message(
|
422
|
-
action: Ably::Models::ProtocolMessage::ACTION.Message.to_i,
|
423
|
-
channel: name,
|
424
|
-
messages: messages
|
425
|
-
)
|
426
|
-
end
|
427
|
-
|
428
|
-
def create_message(message)
|
429
|
-
Ably::Models::Message(message.dup).tap do |msg|
|
430
|
-
msg.encode(client.encoders, options) do |encode_error, error_message|
|
431
|
-
client.logger.error error_message
|
432
|
-
end
|
433
|
-
end
|
434
350
|
end
|
435
351
|
|
436
352
|
def rest_channel
|
@@ -444,9 +360,15 @@ module Ably
|
|
444
360
|
def setup_presence
|
445
361
|
@presence ||= Presence.new(self)
|
446
362
|
end
|
363
|
+
|
364
|
+
# Alias useful for methods with a name argument
|
365
|
+
def channel_name
|
366
|
+
name
|
367
|
+
end
|
447
368
|
end
|
448
369
|
end
|
449
370
|
end
|
450
371
|
|
451
372
|
require 'ably/realtime/channel/channel_manager'
|
452
373
|
require 'ably/realtime/channel/channel_state_machine'
|
374
|
+
require 'ably/realtime/channel/push_channel'
|
@@ -98,7 +98,7 @@ module Ably::Realtime
|
|
98
98
|
def fail_messages_awaiting_ack(error, options = {})
|
99
99
|
immediately = options[:immediately] || false
|
100
100
|
|
101
|
-
fail_proc =
|
101
|
+
fail_proc = lambda do
|
102
102
|
error = Ably::Exceptions::MessageDeliveryFailed.new("Continuity of connection was lost so published messages awaiting ACK have failed") unless error
|
103
103
|
fail_messages_in_queue connection.__pending_message_ack_queue__, error
|
104
104
|
end
|
@@ -111,16 +111,12 @@ module Ably::Realtime
|
|
111
111
|
end
|
112
112
|
end
|
113
113
|
|
114
|
-
# When a channel becomes
|
114
|
+
# When a channel becomes suspended or failed,
|
115
115
|
# all queued messages should be failed immediately as we don't queue in
|
116
116
|
# any of those states
|
117
117
|
def fail_queued_messages(error)
|
118
118
|
error = Ably::Exceptions::MessageDeliveryFailed.new("Queued messages on channel '#{channel.name}' in state '#{channel.state}' will never be delivered") unless error
|
119
119
|
fail_messages_in_queue connection.__outgoing_message_queue__, error
|
120
|
-
channel.__queue__.each do |message|
|
121
|
-
nack_message message, error
|
122
|
-
end
|
123
|
-
channel.__queue__.clear
|
124
120
|
end
|
125
121
|
|
126
122
|
def fail_messages_in_queue(queue, error)
|
@@ -214,7 +210,7 @@ module Ably::Realtime
|
|
214
210
|
state_at_time_of_request = channel.state
|
215
211
|
@pending_state_change_timer = EventMachine::Timer.new(realtime_request_timeout) do
|
216
212
|
if channel.state == state_at_time_of_request
|
217
|
-
error = Ably::Models::ErrorInfo.new(code:
|
213
|
+
error = Ably::Models::ErrorInfo.new(code: Ably::Exceptions::Codes::CHANNEL_OPERATION_FAILED_NO_RESPONSE_FROM_SERVER, message: "Channel #{new_state} operation failed (timed out)")
|
218
214
|
channel.transition_state_machine state_if_failed, reason: error
|
219
215
|
end
|
220
216
|
end
|
@@ -224,7 +220,7 @@ module Ably::Realtime
|
|
224
220
|
@pending_state_change_timer = nil
|
225
221
|
end
|
226
222
|
|
227
|
-
resend_if_disconnected_and_connected =
|
223
|
+
resend_if_disconnected_and_connected = lambda do
|
228
224
|
connection.unsafe_once(:disconnected) do
|
229
225
|
next unless pending_state_change_timer
|
230
226
|
connection.unsafe_once(:connected) do
|
@@ -25,7 +25,7 @@ module Ably::Realtime
|
|
25
25
|
transition :from => :attached, :to => [:attaching, :detaching, :detached, :failed, :suspended]
|
26
26
|
transition :from => :detaching, :to => [:detached, :attaching, :attached, :failed, :suspended]
|
27
27
|
transition :from => :detached, :to => [:attaching, :attached, :failed]
|
28
|
-
transition :from => :suspended, :to => [:attaching, :detached, :failed]
|
28
|
+
transition :from => :suspended, :to => [:attaching, :attached, :detached, :failed]
|
29
29
|
transition :from => :failed, :to => [:attaching]
|
30
30
|
|
31
31
|
after_transition do |channel, transition|
|
@@ -47,7 +47,7 @@ module Ably::Realtime
|
|
47
47
|
|
48
48
|
after_transition(to: [:detached, :failed, :suspended]) do |channel, current_transition|
|
49
49
|
err = error_from_state_change(current_transition)
|
50
|
-
channel.manager.fail_queued_messages
|
50
|
+
channel.manager.fail_queued_messages(err) if channel.failed? or channel.suspended? #RTL11
|
51
51
|
channel.manager.log_channel_error err if err
|
52
52
|
end
|
53
53
|
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module Ably::Realtime
|
2
|
+
class Channel
|
3
|
+
# Publisher module adds publishing capabilities to the current object
|
4
|
+
module Publisher
|
5
|
+
private
|
6
|
+
|
7
|
+
# Prepare and queue messages on the connection queue immediately
|
8
|
+
# @return [Ably::Util::SafeDeferrable]
|
9
|
+
def enqueue_messages_on_connection(client, raw_messages, channel_name, channel_options = {})
|
10
|
+
messages = Array(raw_messages).map do |raw_msg|
|
11
|
+
create_message(client, raw_msg, channel_options).tap do |message|
|
12
|
+
next if message.client_id.nil?
|
13
|
+
if message.client_id == '*'
|
14
|
+
raise Ably::Exceptions::IncompatibleClientId.new('Wildcard client_id is reserved and cannot be used when publishing messages')
|
15
|
+
end
|
16
|
+
if message.client_id && !message.client_id.kind_of?(String)
|
17
|
+
raise Ably::Exceptions::IncompatibleClientId.new('client_id must be a String when publishing messages')
|
18
|
+
end
|
19
|
+
unless client.auth.can_assume_client_id?(message.client_id)
|
20
|
+
raise Ably::Exceptions::IncompatibleClientId.new("Cannot publish with client_id '#{message.client_id}' as it is incompatible with the current configured client_id '#{client.client_id}'")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
connection.send_protocol_message(
|
26
|
+
action: Ably::Models::ProtocolMessage::ACTION.Message.to_i,
|
27
|
+
channel: channel_name,
|
28
|
+
messages: messages
|
29
|
+
)
|
30
|
+
|
31
|
+
if messages.count == 1
|
32
|
+
# A message is a Deferrable so, if publishing only one message, simply return that Deferrable
|
33
|
+
messages.first
|
34
|
+
else
|
35
|
+
deferrable_for_multiple_messages(messages)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# A deferrable object that calls the success callback once all messages are delivered
|
40
|
+
# If any message fails, the errback is called immediately
|
41
|
+
# Only one callback or errback is ever called i.e. if a group of messages all fail, only once
|
42
|
+
# errback will be invoked
|
43
|
+
def deferrable_for_multiple_messages(messages)
|
44
|
+
expected_deliveries = messages.count
|
45
|
+
actual_deliveries = 0
|
46
|
+
failed = false
|
47
|
+
|
48
|
+
Ably::Util::SafeDeferrable.new(logger).tap do |deferrable|
|
49
|
+
messages.each do |message|
|
50
|
+
message.callback do
|
51
|
+
next if failed
|
52
|
+
actual_deliveries += 1
|
53
|
+
deferrable.succeed messages if actual_deliveries == expected_deliveries
|
54
|
+
end
|
55
|
+
message.errback do |error|
|
56
|
+
next if failed
|
57
|
+
failed = true
|
58
|
+
deferrable.fail error, message
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def create_message(client, message, channel_options)
|
65
|
+
Ably::Models::Message(message.dup).tap do |msg|
|
66
|
+
msg.encode(client.encoders, channel_options) do |encode_error, error_message|
|
67
|
+
client.logger.error error_message
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|