ably-pubsub-core 0.0.1.pre

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.
Files changed (105) hide show
  1. checksums.yaml +7 -0
  2. data/lib/ably/agent.rb +8 -0
  3. data/lib/ably/auth.rb +791 -0
  4. data/lib/ably/exceptions.rb +169 -0
  5. data/lib/ably/logger.rb +119 -0
  6. data/lib/ably/models/auth_details.rb +45 -0
  7. data/lib/ably/models/channel_details.rb +69 -0
  8. data/lib/ably/models/channel_metrics.rb +107 -0
  9. data/lib/ably/models/channel_occupancy.rb +50 -0
  10. data/lib/ably/models/channel_options.rb +120 -0
  11. data/lib/ably/models/channel_state_change.rb +84 -0
  12. data/lib/ably/models/channel_status.rb +63 -0
  13. data/lib/ably/models/cipher_params.rb +137 -0
  14. data/lib/ably/models/connection_details.rb +149 -0
  15. data/lib/ably/models/connection_state_change.rb +83 -0
  16. data/lib/ably/models/delta_extras.rb +28 -0
  17. data/lib/ably/models/device_details.rb +126 -0
  18. data/lib/ably/models/device_push_details.rb +94 -0
  19. data/lib/ably/models/error_info.rb +104 -0
  20. data/lib/ably/models/http_paginated_response.rb +112 -0
  21. data/lib/ably/models/idiomatic_ruby_wrapper.rb +235 -0
  22. data/lib/ably/models/message.rb +223 -0
  23. data/lib/ably/models/message_encoders/base.rb +135 -0
  24. data/lib/ably/models/message_encoders/base64.rb +40 -0
  25. data/lib/ably/models/message_encoders/cipher.rb +84 -0
  26. data/lib/ably/models/message_encoders/json.rb +34 -0
  27. data/lib/ably/models/message_encoders/utf8.rb +26 -0
  28. data/lib/ably/models/nil_logger.rb +20 -0
  29. data/lib/ably/models/paginated_result.rb +201 -0
  30. data/lib/ably/models/presence_message.rb +244 -0
  31. data/lib/ably/models/protocol_message.rb +288 -0
  32. data/lib/ably/models/push_channel_subscription.rb +114 -0
  33. data/lib/ably/models/stats.rb +242 -0
  34. data/lib/ably/models/stats_types.rb +107 -0
  35. data/lib/ably/models/token_details.rb +148 -0
  36. data/lib/ably/models/token_request.rb +180 -0
  37. data/lib/ably/modules/ably.rb +26 -0
  38. data/lib/ably/modules/async_wrapper.rb +69 -0
  39. data/lib/ably/modules/channels_collection.rb +105 -0
  40. data/lib/ably/modules/conversions.rb +153 -0
  41. data/lib/ably/modules/encodeable.rb +111 -0
  42. data/lib/ably/modules/enum.rb +230 -0
  43. data/lib/ably/modules/event_emitter.rb +200 -0
  44. data/lib/ably/modules/event_machine_helpers.rb +26 -0
  45. data/lib/ably/modules/exception_codes.rb +128 -0
  46. data/lib/ably/modules/http_helpers.rb +41 -0
  47. data/lib/ably/modules/message_emitter.rb +78 -0
  48. data/lib/ably/modules/message_pack.rb +14 -0
  49. data/lib/ably/modules/model_common.rb +84 -0
  50. data/lib/ably/modules/safe_deferrable.rb +83 -0
  51. data/lib/ably/modules/safe_yield.rb +41 -0
  52. data/lib/ably/modules/state_emitter.rb +181 -0
  53. data/lib/ably/modules/state_machine.rb +59 -0
  54. data/lib/ably/modules/statesman_monkey_patch.rb +33 -0
  55. data/lib/ably/modules/uses_state_machine.rb +111 -0
  56. data/lib/ably/realtime/auth.rb +283 -0
  57. data/lib/ably/realtime/channel/channel_manager.rb +272 -0
  58. data/lib/ably/realtime/channel/channel_properties.rb +40 -0
  59. data/lib/ably/realtime/channel/channel_state_machine.rb +104 -0
  60. data/lib/ably/realtime/channel/publisher.rb +82 -0
  61. data/lib/ably/realtime/channel/push_channel.rb +69 -0
  62. data/lib/ably/realtime/channel.rb +440 -0
  63. data/lib/ably/realtime/channels.rb +71 -0
  64. data/lib/ably/realtime/client/incoming_message_dispatcher.rb +225 -0
  65. data/lib/ably/realtime/client/outgoing_message_dispatcher.rb +87 -0
  66. data/lib/ably/realtime/client.rb +363 -0
  67. data/lib/ably/realtime/connection/connection_manager.rb +594 -0
  68. data/lib/ably/realtime/connection/connection_state_machine.rb +144 -0
  69. data/lib/ably/realtime/connection/websocket_transport.rb +287 -0
  70. data/lib/ably/realtime/connection.rb +738 -0
  71. data/lib/ably/realtime/models/nil_channel.rb +30 -0
  72. data/lib/ably/realtime/presence/members_map.rb +395 -0
  73. data/lib/ably/realtime/presence/presence_manager.rb +78 -0
  74. data/lib/ably/realtime/presence/presence_state_machine.rb +57 -0
  75. data/lib/ably/realtime/presence.rb +502 -0
  76. data/lib/ably/realtime/push/admin.rb +75 -0
  77. data/lib/ably/realtime/push/channel_subscriptions.rb +108 -0
  78. data/lib/ably/realtime/push/device_registrations.rb +105 -0
  79. data/lib/ably/realtime/push.rb +25 -0
  80. data/lib/ably/realtime/recovery_key_context.rb +36 -0
  81. data/lib/ably/realtime.rb +60 -0
  82. data/lib/ably/rest/channel/push_channel.rb +59 -0
  83. data/lib/ably/rest/channel.rb +194 -0
  84. data/lib/ably/rest/channels.rb +47 -0
  85. data/lib/ably/rest/client.rb +727 -0
  86. data/lib/ably/rest/middleware/encoder.rb +49 -0
  87. data/lib/ably/rest/middleware/exceptions.rb +53 -0
  88. data/lib/ably/rest/middleware/external_exceptions.rb +24 -0
  89. data/lib/ably/rest/middleware/fail_if_unsupported_mime_type.rb +22 -0
  90. data/lib/ably/rest/middleware/logger.rb +58 -0
  91. data/lib/ably/rest/middleware/parse_json.rb +27 -0
  92. data/lib/ably/rest/middleware/parse_message_pack.rb +43 -0
  93. data/lib/ably/rest/presence.rb +113 -0
  94. data/lib/ably/rest/push/admin.rb +58 -0
  95. data/lib/ably/rest/push/channel_subscriptions.rb +121 -0
  96. data/lib/ably/rest/push/device_registrations.rb +114 -0
  97. data/lib/ably/rest/push.rb +25 -0
  98. data/lib/ably/rest.rb +40 -0
  99. data/lib/ably/util/ably_extensions.rb +29 -0
  100. data/lib/ably/util/crypto.rb +134 -0
  101. data/lib/ably/util/pub_sub.rb +45 -0
  102. data/lib/ably/util/safe_deferrable.rb +44 -0
  103. data/lib/ably/version.rb +7 -0
  104. data/lib/ably.rb +16 -0
  105. metadata +497 -0
@@ -0,0 +1,107 @@
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
+ #
63
+ # @spec TS5a, TS5b
64
+ #
65
+ class MessageCount < StatsStruct
66
+ coerce_attributes :count, :data, into: IntegerDefaultZero
67
+ end
68
+
69
+ # RequestCount contains aggregate counts for requests made
70
+ #
71
+ # @spec TS8a, TS8b, TS8c
72
+ #
73
+ class RequestCount < StatsStruct
74
+ coerce_attributes :succeeded, :failed, :refused, into: IntegerDefaultZero
75
+ end
76
+
77
+ # ResourceCount contains aggregate data for usage of a resource in a specific scope
78
+ #
79
+ class ResourceCount < StatsStruct
80
+ coerce_attributes :opened, :peak, :mean, :min, :refused, into: IntegerDefaultZero
81
+ end
82
+
83
+ # ConnectionTypes contains a breakdown of summary stats data for different (TLS vs non-TLS) connection types
84
+ #
85
+ # @spec TS4a, TS4b, TS4c
86
+ #
87
+ class ConnectionTypes < StatsStruct
88
+ coerce_attributes :tls, :plain, :all, into: ResourceCount
89
+ end
90
+
91
+ # MessageTypes contains a breakdown of summary stats data for different (message vs presence) message types
92
+ #
93
+ # @spec TS6a, TS6b, TS6c
94
+ #
95
+ class MessageTypes < StatsStruct
96
+ coerce_attributes :messages, :presence, :all, into: MessageCount
97
+ end
98
+
99
+ # MessageTraffic contains a breakdown of summary stats data for traffic over various transport types
100
+ #
101
+ # @spec TS7a, TS7b, TS7c, TS7d
102
+ #
103
+ class MessageTraffic < StatsStruct
104
+ coerce_attributes :realtime, :rest, :webhook, :all, into: MessageTypes
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,148 @@
1
+ module Ably::Models
2
+ # Convert token details argument to a {TokenDetails} object
3
+ #
4
+ # @param attributes (see #initialize)
5
+ #
6
+ # @return [TokenDetails]
7
+ #
8
+ def self.TokenDetails(attributes)
9
+ case attributes
10
+ when TokenDetails
11
+ return attributes
12
+ else
13
+ TokenDetails.new(attributes)
14
+ end
15
+ end
16
+
17
+ # Contains an Ably Token and its associated metadata.
18
+ #
19
+ class TokenDetails
20
+ include Ably::Modules::ModelCommon
21
+
22
+ # Buffer in seconds before a token is considered unusable
23
+ # For example, if buffer is 10s, the token can no longer be used for new requests 9s before it expires
24
+ TOKEN_EXPIRY_BUFFER = 15
25
+
26
+ # @param attributes
27
+ # @option attributes [String] :token token used to authenticate requests
28
+ # @option attributes [String] :key_name API key name used to create this token
29
+ # @option attributes [Time,Integer] :issued Time the token was issued as Time or Integer in milliseconds
30
+ # @option attributes [Time,Integer] :expires Time the token expires as Time or Integer in milliseconds
31
+ # @option attributes [String] :capability JSON stringified capabilities assigned to this token
32
+ # @option attributes [String] :client_id client ID assigned to this token
33
+ #
34
+ def initialize(attributes = {})
35
+ @hash_object = IdiomaticRubyWrapper(attributes.clone)
36
+
37
+ %w(issued expires).map(&:to_sym).each do |time_attribute|
38
+ if self.attributes[time_attribute].kind_of?(Time)
39
+ self.attributes[time_attribute] = (self.attributes[time_attribute].to_f * 1000).round
40
+ end
41
+ end
42
+
43
+ self.attributes.freeze
44
+ end
45
+
46
+ # The Ably Token itself. A typical Ably Token string appears with the form xVLyHw.A-pwh7wicf3afTfgiw4k2Ku33kcnSA7z6y8FjuYpe3QaNRTEo4.
47
+ #
48
+ # @spec TD2
49
+ #
50
+ # @return [String] Token used to authenticate requests
51
+ #
52
+ def token
53
+ attributes[:token]
54
+ end
55
+
56
+ # @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 +:+
57
+ #
58
+ def key_name
59
+ attributes[:key_name]
60
+ end
61
+
62
+ # The timestamp at which this token was issued as milliseconds since the Unix epoch.
63
+ # @spec TD4
64
+ # @return [Time] Time the token was issued
65
+ def issued
66
+ as_time_from_epoch(attributes[:issued], granularity: :ms, allow_nil: :true)
67
+ end
68
+
69
+ # The timestamp at which this token expires as milliseconds since the Unix epoch.
70
+ # @spec TD3
71
+ # @return [Time] Time the token expires
72
+ def expires
73
+ as_time_from_epoch(attributes[:expires], granularity: :ms, allow_nil: :true)
74
+ end
75
+
76
+ # The capabilities associated with this Ably Token. The capabilities value is a JSON-encoded representation of the
77
+ # resource paths and associated operations. Read more about capabilities in the capabilities docs.
78
+ # @spec TD5
79
+ # @return [Hash] Capabilities assigned to this token
80
+ def capability
81
+ if attributes.has_key?(:capability)
82
+ capability_val = attributes.fetch(:capability)
83
+ case capability_val
84
+ when Hash
85
+ capability_val
86
+ when Ably::Models::IdiomaticRubyWrapper
87
+ capability_val.as_json
88
+ else
89
+ JSON.parse(attributes.fetch(:capability))
90
+ end
91
+ end
92
+ end
93
+
94
+ # The client ID, if any, bound to this Ably Token. If a client ID is included, then the Ably Token authenticates its
95
+ # bearer as that client ID, and the Ably Token may only be used to perform operations on behalf of that client ID.
96
+ # The client is then considered to be an identified client.
97
+ # @spec TD6
98
+ # @return [String] Optional client ID assigned to this token
99
+ def client_id
100
+ attributes[:client_id]
101
+ end
102
+
103
+ # Returns true if token is expired or about to expire
104
+ # For tokens that have not got an explicit expires attribute expired? will always return true
105
+ #
106
+ # @param attributes [Hash]
107
+ # @option attributes [Time] :from Sets a current time from which token expires
108
+ #
109
+ # @return [Boolean]
110
+ def expired?(attributes = {})
111
+ return false if !expires
112
+
113
+ from = attributes[:from] || Time.now
114
+ expires < from + TOKEN_EXPIRY_BUFFER
115
+ end
116
+
117
+ # True if the TokenDetails was created from an opaque string i.e. no metadata exists for this token
118
+ # @return [Boolean]
119
+ # @api private
120
+ def from_token_string?
121
+ attributes.keys == [:token]
122
+ end
123
+
124
+ # @return [Hash] Access the token details Hash object ruby'fied to use symbolized keys
125
+ #
126
+ def attributes
127
+ @hash_object
128
+ end
129
+
130
+ def to_s
131
+ "<TokenDetails token=#{token} client_id=#{client_id} key_name=#{key_name} issued=#{issued} expires=#{expires} capability=#{capability} expired?=#{expired?}>"
132
+ end
133
+
134
+ # A static factory method to create a {Ably::Models::TokenDetails} object from a deserialized {Ably::Models::TokenDetails}-like
135
+ # object or a JSON stringified TokenDetails object. This method is provided to minimize bugs as a result of differing
136
+ # types by platform for fields such as timestamp or ttl. For example, in Ruby ttl in the {Ably::Models::TokenDetails}
137
+ # object is exposed in seconds as that is idiomatic for the language, yet when serialized to JSON using to_json it
138
+ # is automatically converted to the Ably standard which is milliseconds. By using the fromJson() method when constructing
139
+ # a {Ably::Models::TokenDetails} object, Ably ensures that all fields are consistently serialized and deserialized across platforms.
140
+ #
141
+ # @overload from_json(json_like_object)
142
+ # @spec TD7
143
+ # @param json_like_object [Hash, String] A deserialized TokenDetails-like object or a JSON stringified TokenDetails object.
144
+ #
145
+ # @return [Ably::Models::TokenDetails] An Ably authentication token.
146
+ #
147
+ end
148
+ end
@@ -0,0 +1,180 @@
1
+ module Ably::Models
2
+ # Convert token request argument to a {TokenRequest} object
3
+ #
4
+ # @param attributes (see #initialize)
5
+ #
6
+ # @return [TokenRequest]
7
+ #
8
+ def self.TokenRequest(attributes)
9
+ case attributes
10
+ when TokenRequest
11
+ return attributes
12
+ else
13
+ TokenRequest.new(attributes)
14
+ end
15
+ end
16
+
17
+
18
+ # Contains the properties of a request for a token to Ably.
19
+ # Tokens are generated using {Ably::Auth#requestToken}.
20
+ #
21
+ # Ruby {http://ruby-doc.org/core/Time.html Time} objects are supported in place of Ably ms since epoch time fields. However, if a numeric is provided
22
+ # it must always be expressed in milliseconds as the Ably API always uses milliseconds for time fields.
23
+ #
24
+ class TokenRequest
25
+ include Ably::Modules::ModelCommon
26
+
27
+ # @param attributes
28
+ # @option attributes [Integer] :ttl requested time to live for the token in milliseconds
29
+ # @option attributes [Time,Integer] :timestamp the timestamp of this request in milliseconds or as a {http://ruby-doc.org/core/Time.html Time}
30
+ # @option attributes [String] :key_name API key name of the key against which this request is made
31
+ # @option attributes [String] :capability JSON stringified capability of the token
32
+ # @option attributes [String] :client_id client ID to associate with this token
33
+ # @option attributes [String] :nonce an opaque nonce string of at least 16 characters
34
+ # @option attributes [String] :mac the Message Authentication Code for this request
35
+ #
36
+ def initialize(attributes = {})
37
+ @hash_object = IdiomaticRubyWrapper(attributes.clone)
38
+ if self.attributes[:timestamp].kind_of?(Time)
39
+ self.attributes[:timestamp] = (self.attributes[:timestamp].to_f * 1000).round
40
+ end
41
+ self.attributes.freeze
42
+ end
43
+
44
+ # The name of the key against which this request is made. The key name is public, whereas the key secret is private.
45
+ #
46
+ # @!attribute [r] key_name
47
+ #
48
+ # @spec TE2
49
+ #
50
+ # @return [String] API key name of the key against which this request is made. An API key is made up of an API key name and secret delimited by a +:+
51
+ #
52
+ def key_name
53
+ attributes.fetch(:key_name) { raise Ably::Exceptions::InvalidTokenRequest, 'Key name is missing' }
54
+ end
55
+
56
+ # Requested time to live for the Ably Token in milliseconds. If the Ably TokenRequest is successful, the TTL of the
57
+ # returned Ably Token is less than or equal to this value, depending on application settings and the attributes of
58
+ # the issuing key. The default is 60 minutes.
59
+ #
60
+ # @!attribute [r] ttl
61
+ #
62
+ # @spec TE4
63
+ #
64
+ # @return [Integer] requested time to live for the token in seconds. If the token request is successful,
65
+ # the TTL of the returned token will be less than or equal to this value depending on application
66
+ # settings and the attributes of the issuing key.
67
+ # TTL when sent to Ably is in milliseconds.
68
+ def ttl
69
+ attributes.fetch(:ttl) / 1000
70
+ end
71
+
72
+ # Capability of the requested Ably Token. If the Ably TokenRequest is successful, the capability of the returned
73
+ # Ably Token will be the intersection of this capability with the capability of the issuing key. The capabilities
74
+ # value is a JSON-encoded representation of the resource paths and associated operations. Read more about
75
+ # capabilities in the capabilities docs.
76
+ #
77
+ # @!attribute [r] capability
78
+ #
79
+ # @spec TE3
80
+ #
81
+ # @return [Hash] capability of the token. If the token request is successful,
82
+ # the capability of the returned token will be the intersection of
83
+ # this capability with the capability of the issuing key.
84
+ def capability
85
+ capability_val = attributes.fetch(:capability) { raise Ably::Exceptions::InvalidTokenRequest, 'Capability is missing' }
86
+
87
+ case capability_val
88
+ when Hash
89
+ capability_val
90
+ when Ably::Models::IdiomaticRubyWrapper
91
+ capability_val.as_json
92
+ else
93
+ JSON.parse(attributes.fetch(:capability))
94
+ end
95
+ end
96
+
97
+ # The client ID to associate with the requested Ably Token. When provided, the Ably Token may only be used to
98
+ # perform operations on behalf of that client ID.
99
+ #
100
+ # @!attribute [r] client_id
101
+ #
102
+ # @spec TE2
103
+ #
104
+ # @return [String] the client ID to associate with this token. The generated token
105
+ # may be used to authenticate as this clientId.
106
+ def client_id
107
+ attributes[:client_id]
108
+ end
109
+
110
+ # The timestamp of this request as milliseconds since the Unix epoch.
111
+ #
112
+ # @!attribute [r] timestamp
113
+ #
114
+ # @spec TE5
115
+ #
116
+ # @return [Time] the timestamp of this request.
117
+ # Timestamps, in conjunction with the nonce, are used to prevent
118
+ # token requests from being replayed.
119
+ # Timestamp when sent to Ably is in milliseconds.
120
+ def timestamp
121
+ timestamp_val = attributes.fetch(:timestamp) { raise Ably::Exceptions::InvalidTokenRequest, 'Timestamp is missing' }
122
+ as_time_from_epoch(timestamp_val, granularity: :ms)
123
+ end
124
+
125
+ # A cryptographically secure random string of at least 16 characters, used to ensure the TokenRequest cannot be reused.
126
+ #
127
+ # @!attribute [r] nonce
128
+ #
129
+ # @spec TE2
130
+ #
131
+ # @return [String] an opaque nonce string of at least 16 characters to ensure
132
+ # uniqueness of this request. Any subsequent request using the
133
+ # same nonce will be rejected.
134
+ def nonce
135
+ attributes.fetch(:nonce) { raise Ably::Exceptions::InvalidTokenRequest, 'Nonce is missing' }
136
+ end
137
+
138
+ # The Message Authentication Code for this request.
139
+ #
140
+ # @!attribute [r] mac
141
+ #
142
+ # @spec TE2
143
+ #
144
+ # @return [String] the Message Authentication Code for this request. See the
145
+ #
146
+ def mac
147
+ attributes.fetch(:mac) { raise Ably::Exceptions::InvalidTokenRequest, 'MAC is missing' }
148
+ end
149
+
150
+ # Requests that the token is always persisted
151
+ #
152
+ # @api private
153
+ #
154
+ def persisted
155
+ attributes[:persisted]
156
+ end
157
+
158
+ # @!attribute [r] attributes
159
+ #
160
+ # @return [Hash] the token request Hash object ruby'fied to use symbolized keys
161
+ #
162
+ def attributes
163
+ @hash_object
164
+ end
165
+
166
+ # A static factory method to create a TokenRequest object from a deserialized TokenRequest-like object or a JSON
167
+ # stringified TokenRequest object. This method is provided to minimize bugs as a result of differing types by platform
168
+ # for fields such as timestamp or ttl. For example, in Ruby ttl in the TokenRequest object is exposed in seconds as
169
+ # that is idiomatic for the language, yet when serialized to JSON using to_json it is automatically converted to
170
+ # the Ably standard which is milliseconds. By using the fromJson() method when constructing a TokenRequest object,
171
+ # Ably ensures that all fields are consistently serialized and deserialized across platforms.
172
+ #
173
+ # @overload from_json(json_like_object)
174
+ # @spec TE6
175
+ # @param json_like_object [Hash, String] A deserialized TokenRequest-like object or a JSON stringified TokenRequest object to create a TokenRequest.
176
+ #
177
+ # @return [Ably::Models::TokenRequest] An Ably token request object.
178
+ #
179
+ end
180
+ end
@@ -0,0 +1,26 @@
1
+ # Ably is the base namespace for the Ably {Ably::Realtime Realtime} & {Ably::Rest Rest} client libraries.
2
+ #
3
+ # Please refer to the {file:README.md Readme} on getting started.
4
+ #
5
+ # @see file:README.md README
6
+ module Ably
7
+ # Fallback hosts to use when a connection to rest/realtime.ably.io is not possible due to
8
+ # network failures either at the client, between the client and Ably, within an Ably data center, or at the IO domain registrar
9
+ # see https://ably.com/docs/client-lib-development-guide/features/#RSC15a
10
+ #
11
+ FALLBACK_DOMAIN = 'ably-realtime.com'.freeze
12
+ FALLBACK_IDS = %w(a b c d e).freeze
13
+
14
+ # Default production fallbacks a.ably-realtime.com ... e.ably-realtime.com
15
+ FALLBACK_HOSTS = FALLBACK_IDS.map { |host| "#{host}.#{FALLBACK_DOMAIN}".freeze }.freeze
16
+
17
+ # Custom environment default fallbacks {ENV}-a-fallback.ably-realtime.com ... {ENV}-a-fallback.ably-realtime.com
18
+ CUSTOM_ENVIRONMENT_FALLBACKS_SUFFIXES = FALLBACK_IDS.map do |host|
19
+ "-#{host}-fallback.#{FALLBACK_DOMAIN}".freeze
20
+ end.freeze
21
+
22
+ INTERNET_CHECK = {
23
+ url: '//internet-up.ably-realtime.com/is-the-internet-up.txt',
24
+ ok_text: 'yes'
25
+ }.freeze
26
+ end
@@ -0,0 +1,69 @@
1
+ require 'eventmachine'
2
+
3
+ module Ably::Modules
4
+ # Provides methods to convert synchronous operations into async operations through the use of
5
+ # {http://www.rubydoc.info/github/eventmachine/eventmachine/EventMachine#defer-class_method EventMachine#defer}.
6
+ # The async_wrap method can only be called from within an EventMachine reactor, and must be thread safe.
7
+ #
8
+ # @note using this AsyncWrapper should only be used for methods that are used less frequently and typically
9
+ # not run with levels of concurrency due to the limited number of threads available to EventMachine by default.
10
+ # This module requires that the method #logger is defined.
11
+ #
12
+ # @example
13
+ # class BlockingOperation
14
+ # include Aby::Modules::AsyncWrapper
15
+ #
16
+ # def operation(&success_callback)
17
+ # async_wrap(success_callback) do
18
+ # sleep 1
19
+ # 'slept'
20
+ # end
21
+ # end
22
+ # end
23
+ #
24
+ # blocking_object = BlockingOperation.new
25
+ # deferrable = blocking_object.operation do |result|
26
+ # puts "Done with result: #{result}"
27
+ # end
28
+ # puts "Starting"
29
+ #
30
+ # # => 'Starting'
31
+ # # => 'Done with result: slept'
32
+ #
33
+ module AsyncWrapper
34
+ private
35
+
36
+ # Will yield the provided block in a new thread and return an {Ably::Util::SafeDeferrable}
37
+ #
38
+ # @yield [Object] operation block that is run in a thread
39
+ #
40
+ # @return [Ably::Util::SafeDeferrable]
41
+ #
42
+ def async_wrap(success_callback = nil, custom_error_handling = nil)
43
+ raise ArgumentError, 'Block required' unless block_given?
44
+
45
+ Ably::Util::SafeDeferrable.new(logger).tap do |deferrable|
46
+ deferrable.callback(&success_callback) if success_callback
47
+
48
+ operation_with_exception_handling = lambda do
49
+ begin
50
+ yield
51
+ rescue StandardError => err
52
+ if custom_error_handling
53
+ custom_error_handling.call err, deferrable
54
+ else
55
+ logger.error { "An exception in an AsyncWrapper block was caught. #{err.class}: #{err.message}\n#{err.backtrace.join("\n")}" }
56
+ deferrable.fail err
57
+ end
58
+ end
59
+ end
60
+
61
+ complete_callback = lambda do |result|
62
+ deferrable.succeed result
63
+ end
64
+
65
+ EventMachine.defer operation_with_exception_handling, complete_callback
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,105 @@
1
+ module Ably::Modules
2
+ # ChannelsCollection module provides common functionality to the Rest and Realtime Channels objects
3
+ # such as #get, #[], #fetch, and #release
4
+ module ChannelsCollection
5
+ include Enumerable
6
+
7
+ def initialize(client, channel_klass)
8
+ @client = client
9
+ @channel_klass = channel_klass
10
+ @channels = {}
11
+ end
12
+
13
+ # Return a Channel for the given name
14
+ #
15
+ # @param name [String] The name of the channel
16
+ # @param channel_options [Hash, Ably::Models::ChannelOptions] A hash of options or a {Ably::Models::ChannelOptions}
17
+ #
18
+ # @return [Channel]
19
+ #
20
+ def get(name, channel_options = {})
21
+ if channels.has_key?(name)
22
+ channels[name].tap do |channel|
23
+ if channel_options && !channel_options.empty?
24
+ if channel.respond_to?(:need_reattach?) && channel.need_reattach?
25
+ raise_implicit_options_update
26
+ else
27
+ warn_implicit_options_update
28
+ channel.options = channel_options
29
+ end
30
+ end
31
+ end
32
+ else
33
+ channels[name] ||= channel_klass.new(client, name, channel_options)
34
+ end
35
+ end
36
+ alias_method :[], :get
37
+
38
+ # Return a Channel for the given name if it exists, else the block will be called.
39
+ # This method is intentionally similar to {http://ruby-doc.org/core-2.1.3/Hash.html#method-i-fetch Hash#fetch} providing a simple way to check if a channel exists or not without creating one
40
+ #
41
+ # @param name [String] The name of the channel
42
+ #
43
+ # @yield [options] (optional) if a missing_block is passed to this method and no channel exists matching the name, this block is called
44
+ # @yieldparam [String] name of the missing channel
45
+ #
46
+ # @return [Channel]
47
+ #
48
+ def fetch(name, &missing_block)
49
+ channels.fetch(name, &missing_block)
50
+ end
51
+
52
+ # Destroy the Channel and releases the associated resources.
53
+ #
54
+ # Releasing a Channel is not typically necessary as a channel consumes no resources other than the memory footprint of the
55
+ # Channel object. Explicitly release channels to free up resources if required
56
+ #
57
+ # @param name [String] The name of the channel
58
+ #
59
+ # @return [void]
60
+ #
61
+ def release(name)
62
+ channels.delete(name)
63
+ end
64
+
65
+ # @!attribute [r] length
66
+ # @return [Integer] number of channels created
67
+ def length
68
+ channels.length
69
+ end
70
+ alias_method :count, :length
71
+ alias_method :size, :length
72
+
73
+ # Method to allow {ChannelsCollection} to be {http://ruby-doc.org/core-2.1.3/Enumerable.html Enumerable}
74
+ def each(&block)
75
+ return to_enum(:each) unless block_given?
76
+ channels.values.each(&block)
77
+ end
78
+
79
+ private
80
+
81
+ def raise_implicit_options_update
82
+ raise ArgumentError, "You are trying to indirectly update channel options which will trigger reattachment of the channel. Please use Channel#set_options directly if you wish to continue"
83
+ end
84
+
85
+ def warn_implicit_options_update
86
+ logger.warn { "Channels#get: Using this method to update channel options is deprecated and may be removed in a future version of ably-ruby. Please use Channel#setOptions instead" }
87
+ end
88
+
89
+ def logger
90
+ client.logger
91
+ end
92
+
93
+ def client
94
+ @client
95
+ end
96
+
97
+ def channel_klass
98
+ @channel_klass
99
+ end
100
+
101
+ def channels
102
+ @channels
103
+ end
104
+ end
105
+ end