ably 0.7.5 → 0.7.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|