ably-rest 0.8.3 → 0.8.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -0
- data/lib/submodules/ably-ruby/CHANGELOG.md +10 -0
- data/lib/submodules/ably-ruby/README.md +1 -1
- data/lib/submodules/ably-ruby/Rakefile +1 -1
- data/lib/submodules/ably-ruby/lib/ably/auth.rb +24 -20
- data/lib/submodules/ably-ruby/lib/ably/exceptions.rb +3 -0
- data/lib/submodules/ably-ruby/lib/ably/models/channel_state_change.rb +41 -0
- data/lib/submodules/ably-ruby/lib/ably/models/connection_state_change.rb +43 -0
- data/lib/submodules/ably-ruby/lib/ably/models/message.rb +1 -1
- data/lib/submodules/ably-ruby/lib/ably/models/presence_message.rb +1 -1
- data/lib/submodules/ably-ruby/lib/ably/models/protocol_message.rb +2 -1
- data/lib/submodules/ably-ruby/lib/ably/models/token_details.rb +8 -6
- data/lib/submodules/ably-ruby/lib/ably/modules/conversions.rb +4 -0
- data/lib/submodules/ably-ruby/lib/ably/modules/state_emitter.rb +4 -1
- data/lib/submodules/ably-ruby/lib/ably/modules/uses_state_machine.rb +35 -4
- data/lib/submodules/ably-ruby/lib/ably/realtime/auth.rb +13 -13
- data/lib/submodules/ably-ruby/lib/ably/realtime/channel.rb +13 -5
- data/lib/submodules/ably-ruby/lib/ably/realtime/channel/channel_manager.rb +27 -7
- data/lib/submodules/ably-ruby/lib/ably/realtime/channel/channel_state_machine.rb +22 -12
- data/lib/submodules/ably-ruby/lib/ably/realtime/client/incoming_message_dispatcher.rb +16 -10
- data/lib/submodules/ably-ruby/lib/ably/realtime/client/outgoing_message_dispatcher.rb +6 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/connection.rb +5 -4
- data/lib/submodules/ably-ruby/lib/ably/realtime/connection/connection_manager.rb +42 -24
- data/lib/submodules/ably-ruby/lib/ably/realtime/connection/connection_state_machine.rb +25 -17
- data/lib/submodules/ably-ruby/lib/ably/realtime/presence.rb +4 -4
- data/lib/submodules/ably-ruby/lib/ably/rest/channel.rb +3 -2
- data/lib/submodules/ably-ruby/lib/ably/rest/client.rb +2 -2
- data/lib/submodules/ably-ruby/lib/ably/util/crypto.rb +15 -0
- data/lib/submodules/ably-ruby/lib/ably/version.rb +1 -1
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/auth_spec.rb +9 -9
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/channel_history_spec.rb +2 -2
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/channel_spec.rb +168 -21
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/channels_spec.rb +6 -2
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/client_spec.rb +6 -5
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_failures_spec.rb +29 -19
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_spec.rb +150 -35
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/message_spec.rb +146 -23
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/presence_history_spec.rb +2 -2
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/presence_spec.rb +44 -24
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/stats_spec.rb +1 -1
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/time_spec.rb +1 -1
- data/lib/submodules/ably-ruby/spec/acceptance/rest/auth_spec.rb +77 -46
- data/lib/submodules/ably-ruby/spec/acceptance/rest/channel_spec.rb +31 -3
- data/lib/submodules/ably-ruby/spec/acceptance/rest/client_spec.rb +15 -5
- data/lib/submodules/ably-ruby/spec/acceptance/rest/presence_spec.rb +9 -7
- data/lib/submodules/ably-ruby/spec/support/event_machine_helper.rb +30 -4
- data/lib/submodules/ably-ruby/spec/support/protocol_helper.rb +9 -6
- data/lib/submodules/ably-ruby/spec/unit/auth_spec.rb +1 -1
- data/lib/submodules/ably-ruby/spec/unit/models/channel_state_change_spec.rb +44 -0
- data/lib/submodules/ably-ruby/spec/unit/models/connection_state_change_spec.rb +54 -0
- data/lib/submodules/ably-ruby/spec/unit/models/token_details_spec.rb +8 -0
- data/lib/submodules/ably-ruby/spec/unit/modules/async_wrapper_spec.rb +1 -1
- data/lib/submodules/ably-ruby/spec/unit/util/crypto_spec.rb +18 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1b1045e268247db9dd96742a0c11404b03fbb533
|
4
|
+
data.tar.gz: 180a9c3dfee6b05b4fc8c8f947e1081bba97b635
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 163805382715a09c67f446297b49c5c4588ff2c141c3cc6173eb9917423305b3f532d076f46af854d6b869439e9e465a02eb23735e40be64fe8d017773d782a0
|
7
|
+
data.tar.gz: b024865d3a6f266681e0ed4224b6a14c1e4248e21f93958d357d3009010a662d02d779615a21d0c4616e6397fc6c1053c0afc887ef7c52dcde9c286e24960d3d
|
data/.travis.yml
CHANGED
@@ -6,6 +6,12 @@
|
|
6
6
|
|
7
7
|
**Implemented enhancements:**
|
8
8
|
|
9
|
+
- Add compatibility support for default Crypto params [\#53](https://github.com/ably/ably-ruby/issues/53)
|
10
|
+
|
11
|
+
- EventEmitter on connection [\#52](https://github.com/ably/ably-ruby/issues/52)
|
12
|
+
|
13
|
+
- Add test for connectionId attribute for a message sent over REST [\#50](https://github.com/ably/ably-ruby/issues/50)
|
14
|
+
|
9
15
|
- Implement :queue\_messages option [\#36](https://github.com/ably/ably-ruby/issues/36)
|
10
16
|
|
11
17
|
- Check that a non 200-299 status code for REST requests uses fallback hosts [\#35](https://github.com/ably/ably-ruby/issues/35)
|
@@ -32,6 +38,10 @@
|
|
32
38
|
|
33
39
|
**Merged pull requests:**
|
34
40
|
|
41
|
+
- Spec update to fix a number of issues [\#60](https://github.com/ably/ably-ruby/pull/60) ([mattheworiordan](https://github.com/mattheworiordan))
|
42
|
+
|
43
|
+
- Allow clientId to be provided on init if using externally created token [\#58](https://github.com/ably/ably-ruby/pull/58) ([SimonWoolf](https://github.com/SimonWoolf))
|
44
|
+
|
35
45
|
- Separate token params for auth [\#57](https://github.com/ably/ably-ruby/pull/57) ([mattheworiordan](https://github.com/mattheworiordan))
|
36
46
|
|
37
47
|
- Ensure files are required in a consistent order [\#51](https://github.com/ably/ably-ruby/pull/51) ([SimonWoolf](https://github.com/SimonWoolf))
|
@@ -187,7 +187,7 @@ token_details = client.auth.request_token
|
|
187
187
|
token_details.token # => "xVLyHw.CLchevH3hF....MDh9ZC_Q"
|
188
188
|
client = Ably::Rest.new(token: token_details.token)
|
189
189
|
|
190
|
-
token = client.auth.create_token_request(
|
190
|
+
token = client.auth.create_token_request(ttl: 3600)
|
191
191
|
# => {"id"=>...,
|
192
192
|
# "clientId"=>nil,
|
193
193
|
# "ttl"=>3600,
|
@@ -16,7 +16,7 @@ begin
|
|
16
16
|
namespace :doc do
|
17
17
|
desc 'Generate Markdown Specification from the RSpec public API tests'
|
18
18
|
task :spec do
|
19
|
-
ENV['
|
19
|
+
ENV['PROTOCOL'] = 'json'
|
20
20
|
|
21
21
|
rspec_task.rspec_opts = %w(
|
22
22
|
--require ./spec/support/markdown_spec_formatter
|
@@ -43,11 +43,11 @@ module Ably
|
|
43
43
|
# Creates an Auth object
|
44
44
|
#
|
45
45
|
# @param [Ably::Rest::Client] client {Ably::Rest::Client} this Auth object uses
|
46
|
-
# @param [Hash] auth_options the authentication options used as a default future token requests
|
47
46
|
# @param [Hash] token_params the token params used as a default for future token requests
|
47
|
+
# @param [Hash] auth_options the authentication options used as a default future token requests
|
48
48
|
# @option (see #request_token)
|
49
49
|
#
|
50
|
-
def initialize(client,
|
50
|
+
def initialize(client, token_params, auth_options)
|
51
51
|
unless auth_options.kind_of?(Hash)
|
52
52
|
raise ArgumentError, 'Expected auth_options to be a Hash'
|
53
53
|
end
|
@@ -74,7 +74,7 @@ module Ably
|
|
74
74
|
raise ArgumentError, 'key is missing. Either an API key, token, or token auth method must be provided'
|
75
75
|
end
|
76
76
|
|
77
|
-
if has_client_id?
|
77
|
+
if has_client_id? && !token_creatable_externally?
|
78
78
|
raise ArgumentError, 'client_id cannot be provided without a complete API key. Key name & Secret is needed to authenticate with Ably and obtain a token' unless api_key_present?
|
79
79
|
ensure_utf_8 :client_id, client_id
|
80
80
|
end
|
@@ -87,8 +87,8 @@ module Ably
|
|
87
87
|
#
|
88
88
|
# In the event that a new token request is made, the provided options are used.
|
89
89
|
#
|
90
|
-
# @param [Hash] auth_options the authentication options used for future token requests
|
91
90
|
# @param [Hash] token_params the token params used for future token requests
|
91
|
+
# @param [Hash] auth_options the authentication options used for future token requests
|
92
92
|
# @option auth_options [Boolean] :force obtains a new token even if the current token is valid
|
93
93
|
# @option (see #request_token)
|
94
94
|
#
|
@@ -100,12 +100,12 @@ module Ably
|
|
100
100
|
# token_details = client.auth.authorise
|
101
101
|
#
|
102
102
|
# # will use token request from block to authorise if not already authorised
|
103
|
-
# token_details = client.auth.authorise auth_callback: Proc.new do
|
103
|
+
# token_details = client.auth.authorise {}, auth_callback: Proc.new do
|
104
104
|
# # create token_request object
|
105
105
|
# token_request
|
106
106
|
# end
|
107
107
|
#
|
108
|
-
def authorise(
|
108
|
+
def authorise(token_params = {}, auth_options = {})
|
109
109
|
ensure_valid_auth_attributes auth_options
|
110
110
|
|
111
111
|
auth_options = auth_options.clone
|
@@ -120,7 +120,7 @@ module Ably
|
|
120
120
|
token_params = (auth_options.delete(:token_params) || {}).merge(token_params)
|
121
121
|
@token_params = @token_params.merge(token_params) # update defaults
|
122
122
|
|
123
|
-
@current_token_details = request_token(
|
123
|
+
@current_token_details = request_token(token_params, auth_options)
|
124
124
|
end
|
125
125
|
|
126
126
|
# Request a {Ably::Models::TokenDetails} which can be used to make authenticated token based requests
|
@@ -143,15 +143,15 @@ module Ably
|
|
143
143
|
# token_details = client.auth.request_token
|
144
144
|
#
|
145
145
|
# # token request with token params
|
146
|
-
# client.auth.request_token
|
146
|
+
# client.auth.request_token ttl: 1.hour
|
147
147
|
#
|
148
148
|
# # token request using auth block
|
149
|
-
# token_details = client.auth.request_token auth_callback: Proc.new do
|
149
|
+
# token_details = client.auth.request_token {}, auth_callback: Proc.new do
|
150
150
|
# # create token_request object
|
151
151
|
# token_request
|
152
152
|
# end
|
153
153
|
#
|
154
|
-
def request_token(
|
154
|
+
def request_token(token_params = {}, auth_options = {})
|
155
155
|
ensure_valid_auth_attributes auth_options
|
156
156
|
|
157
157
|
token_params = (auth_options[:token_params] || {}).merge(token_params)
|
@@ -163,7 +163,7 @@ module Ably
|
|
163
163
|
elsif auth_url = auth_options.delete(:auth_url)
|
164
164
|
token_request_from_auth_url(auth_url, auth_options)
|
165
165
|
else
|
166
|
-
create_token_request(
|
166
|
+
create_token_request(token_params, auth_options)
|
167
167
|
end
|
168
168
|
|
169
169
|
case token_request
|
@@ -186,12 +186,6 @@ module Ably
|
|
186
186
|
|
187
187
|
# Creates and signs a token request that can then subsequently be used by any client to request a token
|
188
188
|
#
|
189
|
-
# @param [Hash] auth_options the authentication options for the token request
|
190
|
-
# @option auth_options [String] :key API key comprising the key name and key secret in a single string
|
191
|
-
# @option auth_options [String] :client_id client ID identifying this connection to other clients (will use +client_id+ specified when library was instanced if provided)
|
192
|
-
# @option auth_options [Boolean] :query_time when true will query the {https://www.ably.io Ably} system for the current time instead of using the local time
|
193
|
-
# @option auth_options [Hash] :token_params convenience to pass in +token_params+ within the +auth_options+ argument, this helps avoid the following +authorise({key: key}, {ttl: 23})+ by allowing +authorise(key:key,token_params:{ttl:23})+
|
194
|
-
#
|
195
189
|
# @param [Hash] token_params the token params used in the token request
|
196
190
|
# @option token_params [String] :client_id A client ID to associate with this token. The generated token may be used to authenticate as this +client_id+
|
197
191
|
# @option token_params [Integer] :ttl validity time in seconds for the requested {Ably::Models::TokenDetails}. Limits may apply, see {https://www.ably.io/documentation/other/authentication}
|
@@ -199,10 +193,16 @@ module Ably
|
|
199
193
|
# @option token_params [Time] :timestamp the time of the request
|
200
194
|
# @option token_params [String] :nonce an unquoted, unescaped random string of at least 16 characters
|
201
195
|
#
|
196
|
+
# @param [Hash] auth_options the authentication options for the token request
|
197
|
+
# @option auth_options [String] :key API key comprising the key name and key secret in a single string
|
198
|
+
# @option auth_options [String] :client_id client ID identifying this connection to other clients (will use +client_id+ specified when library was instanced if provided)
|
199
|
+
# @option auth_options [Boolean] :query_time when true will query the {https://www.ably.io Ably} system for the current time instead of using the local time
|
200
|
+
# @option auth_options [Hash] :token_params convenience to pass in +token_params+ within the +auth_options+ argument, especially useful when setting default token_params in the client constructor
|
201
|
+
#
|
202
202
|
# @return [Models::TokenRequest]
|
203
203
|
#
|
204
204
|
# @example
|
205
|
-
# client.auth.create_token_request(id: 'asd.asd'
|
205
|
+
# client.auth.create_token_request({ ttl: 3600 }, { id: 'asd.asd' })
|
206
206
|
# #<Ably::Models::TokenRequest:0x007fd5d919df78
|
207
207
|
# # @hash={
|
208
208
|
# # :id=>"asds.adsa",
|
@@ -214,7 +214,7 @@ module Ably
|
|
214
214
|
# # :mac=>"881oZHeFo6oMim7....uE56a8gUxHw="
|
215
215
|
# # }
|
216
216
|
# #>>
|
217
|
-
def create_token_request(
|
217
|
+
def create_token_request(token_params = {}, auth_options = {})
|
218
218
|
ensure_valid_auth_attributes auth_options
|
219
219
|
|
220
220
|
auth_options = auth_options.clone
|
@@ -401,7 +401,11 @@ module Ably
|
|
401
401
|
|
402
402
|
# Returns the current token if it exists or authorises and retrieves a token
|
403
403
|
def token_auth_string
|
404
|
-
|
404
|
+
# If a TokenDetails object has been issued by this library
|
405
|
+
# then that Token will take precedence
|
406
|
+
if @current_token_details
|
407
|
+
authorise.token
|
408
|
+
elsif token # token string was configured in the options
|
405
409
|
token
|
406
410
|
else
|
407
411
|
authorise.token
|
@@ -58,6 +58,9 @@ module Ably
|
|
58
58
|
# Connection Timeout accessing Realtime or REST service
|
59
59
|
class ConnectionTimeout < ConnectionError; end
|
60
60
|
|
61
|
+
# Transport closed unexpectedly
|
62
|
+
class TransportClosed < ConnectionError; end
|
63
|
+
|
61
64
|
# Connection closed unexpectedly
|
62
65
|
class ConnectionClosed < ConnectionError; end
|
63
66
|
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Ably::Models
|
2
|
+
# ChannelStateChange is a class that is emitted by the {Ably::Realtime::Channel} object
|
3
|
+
# when a state change occurs
|
4
|
+
#
|
5
|
+
# @!attribute [r] current
|
6
|
+
# @return [Connection::STATE] Current connection state
|
7
|
+
# @!attribute [r] previous
|
8
|
+
# @return [Connection::STATE] Previous connection state
|
9
|
+
# @!attribute [r] reason
|
10
|
+
# @return [Ably::Models::ErrorInfo] Object describing the reason for a state change when not initiated by the consumer of the client library
|
11
|
+
#
|
12
|
+
class ChannelStateChange
|
13
|
+
include Ably::Modules::ModelCommon
|
14
|
+
|
15
|
+
def initialize(hash_object)
|
16
|
+
unless (hash_object.keys - [:current, :previous, :reason, :protocol_message]).empty?
|
17
|
+
raise ArgumentError, 'Invalid attributes, expecting :current, :previous, :reason'
|
18
|
+
end
|
19
|
+
|
20
|
+
@hash_object = {
|
21
|
+
current: hash_object.fetch(:current),
|
22
|
+
previous: hash_object.fetch(:previous),
|
23
|
+
retry_in: hash_object[:retry_in],
|
24
|
+
reason: hash_object[:reason],
|
25
|
+
protocol_message: hash_object[:protocol_message]
|
26
|
+
}
|
27
|
+
rescue KeyError => e
|
28
|
+
raise ArgumentError, e
|
29
|
+
end
|
30
|
+
|
31
|
+
%w(current previous reason protocol_message).each do |attribute|
|
32
|
+
define_method attribute do
|
33
|
+
@hash_object[attribute.to_sym]
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def to_s
|
38
|
+
"ChannelStateChange: current state #{current}, previous state #{previous}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Ably::Models
|
2
|
+
# ConnectionStateChange is a class that is emitted by the {Ably::Realtime::Connection} object
|
3
|
+
# when a state change occurs
|
4
|
+
#
|
5
|
+
# @!attribute [r] current
|
6
|
+
# @return [Connection::STATE] Current connection state
|
7
|
+
# @!attribute [r] previous
|
8
|
+
# @return [Connection::STATE] Previous connection state
|
9
|
+
# @!attribute [r] retry_in
|
10
|
+
# @return [Integer] Time in seconds until the connection will reattempt to connect when in the +:disconnected+ or +:suspended+ state
|
11
|
+
# @!attribute [r] reason
|
12
|
+
# @return [Ably::Models::ErrorInfo] Object describing the reason for a state change when not initiated by the consumer of the client library
|
13
|
+
#
|
14
|
+
class ConnectionStateChange
|
15
|
+
include Ably::Modules::ModelCommon
|
16
|
+
|
17
|
+
def initialize(hash_object)
|
18
|
+
unless (hash_object.keys - [:current, :previous, :retry_in, :reason, :protocol_message]).empty?
|
19
|
+
raise ArgumentError, 'Invalid attributes, expecting :current, :previous, :retry_in, :reason'
|
20
|
+
end
|
21
|
+
|
22
|
+
@hash_object = {
|
23
|
+
current: hash_object.fetch(:current),
|
24
|
+
previous: hash_object.fetch(:previous),
|
25
|
+
retry_in: hash_object[:retry_in],
|
26
|
+
reason: hash_object[:reason],
|
27
|
+
protocol_message: hash_object[:protocol_message]
|
28
|
+
}
|
29
|
+
rescue KeyError => e
|
30
|
+
raise ArgumentError, e
|
31
|
+
end
|
32
|
+
|
33
|
+
%w(current previous retry_in reason protocol_message).each do |attribute|
|
34
|
+
define_method attribute do
|
35
|
+
@hash_object[attribute.to_sym]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def to_s
|
40
|
+
"ConnectionStateChange: current state #{current}, previous state #{previous}"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -34,7 +34,7 @@ module Ably::Models
|
|
34
34
|
# @param attributes
|
35
35
|
# @option attributes [String] :token token used to authenticate requests
|
36
36
|
# @option attributes [String] :key_name API key name used to create this token
|
37
|
-
# @option attributes [Time,Integer] :issued
|
37
|
+
# @option attributes [Time,Integer] :issued Time the token was issued as Time or Integer in milliseconds
|
38
38
|
# @option attributes [Time,Integer] :expires Time the token expires as Time or Integer in milliseconds
|
39
39
|
# @option attributes [String] :capability JSON stringified capabilities assigned to this token
|
40
40
|
# @option attributes [String] :client_id client ID assigned to this token
|
@@ -52,31 +52,31 @@ module Ably::Models
|
|
52
52
|
# @!attribute [r] token
|
53
53
|
# @return [String] Token used to authenticate requests
|
54
54
|
def token
|
55
|
-
hash
|
55
|
+
hash[:token]
|
56
56
|
end
|
57
57
|
|
58
58
|
# @!attribute [r] key_name
|
59
59
|
# @return [String] API key name used to create this token. An API key is made up of an API key name and secret delimited by a +:+
|
60
60
|
def key_name
|
61
|
-
hash
|
61
|
+
hash[:key_name]
|
62
62
|
end
|
63
63
|
|
64
64
|
# @!attribute [r] issued
|
65
65
|
# @return [Time] Time the token was issued
|
66
66
|
def issued
|
67
|
-
as_time_from_epoch(hash
|
67
|
+
as_time_from_epoch(hash[:issued], granularity: :ms, allow_nil: :true)
|
68
68
|
end
|
69
69
|
|
70
70
|
# @!attribute [r] expires
|
71
71
|
# @return [Time] Time the token expires
|
72
72
|
def expires
|
73
|
-
as_time_from_epoch(hash
|
73
|
+
as_time_from_epoch(hash[:expires], granularity: :ms, allow_nil: :true)
|
74
74
|
end
|
75
75
|
|
76
76
|
# @!attribute [r] capability
|
77
77
|
# @return [Hash] Capabilities assigned to this token
|
78
78
|
def capability
|
79
|
-
JSON.parse(hash.fetch(:capability))
|
79
|
+
JSON.parse(hash.fetch(:capability)) if hash.fetch(:capability)
|
80
80
|
end
|
81
81
|
|
82
82
|
# @!attribute [r] client_id
|
@@ -86,9 +86,11 @@ module Ably::Models
|
|
86
86
|
end
|
87
87
|
|
88
88
|
# Returns true if token is expired or about to expire
|
89
|
+
# For tokens that have not got an explicit expires attribute expired? will always return true
|
89
90
|
#
|
90
91
|
# @return [Boolean]
|
91
92
|
def expired?
|
93
|
+
return false if !expires
|
92
94
|
expires < Time.now + TOKEN_EXPIRY_BUFFER
|
93
95
|
end
|
94
96
|
|
@@ -6,6 +6,8 @@ module Ably::Modules
|
|
6
6
|
|
7
7
|
private
|
8
8
|
def as_since_epoch(time, options = {})
|
9
|
+
return nil if options[:allow_nil] && !time
|
10
|
+
|
9
11
|
granularity = options.fetch(:granularity, :ms)
|
10
12
|
|
11
13
|
case time
|
@@ -19,6 +21,8 @@ module Ably::Modules
|
|
19
21
|
end
|
20
22
|
|
21
23
|
def as_time_from_epoch(time, options = {})
|
24
|
+
return nil if options[:allow_nil] && !time
|
25
|
+
|
22
26
|
granularity = options.fetch(:granularity, :ms)
|
23
27
|
|
24
28
|
case time
|
@@ -141,7 +141,10 @@ module Ably::Modules
|
|
141
141
|
#
|
142
142
|
def deferrable_for_state_change_to(target_state)
|
143
143
|
Ably::Util::SafeDeferrable.new(logger).tap do |deferrable|
|
144
|
-
|
144
|
+
fail_proc = Proc.new do |state_change|
|
145
|
+
deferrable.fail state_change.reason
|
146
|
+
end
|
147
|
+
once_or_if(target_state, else: fail_proc) do
|
145
148
|
yield self if block_given?
|
146
149
|
deferrable.succeed self
|
147
150
|
end
|
@@ -13,8 +13,8 @@ module Ably::Modules
|
|
13
13
|
#
|
14
14
|
# @return [Boolean] true if new_state can be transitioned to by state machine
|
15
15
|
# @api private
|
16
|
-
def transition_state_machine(new_state,
|
17
|
-
state_machine.transition_state(new_state, emit_object)
|
16
|
+
def transition_state_machine(new_state, emit_params = {})
|
17
|
+
state_machine.transition_state(new_state, emit_object(new_state, emit_params))
|
18
18
|
end
|
19
19
|
|
20
20
|
# Call #transition_to! on the StateMachine
|
@@ -22,8 +22,8 @@ module Ably::Modules
|
|
22
22
|
#
|
23
23
|
# @return [void]
|
24
24
|
# @api private
|
25
|
-
def transition_state_machine!(new_state,
|
26
|
-
state_machine.transition_to!(new_state, emit_object)
|
25
|
+
def transition_state_machine!(new_state, emit_params = {})
|
26
|
+
state_machine.transition_to!(new_state, emit_object(new_state, emit_params))
|
27
27
|
end
|
28
28
|
|
29
29
|
# Provides an internal method for this object's state to match the StateMachine's current state.
|
@@ -70,5 +70,36 @@ module Ably::Modules
|
|
70
70
|
logger.debug "#{self.class.name}: Transitioned to #{state_machine.current_state}"
|
71
71
|
end
|
72
72
|
end
|
73
|
+
|
74
|
+
def emit_object(new_state, emit_params)
|
75
|
+
if self.class.emits_klass
|
76
|
+
self.class.emits_klass.new((emit_params || {}).merge(current: STATE(new_state), previous: STATE(state_machine.current_state)))
|
77
|
+
else
|
78
|
+
emit_params
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.included(base)
|
83
|
+
base.extend(ClassMethods)
|
84
|
+
end
|
85
|
+
|
86
|
+
module ClassMethods
|
87
|
+
def emits_klass
|
88
|
+
@emits_klass ||= if @emits_klass_name
|
89
|
+
get_const(@emits_klass_name)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def ensure_state_machine_emits(klass)
|
94
|
+
@emits_klass_name = klass
|
95
|
+
end
|
96
|
+
|
97
|
+
def get_const(klass_name)
|
98
|
+
klass_names = klass_name.split('::')
|
99
|
+
klass_names.inject(Kernel) do |klass, name|
|
100
|
+
klass.const_get(name)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
73
104
|
end
|
74
105
|
end
|