ably 0.7.5 → 0.7.6
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 -13
- data/.gitignore +1 -0
- data/.gitmodules +3 -0
- data/README.md +46 -22
- data/SPEC.md +345 -240
- data/ably.gemspec +4 -2
- data/lib/ably/auth.rb +18 -14
- data/lib/ably/models/message.rb +1 -1
- data/lib/ably/models/paginated_resource.rb +31 -44
- data/lib/ably/models/presence_message.rb +1 -1
- data/lib/ably/models/stat.rb +67 -24
- data/lib/ably/models/stats_types.rb +131 -0
- data/lib/ably/modules/async_wrapper.rb +3 -2
- data/lib/ably/modules/message_emitter.rb +2 -2
- data/lib/ably/realtime.rb +1 -1
- data/lib/ably/realtime/channel.rb +24 -3
- data/lib/ably/realtime/channel/channel_manager.rb +1 -0
- data/lib/ably/realtime/client.rb +2 -2
- data/lib/ably/realtime/connection.rb +1 -1
- data/lib/ably/realtime/presence.rb +12 -1
- data/lib/ably/rest.rb +1 -1
- data/lib/ably/rest/channel.rb +4 -5
- data/lib/ably/rest/client.rb +5 -5
- data/lib/ably/rest/presence.rb +2 -2
- data/lib/ably/version.rb +1 -1
- data/spec/acceptance/realtime/channel_history_spec.rb +74 -23
- data/spec/acceptance/realtime/channel_spec.rb +3 -3
- data/spec/acceptance/realtime/client_spec.rb +3 -3
- data/spec/acceptance/realtime/connection_failures_spec.rb +2 -2
- data/spec/acceptance/realtime/connection_spec.rb +4 -4
- data/spec/acceptance/realtime/message_spec.rb +5 -5
- data/spec/acceptance/realtime/presence_history_spec.rb +56 -13
- data/spec/acceptance/realtime/presence_spec.rb +8 -8
- data/spec/acceptance/realtime/stats_spec.rb +1 -1
- data/spec/acceptance/realtime/time_spec.rb +1 -1
- data/spec/acceptance/rest/auth_spec.rb +31 -4
- data/spec/acceptance/rest/base_spec.rb +3 -3
- data/spec/acceptance/rest/channel_spec.rb +19 -19
- data/spec/acceptance/rest/channels_spec.rb +1 -1
- data/spec/acceptance/rest/client_spec.rb +9 -6
- data/spec/acceptance/rest/encoders_spec.rb +1 -1
- data/spec/acceptance/rest/message_spec.rb +10 -10
- data/spec/acceptance/rest/presence_spec.rb +81 -51
- data/spec/acceptance/rest/stats_spec.rb +46 -41
- data/spec/acceptance/rest/time_spec.rb +1 -1
- data/spec/shared/client_initializer_behaviour.rb +30 -19
- data/spec/spec_helper.rb +3 -0
- data/spec/support/markdown_spec_formatter.rb +1 -1
- data/spec/support/test_app.rb +11 -24
- data/spec/unit/auth_spec.rb +1 -1
- data/spec/unit/models/paginated_resource_spec.rb +81 -72
- data/spec/unit/models/stats_spec.rb +289 -0
- data/spec/unit/modules/async_wrapper_spec.rb +1 -1
- data/spec/unit/realtime/client_spec.rb +1 -1
- data/spec/unit/realtime/realtime_spec.rb +1 -1
- data/spec/unit/rest/channel_spec.rb +1 -1
- data/spec/unit/rest/client_spec.rb +8 -8
- data/spec/unit/rest/rest_spec.rb +1 -1
- data/spec/unit/util/crypto_spec.rb +1 -1
- metadata +55 -43
- data/spec/resources/crypto-data-128.json +0 -56
- data/spec/resources/crypto-data-256.json +0 -56
- data/spec/unit/models/stat_spec.rb +0 -113
data/ably.gemspec
CHANGED
@@ -8,8 +8,8 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.version = Ably::VERSION
|
9
9
|
spec.authors = ['Lewis Marshall', "Matthew O'Riordan"]
|
10
10
|
spec.email = ['lewis@lmars.net', 'matt@ably.io']
|
11
|
-
spec.description = %q{A Ruby client library for ably.io, the
|
12
|
-
spec.summary = %q{A Ruby client library for ably.io, the
|
11
|
+
spec.description = %q{A Ruby client library for ably.io, the realtime messaging service}
|
12
|
+
spec.summary = %q{A Ruby client library for ably.io, the realtime messaging service}
|
13
13
|
spec.homepage = 'http://github.com/ably/ably-ruby'
|
14
14
|
spec.license = 'MIT'
|
15
15
|
|
@@ -33,4 +33,6 @@ Gem::Specification.new do |spec|
|
|
33
33
|
spec.add_development_dependency 'rspec-retry'
|
34
34
|
spec.add_development_dependency 'yard'
|
35
35
|
spec.add_development_dependency 'webmock'
|
36
|
+
|
37
|
+
spec.add_development_dependency 'coveralls'
|
36
38
|
end
|
data/lib/ably/auth.rb
CHANGED
@@ -15,7 +15,7 @@ module Ably
|
|
15
15
|
# @return [Ably::Models::Token] Current {Ably::Models::Token} issued by this library or one of the provided callbacks used to authenticate requests
|
16
16
|
# @!attribute [r] token_id
|
17
17
|
# @return [String] Token ID provided to the {Ably::Client} constructor that is used to authenticate all requests
|
18
|
-
# @!attribute [r]
|
18
|
+
# @!attribute [r] key
|
19
19
|
# @return [String] Complete API key containing both the key ID and key secret, if present
|
20
20
|
# @!attribute [r] key_id
|
21
21
|
# @return [String] Key ID (public part of the API key), if present
|
@@ -49,14 +49,16 @@ module Ably
|
|
49
49
|
raise ArgumentError, 'Expected auth_options to be a Hash'
|
50
50
|
end
|
51
51
|
|
52
|
-
|
53
|
-
|
52
|
+
api_key = auth_options[:key] || auth_options[:api_key] # backwards support for previously used :api_key
|
53
|
+
|
54
|
+
if api_key && (auth_options[:key_secret] || auth_options[:key_id])
|
55
|
+
raise ArgumentError, 'key and key_id or key_secret are mutually exclusive. Provider either a key or key_id & key_secret'
|
54
56
|
end
|
55
57
|
|
56
|
-
split_api_key_into_key_and_secret! auth_options if
|
58
|
+
split_api_key_into_key_and_secret! auth_options if api_key
|
57
59
|
|
58
60
|
if using_basic_auth? && !api_key_present?
|
59
|
-
raise ArgumentError, '
|
61
|
+
raise ArgumentError, 'key is missing. Either an API key, token, or token auth method must be provided'
|
60
62
|
end
|
61
63
|
|
62
64
|
if has_client_id?
|
@@ -73,7 +75,7 @@ module Ably
|
|
73
75
|
#
|
74
76
|
# @param [Hash] options the options for the token request
|
75
77
|
# @option options (see #request_token)
|
76
|
-
# @option options [String] :
|
78
|
+
# @option options [String] :key API key comprising the key ID and key secret in a single string
|
77
79
|
# @option options [Boolean] :force obtains a new token even if the current token is valid
|
78
80
|
#
|
79
81
|
# @yield (see #request_token)
|
@@ -84,7 +86,7 @@ module Ably
|
|
84
86
|
#
|
85
87
|
# @example
|
86
88
|
# # will issue a simple token request using basic auth
|
87
|
-
# client = Ably::Rest::Client.new(
|
89
|
+
# client = Ably::Rest::Client.new(key: 'key.id:secret')
|
88
90
|
# token = client.auth.authorise
|
89
91
|
#
|
90
92
|
# # will use token request from block to authorise if not already authorised
|
@@ -99,7 +101,9 @@ module Ably
|
|
99
101
|
end
|
100
102
|
|
101
103
|
options = options.clone
|
102
|
-
|
104
|
+
|
105
|
+
api_key = options[:key] || options[:api_key] # backwards support for previously used :api_key
|
106
|
+
split_api_key_into_key_and_secret! options if api_key
|
103
107
|
|
104
108
|
@options = @options.merge(options)
|
105
109
|
@default_token_block = token_request_block if block_given?
|
@@ -131,7 +135,7 @@ module Ably
|
|
131
135
|
#
|
132
136
|
# @example
|
133
137
|
# # simple token request using basic auth
|
134
|
-
# client = Ably::Rest::Client.new(
|
138
|
+
# client = Ably::Rest::Client.new(key: 'key.id:secret')
|
135
139
|
# token = client.auth.request_token
|
136
140
|
#
|
137
141
|
# # token request using auth block
|
@@ -179,7 +183,7 @@ module Ably
|
|
179
183
|
# @return [Hash]
|
180
184
|
#
|
181
185
|
# @example
|
182
|
-
# client.auth.
|
186
|
+
# client.auth.create_token_request(id: 'asd.asd', ttl: 3600)
|
183
187
|
# # => {
|
184
188
|
# # :id=>"asds.adsa",
|
185
189
|
# # :client_id=>nil,
|
@@ -225,7 +229,7 @@ module Ably
|
|
225
229
|
convert_to_mixed_case_hash(token_request)
|
226
230
|
end
|
227
231
|
|
228
|
-
def
|
232
|
+
def key
|
229
233
|
"#{key_id}:#{key_secret}" if api_key_present?
|
230
234
|
end
|
231
235
|
|
@@ -308,12 +312,12 @@ module Ably
|
|
308
312
|
# Basic Auth HTTP Authorization header value
|
309
313
|
def basic_auth_header
|
310
314
|
ensure_api_key_sent_over_secure_connection
|
311
|
-
"Basic #{encode64("#{
|
315
|
+
"Basic #{encode64("#{key}")}"
|
312
316
|
end
|
313
317
|
|
314
318
|
def split_api_key_into_key_and_secret!(options)
|
315
|
-
api_key_parts = options[:api_key].to_s.match(/(?<id>[\w_-]+\.[\w_-]+):(?<secret>[\w_-]+)/)
|
316
|
-
raise ArgumentError, '
|
319
|
+
api_key_parts = (options[:key] || options[:api_key]).to_s.match(/(?<id>[\w_-]+\.[\w_-]+):(?<secret>[\w_-]+)/)
|
320
|
+
raise ArgumentError, 'key is invalid' unless api_key_parts
|
317
321
|
|
318
322
|
options[:key_id] = api_key_parts[:id].encode(Encoding::UTF_8)
|
319
323
|
options[:key_secret] = api_key_parts[:secret].encode(Encoding::UTF_8)
|
data/lib/ably/models/message.rb
CHANGED
@@ -29,7 +29,7 @@ module Ably::Models
|
|
29
29
|
# @return [Object] The encoding for the message data. Encoding and decoding of messages is handled automatically by the client library.
|
30
30
|
# Therefore, the `encoding` attribute should always be nil unless an Ably library decoding error has occurred.
|
31
31
|
# @!attribute [r] timestamp
|
32
|
-
# @return [Time] Timestamp when the message was received by the Ably the
|
32
|
+
# @return [Time] Timestamp when the message was received by the Ably the realtime service
|
33
33
|
# @!attribute [r] id
|
34
34
|
# @return [String] A globally unique message ID
|
35
35
|
# @!attribute [r] connection_id
|
@@ -1,12 +1,18 @@
|
|
1
1
|
module Ably::Models
|
2
|
-
# Wraps any Ably HTTP response that supports paging and
|
3
|
-
# the
|
2
|
+
# Wraps any Ably HTTP response that supports paging and provides methods to iterate through
|
3
|
+
# the pages using {#first}, {#next}, {#first?}, {#has_next?} and {#last?}
|
4
|
+
#
|
5
|
+
# All items in the HTTP response are available in the Array returned from {#items}
|
4
6
|
#
|
5
7
|
# Paging information is provided by Ably in the LINK HTTP headers
|
8
|
+
#
|
6
9
|
class PaginatedResource
|
7
|
-
include Enumerable
|
8
10
|
include Ably::Modules::AsyncWrapper if defined?(Ably::Realtime)
|
9
11
|
|
12
|
+
# The items contained within this {PaginatedResource}
|
13
|
+
# @return [Array]
|
14
|
+
attr_reader :items
|
15
|
+
|
10
16
|
# @param [Faraday::Response] http_response Initial HTTP response from an Ably request to a paged resource
|
11
17
|
# @param [String] base_url Base URL for request that generated the http_response so that subsequent paged requests can be made
|
12
18
|
# @param [Client] client {Ably::Client} used to make the request to Ably
|
@@ -25,9 +31,9 @@ module Ably::Models
|
|
25
31
|
@each_block = each_block
|
26
32
|
@make_async = options.fetch(:async_blocking_operations, false)
|
27
33
|
|
28
|
-
@
|
29
|
-
@
|
30
|
-
@
|
34
|
+
@items = http_response.body
|
35
|
+
@items = coerce_items_into(items, @coerce_into) if @coerce_into
|
36
|
+
@items = items.map { |item| yield item } if block_given?
|
31
37
|
end
|
32
38
|
|
33
39
|
# Retrieve the first page of results.
|
@@ -35,8 +41,9 @@ module Ably::Models
|
|
35
41
|
# and allows an optional success callback block to be provided.
|
36
42
|
#
|
37
43
|
# @return [PaginatedResource,Ably::Util::SafeDeferrable]
|
38
|
-
def
|
44
|
+
def first(&success_callback)
|
39
45
|
async_wrap_if_realtime(success_callback) do
|
46
|
+
return nil unless supports_pagination?
|
40
47
|
PaginatedResource.new(client.get(pagination_url('first')), base_url, client, pagination_options, &each_block)
|
41
48
|
end
|
42
49
|
end
|
@@ -46,9 +53,9 @@ module Ably::Models
|
|
46
53
|
# and allows an optional success callback block to be provided.
|
47
54
|
#
|
48
55
|
# @return [PaginatedResource,Ably::Util::SafeDeferrable]
|
49
|
-
def
|
56
|
+
def next(&success_callback)
|
50
57
|
async_wrap_if_realtime(success_callback) do
|
51
|
-
|
58
|
+
return nil unless has_next?
|
52
59
|
PaginatedResource.new(client.get(pagination_url('next')), base_url, client, pagination_options, &each_block)
|
53
60
|
end
|
54
61
|
end
|
@@ -56,7 +63,7 @@ module Ably::Models
|
|
56
63
|
# True if this is the last page in the paged resource set
|
57
64
|
#
|
58
65
|
# @return [Boolean]
|
59
|
-
def
|
66
|
+
def last?
|
60
67
|
!supports_pagination? ||
|
61
68
|
pagination_header('next').nil?
|
62
69
|
end
|
@@ -64,11 +71,18 @@ module Ably::Models
|
|
64
71
|
# True if this is the first page in the paged resource set
|
65
72
|
#
|
66
73
|
# @return [Boolean]
|
67
|
-
def
|
74
|
+
def first?
|
68
75
|
!supports_pagination? ||
|
69
76
|
pagination_header('first') == pagination_header('current')
|
70
77
|
end
|
71
78
|
|
79
|
+
# True if there is a subsequent page in this paginated set available with {#next}
|
80
|
+
#
|
81
|
+
# @return [Boolean]
|
82
|
+
def has_next?
|
83
|
+
supports_pagination? && !last?
|
84
|
+
end
|
85
|
+
|
72
86
|
# True if the HTTP response supports paging with the expected LINK HTTP headers
|
73
87
|
#
|
74
88
|
# @return [Boolean]
|
@@ -76,48 +90,21 @@ module Ably::Models
|
|
76
90
|
!pagination_headers.empty?
|
77
91
|
end
|
78
92
|
|
79
|
-
# Standard Array accessor method
|
80
|
-
def [](index)
|
81
|
-
body[index]
|
82
|
-
end
|
83
|
-
|
84
|
-
# Returns number of items within this page, not the total number of items in the entire paged resource set
|
85
|
-
def length
|
86
|
-
body.length
|
87
|
-
end
|
88
|
-
alias_method :count, :length
|
89
|
-
alias_method :size, :length
|
90
|
-
|
91
|
-
# Method to allow {PaginatedResource} to be {http://ruby-doc.org/core-2.1.3/Enumerable.html Enumerable}
|
92
|
-
def each(&block)
|
93
|
-
return to_enum(:each) unless block_given?
|
94
|
-
body.each(&block)
|
95
|
-
end
|
96
|
-
|
97
|
-
# First item in this page
|
98
|
-
def first
|
99
|
-
body.first
|
100
|
-
end
|
101
|
-
|
102
|
-
# Last item in this page
|
103
|
-
def last
|
104
|
-
body.last
|
105
|
-
end
|
106
|
-
|
107
93
|
def inspect
|
108
94
|
<<-EOF.gsub(/^ /, '')
|
109
95
|
#<#{self.class.name}:#{self.object_id}
|
110
96
|
@base_url="#{base_url}",
|
111
|
-
@
|
112
|
-
@
|
113
|
-
@
|
114
|
-
|
97
|
+
@first?=#{!!first?},
|
98
|
+
@last?=#{!!first?},
|
99
|
+
@has_next?=#{!!has_next?},
|
100
|
+
@items=
|
101
|
+
#{items.map { |item| item.inspect }.join(",\n ") }
|
115
102
|
>
|
116
103
|
EOF
|
117
104
|
end
|
118
105
|
|
119
106
|
private
|
120
|
-
attr_reader :
|
107
|
+
attr_reader :http_response, :base_url, :client, :coerce_into, :raw_body, :each_block, :make_async
|
121
108
|
|
122
109
|
def coerce_items_into(items, type_string)
|
123
110
|
items.map do |item|
|
@@ -33,7 +33,7 @@ module Ably::Models
|
|
33
33
|
# @return [Object] The encoding for the message data. Encoding and decoding of messages is handled automatically by the client library.
|
34
34
|
# Therefore, the `encoding` attribute should always be nil unless an Ably library decoding error has occurred.
|
35
35
|
# @!attribute [r] timestamp
|
36
|
-
# @return [Time] Timestamp when the message was received by the Ably the
|
36
|
+
# @return [Time] Timestamp when the message was received by the Ably the realtime service
|
37
37
|
# @!attribute [r] hash
|
38
38
|
# @return [Hash] Access the protocol message Hash object ruby'fied to use symbolized keys
|
39
39
|
#
|
data/lib/ably/models/stat.rb
CHANGED
@@ -1,38 +1,40 @@
|
|
1
|
+
require 'ably/models/stats_types'
|
2
|
+
|
1
3
|
module Ably::Models
|
2
|
-
# Convert stat argument to a {
|
4
|
+
# Convert stat argument to a {Stats} object
|
3
5
|
#
|
4
|
-
# @param stat [
|
6
|
+
# @param stat [Stats,Hash] A Stats object or Hash of stat properties
|
5
7
|
#
|
6
|
-
# @return [
|
7
|
-
def self.
|
8
|
+
# @return [Stats]
|
9
|
+
def self.Stats(stat)
|
8
10
|
case stat
|
9
|
-
when
|
11
|
+
when Stats
|
10
12
|
stat
|
11
13
|
else
|
12
|
-
|
14
|
+
Stats.new(stat)
|
13
15
|
end
|
14
16
|
end
|
15
17
|
|
16
18
|
# A class representing an individual statistic for a specified {#interval_id}
|
17
19
|
#
|
18
20
|
# @!attribute [r] all
|
19
|
-
# @return [
|
21
|
+
# @return [Stats::MessageTypes] Breakdown of summary stats for all message types
|
20
22
|
# @!attribute [r] inbound
|
21
|
-
# @return [
|
23
|
+
# @return [Stats::MessageTraffic] Breakdown of summary stats for traffic over various transport types for all inbound messages
|
22
24
|
# @!attribute [r] outbound
|
23
|
-
# @return [
|
25
|
+
# @return [Stats::MessageTraffic] Breakdown of summary stats for traffic over various transport types for all outbound messages
|
24
26
|
# @!attribute [r] persisted
|
25
|
-
# @return [
|
27
|
+
# @return [Stats::MessageTypes] Breakdown of summary stats for all persisted messages
|
26
28
|
# @!attribute [r] connections
|
27
|
-
# @return [
|
29
|
+
# @return [Stats::ConnectionTypes] A breakdown of summary stats data for different (TLS vs non-TLS) connection types.
|
28
30
|
# @!attribute [r] channels
|
29
|
-
# @return [
|
31
|
+
# @return [Stats::ResourceCount] Aggregate data for usage of Channels
|
30
32
|
# @!attribute [r] api_requests
|
31
|
-
# @return [
|
33
|
+
# @return [Stats::RequestCount] Aggregate data for numbers of API requests
|
32
34
|
# @!attribute [r] token_requests
|
33
|
-
# @return [
|
35
|
+
# @return [Stats::RequestCount] Aggregate data for numbers of Token requests
|
34
36
|
#
|
35
|
-
class
|
37
|
+
class Stats
|
36
38
|
include Ably::Modules::ModelCommon
|
37
39
|
extend Ably::Modules::Enum
|
38
40
|
|
@@ -53,7 +55,7 @@ module Ably::Models
|
|
53
55
|
class << self
|
54
56
|
# Convert a Time with the specified Granularity into an interval ID based on UTC 0 time
|
55
57
|
# @example
|
56
|
-
#
|
58
|
+
# Stats.to_interval_id(Time.now, :hour) # => '2015-01-01:10'
|
57
59
|
#
|
58
60
|
# @param time [Time] Time used to determine the interval
|
59
61
|
# @param granularity [GRANULARITY] Granularity of the metrics such as :hour, :day
|
@@ -71,7 +73,7 @@ module Ably::Models
|
|
71
73
|
|
72
74
|
# Returns the UTC 0 start Time of an interval_id
|
73
75
|
# @example
|
74
|
-
#
|
76
|
+
# Stats.from_interval_id('2015-01-01:10') # => 2015-01-01 10:00:00 +0000
|
75
77
|
#
|
76
78
|
# @param interval_id [String]
|
77
79
|
#
|
@@ -88,7 +90,7 @@ module Ably::Models
|
|
88
90
|
|
89
91
|
# Returns the {GRANULARITY} determined from the interval_id
|
90
92
|
# @example
|
91
|
-
#
|
93
|
+
# Stats.granularity_from_interval_id('2015-01-01:10') # => :hour
|
92
94
|
#
|
93
95
|
# @param interval_id [String]
|
94
96
|
#
|
@@ -109,20 +111,61 @@ module Ably::Models
|
|
109
111
|
end
|
110
112
|
end
|
111
113
|
|
112
|
-
# {
|
114
|
+
# {Stats} initializer
|
113
115
|
#
|
114
116
|
# @param hash_object [Hash] object with the underlying stat details
|
115
117
|
#
|
116
118
|
def initialize(hash_object)
|
117
119
|
@raw_hash_object = hash_object
|
118
|
-
|
119
120
|
set_hash_object hash_object
|
120
121
|
end
|
121
122
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
123
|
+
# Aggregates inbound and outbound messages
|
124
|
+
# return {@Stats::MessageTypes}
|
125
|
+
def all
|
126
|
+
@all ||= Stats::MessageTypes.new(hash[:all])
|
127
|
+
end
|
128
|
+
|
129
|
+
# All inbound messages i.e. received by Ably from clients
|
130
|
+
# @return {Stats::MessageTraffic}
|
131
|
+
def inbound
|
132
|
+
@inbound ||= Stats::MessageTraffic.new(hash[:inbound])
|
133
|
+
end
|
134
|
+
|
135
|
+
# All outbound messages i.e. sent from Ably to clients
|
136
|
+
# @return {Stats::MessageTraffic}
|
137
|
+
def outbound
|
138
|
+
@outbound ||= Stats::MessageTraffic.new(hash[:outbound])
|
139
|
+
end
|
140
|
+
|
141
|
+
# Messages persisted for later retrieval via the history API
|
142
|
+
# @return {Stats::MessageTypes}
|
143
|
+
def persisted
|
144
|
+
@persisted ||= Stats::MessageTypes.new(hash[:persisted])
|
145
|
+
end
|
146
|
+
|
147
|
+
# Breakdown of connection stats data for different (TLS vs non-TLS) connection types
|
148
|
+
# @return {Stats::ConnectionTypes}
|
149
|
+
def connections
|
150
|
+
@connections ||= Stats::ConnectionTypes.new(hash[:connections])
|
151
|
+
end
|
152
|
+
|
153
|
+
# Breakdown of channels stats
|
154
|
+
# @return {Stats::ResourceCount}
|
155
|
+
def channels
|
156
|
+
@channels ||= Stats::ResourceCount.new(hash[:channels])
|
157
|
+
end
|
158
|
+
|
159
|
+
# Breakdown of API requests received via the REST API
|
160
|
+
# @return {Stats::RequestCount}
|
161
|
+
def api_requests
|
162
|
+
@api_requests ||= Stats::RequestCount.new(hash[:api_requests])
|
163
|
+
end
|
164
|
+
|
165
|
+
# Breakdown of Token requests received via the REST API
|
166
|
+
# @return {Stats::RequestCount}
|
167
|
+
def token_requests
|
168
|
+
@token_requests ||= Stats::RequestCount.new(hash[:token_requests])
|
126
169
|
end
|
127
170
|
|
128
171
|
# @!attribute [r] interval_id
|
@@ -0,0 +1,131 @@
|
|
1
|
+
module Ably::Models
|
2
|
+
class Stats
|
3
|
+
# StatsStruct is a basic Struct like class that allows methods to be defined
|
4
|
+
# on the class that will be retuned co-erced objects from the underlying hash used to
|
5
|
+
# initialize the object.
|
6
|
+
#
|
7
|
+
# This class provides a concise way to create classes that have fixed attributes and types
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# class MessageCount < StatsStruct
|
11
|
+
# coerce_attributes :count, :data, into: Integer
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# @api private
|
15
|
+
#
|
16
|
+
class StatsStruct
|
17
|
+
class << self
|
18
|
+
def coerce_attributes(*attributes)
|
19
|
+
options = attributes.pop
|
20
|
+
raise ArgumentError, 'Expected attribute into: within options hash' unless options.kind_of?(Hash) && options[:into]
|
21
|
+
|
22
|
+
@type_klass = options[:into]
|
23
|
+
setup_attribute_methods attributes
|
24
|
+
end
|
25
|
+
|
26
|
+
def type_klass
|
27
|
+
@type_klass
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
def setup_attribute_methods(attributes)
|
32
|
+
attributes.each do |attr|
|
33
|
+
define_method(attr) do
|
34
|
+
# Lazy load the co-erced value only when accessed
|
35
|
+
unless instance_variable_defined?("@#{attr}")
|
36
|
+
instance_variable_set "@#{attr}", self.class.type_klass.new(hash[attr.to_sym])
|
37
|
+
end
|
38
|
+
instance_variable_get("@#{attr}")
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
attr_reader :hash
|
45
|
+
|
46
|
+
def initialize(hash)
|
47
|
+
@hash = hash || {}
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# IntegerDefaultZero will always return an Integer object and will default to value 0 unless truthy
|
52
|
+
#
|
53
|
+
# @api private
|
54
|
+
#
|
55
|
+
class IntegerDefaultZero
|
56
|
+
def self.new(value)
|
57
|
+
(value && value.to_i) || 0
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# MessageCount contains aggregate counts for messages and data transferred
|
62
|
+
# @!attribute [r] count
|
63
|
+
# @return [Integer] count of all messages
|
64
|
+
# @!attribute [r] data
|
65
|
+
# @return [Integer] total data transferred for all messages in bytes
|
66
|
+
class MessageCount < StatsStruct
|
67
|
+
coerce_attributes :count, :data, into: IntegerDefaultZero
|
68
|
+
end
|
69
|
+
|
70
|
+
# RequestCount contains aggregate counts for requests made
|
71
|
+
# @!attribute [r] succeeded
|
72
|
+
# @return [Integer] requests succeeded
|
73
|
+
# @!attribute [r] failed
|
74
|
+
# @return [Integer] requests failed
|
75
|
+
# @!attribute [r] refused
|
76
|
+
# @return [Integer] requests refused typically as a result of permissions or a limit being exceeded
|
77
|
+
class RequestCount < StatsStruct
|
78
|
+
coerce_attributes :succeeded, :failed, :refused, into: IntegerDefaultZero
|
79
|
+
end
|
80
|
+
|
81
|
+
# ResourceCount contains aggregate data for usage of a resource in a specific scope
|
82
|
+
# @!attribute [r] opened
|
83
|
+
# @return [Integer] total resources of this type opened
|
84
|
+
# @!attribute [r] peak
|
85
|
+
# @return [Integer] peak resources of this type used for this period
|
86
|
+
# @!attribute [r] mean
|
87
|
+
# @return [Integer] average resources of this type used for this period
|
88
|
+
# @!attribute [r] min
|
89
|
+
# @return [Integer] minimum total resources of this type used for this period
|
90
|
+
# @!attribute [r] refused
|
91
|
+
# @return [Integer] resource requests refused within this period
|
92
|
+
class ResourceCount < StatsStruct
|
93
|
+
coerce_attributes :opened, :peak, :mean, :min, :refused, into: IntegerDefaultZero
|
94
|
+
end
|
95
|
+
|
96
|
+
# ConnectionTypes contains a breakdown of summary stats data for different (TLS vs non-TLS) connection types
|
97
|
+
# @!attribute [r] tls
|
98
|
+
# @return [ResourceCount] TLS connection count
|
99
|
+
# @!attribute [r] plain
|
100
|
+
# @return [ResourceCount] non-TLS connection count (unencrypted)
|
101
|
+
# @!attribute [r] all
|
102
|
+
# @return [ResourceCount] all connection count (includes both TLS & non-TLS connections)
|
103
|
+
class ConnectionTypes < StatsStruct
|
104
|
+
coerce_attributes :tls, :plain, :all, into: ResourceCount
|
105
|
+
end
|
106
|
+
|
107
|
+
# MessageTypes contains a breakdown of summary stats data for different (message vs presence) message types
|
108
|
+
# @!attribute [r] messages
|
109
|
+
# @return [MessageCount] count of channel messages
|
110
|
+
# @!attribute [r] presence
|
111
|
+
# @return [MessageCount] count of presence messages
|
112
|
+
# @!attribute [r] all
|
113
|
+
# @return [MessageCount] all messages count (includes both presence & messages)
|
114
|
+
class MessageTypes < StatsStruct
|
115
|
+
coerce_attributes :messages, :presence, :all, into: MessageCount
|
116
|
+
end
|
117
|
+
|
118
|
+
# MessageTraffic contains a breakdown of summary stats data for traffic over various transport types
|
119
|
+
# @!attribute [r] realtime
|
120
|
+
# @return [MessageTypes] count of messages transferred over a realtime transport such as WebSockets
|
121
|
+
# @!attribute [r] rest
|
122
|
+
# @return [MessageTypes] count of messages transferred using REST
|
123
|
+
# @!attribute [r] webhook
|
124
|
+
# @return [MessageTypes] count of messages delivered using WebHooks
|
125
|
+
# @!attribute [r] all
|
126
|
+
# @return [MessageTypes] all messages count (includes realtime, rest and webhook messages)
|
127
|
+
class MessageTraffic < StatsStruct
|
128
|
+
coerce_attributes :realtime, :rest, :webhook, :all, into: MessageTypes
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|