ably-rest 1.0.6 → 1.1.4.rc
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 +4 -4
- data/CHANGELOG.md +1 -1
- data/README.md +23 -15
- data/ably-rest.gemspec +6 -6
- data/lib/submodules/ably-ruby/.editorconfig +14 -0
- data/lib/submodules/ably-ruby/.travis.yml +10 -8
- data/lib/submodules/ably-ruby/CHANGELOG.md +75 -3
- data/lib/submodules/ably-ruby/LICENSE +1 -3
- data/lib/submodules/ably-ruby/README.md +12 -7
- data/lib/submodules/ably-ruby/Rakefile +32 -0
- data/lib/submodules/ably-ruby/SPEC.md +1277 -835
- data/lib/submodules/ably-ruby/ably.gemspec +15 -10
- data/lib/submodules/ably-ruby/lib/ably/auth.rb +30 -4
- data/lib/submodules/ably-ruby/lib/ably/exceptions.rb +10 -4
- data/lib/submodules/ably-ruby/lib/ably/logger.rb +7 -1
- data/lib/submodules/ably-ruby/lib/ably/models/channel_state_change.rb +1 -1
- data/lib/submodules/ably-ruby/lib/ably/models/connection_state_change.rb +1 -1
- data/lib/submodules/ably-ruby/lib/ably/models/device_details.rb +87 -0
- data/lib/submodules/ably-ruby/lib/ably/models/device_push_details.rb +86 -0
- data/lib/submodules/ably-ruby/lib/ably/models/error_info.rb +23 -2
- data/lib/submodules/ably-ruby/lib/ably/models/idiomatic_ruby_wrapper.rb +4 -4
- data/lib/submodules/ably-ruby/lib/ably/models/protocol_message.rb +32 -2
- data/lib/submodules/ably-ruby/lib/ably/models/push_channel_subscription.rb +89 -0
- data/lib/submodules/ably-ruby/lib/ably/modules/conversions.rb +1 -1
- data/lib/submodules/ably-ruby/lib/ably/modules/encodeable.rb +1 -1
- data/lib/submodules/ably-ruby/lib/ably/modules/exception_codes.rb +128 -0
- data/lib/submodules/ably-ruby/lib/ably/modules/model_common.rb +15 -2
- data/lib/submodules/ably-ruby/lib/ably/modules/state_machine.rb +2 -2
- data/lib/submodules/ably-ruby/lib/ably/realtime.rb +1 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/auth.rb +1 -1
- data/lib/submodules/ably-ruby/lib/ably/realtime/channel.rb +24 -102
- data/lib/submodules/ably-ruby/lib/ably/realtime/channel/channel_manager.rb +2 -6
- data/lib/submodules/ably-ruby/lib/ably/realtime/channel/channel_state_machine.rb +2 -2
- data/lib/submodules/ably-ruby/lib/ably/realtime/channel/publisher.rb +74 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/channel/push_channel.rb +62 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/client.rb +91 -3
- data/lib/submodules/ably-ruby/lib/ably/realtime/client/incoming_message_dispatcher.rb +6 -2
- data/lib/submodules/ably-ruby/lib/ably/realtime/client/outgoing_message_dispatcher.rb +1 -1
- data/lib/submodules/ably-ruby/lib/ably/realtime/connection.rb +34 -20
- data/lib/submodules/ably-ruby/lib/ably/realtime/connection/connection_manager.rb +25 -9
- data/lib/submodules/ably-ruby/lib/ably/realtime/connection/websocket_transport.rb +1 -1
- data/lib/submodules/ably-ruby/lib/ably/realtime/presence.rb +4 -4
- data/lib/submodules/ably-ruby/lib/ably/realtime/presence/members_map.rb +3 -3
- data/lib/submodules/ably-ruby/lib/ably/realtime/push.rb +40 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/push/admin.rb +61 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/push/channel_subscriptions.rb +108 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/push/device_registrations.rb +105 -0
- data/lib/submodules/ably-ruby/lib/ably/rest.rb +1 -0
- data/lib/submodules/ably-ruby/lib/ably/rest/channel.rb +53 -17
- data/lib/submodules/ably-ruby/lib/ably/rest/channel/push_channel.rb +62 -0
- data/lib/submodules/ably-ruby/lib/ably/rest/client.rb +162 -35
- data/lib/submodules/ably-ruby/lib/ably/rest/middleware/fail_if_unsupported_mime_type.rb +4 -1
- data/lib/submodules/ably-ruby/lib/ably/rest/middleware/parse_message_pack.rb +17 -1
- data/lib/submodules/ably-ruby/lib/ably/rest/presence.rb +1 -0
- data/lib/submodules/ably-ruby/lib/ably/rest/push.rb +42 -0
- data/lib/submodules/ably-ruby/lib/ably/rest/push/admin.rb +54 -0
- data/lib/submodules/ably-ruby/lib/ably/rest/push/channel_subscriptions.rb +121 -0
- data/lib/submodules/ably-ruby/lib/ably/rest/push/device_registrations.rb +103 -0
- data/lib/submodules/ably-ruby/lib/ably/version.rb +7 -2
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/auth_spec.rb +245 -17
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/channel_history_spec.rb +26 -20
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/channel_spec.rb +177 -59
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/client_spec.rb +153 -0
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_failures_spec.rb +72 -6
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_spec.rb +129 -18
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/message_spec.rb +36 -34
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/presence_spec.rb +201 -167
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/push_admin_spec.rb +736 -0
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/push_spec.rb +27 -0
- data/lib/submodules/ably-ruby/spec/acceptance/rest/auth_spec.rb +41 -3
- data/lib/submodules/ably-ruby/spec/acceptance/rest/base_spec.rb +2 -2
- data/lib/submodules/ably-ruby/spec/acceptance/rest/channel_spec.rb +79 -4
- data/lib/submodules/ably-ruby/spec/acceptance/rest/channels_spec.rb +6 -0
- data/lib/submodules/ably-ruby/spec/acceptance/rest/client_spec.rb +129 -10
- data/lib/submodules/ably-ruby/spec/acceptance/rest/message_spec.rb +158 -6
- data/lib/submodules/ably-ruby/spec/acceptance/rest/push_admin_spec.rb +952 -0
- data/lib/submodules/ably-ruby/spec/acceptance/rest/push_spec.rb +25 -0
- data/lib/submodules/ably-ruby/spec/acceptance/rest/time_spec.rb +1 -1
- data/lib/submodules/ably-ruby/spec/run_parallel_tests +33 -0
- data/lib/submodules/ably-ruby/spec/spec_helper.rb +1 -1
- data/lib/submodules/ably-ruby/spec/support/debug_failure_helper.rb +9 -5
- data/lib/submodules/ably-ruby/spec/support/test_app.rb +2 -2
- data/lib/submodules/ably-ruby/spec/unit/logger_spec.rb +10 -3
- data/lib/submodules/ably-ruby/spec/unit/models/device_details_spec.rb +102 -0
- data/lib/submodules/ably-ruby/spec/unit/models/device_push_details_spec.rb +101 -0
- data/lib/submodules/ably-ruby/spec/unit/models/error_info_spec.rb +51 -3
- data/lib/submodules/ably-ruby/spec/unit/models/message_spec.rb +17 -2
- data/lib/submodules/ably-ruby/spec/unit/models/presence_message_spec.rb +1 -1
- data/lib/submodules/ably-ruby/spec/unit/models/push_channel_subscription_spec.rb +86 -0
- data/lib/submodules/ably-ruby/spec/unit/modules/enum_spec.rb +1 -1
- data/lib/submodules/ably-ruby/spec/unit/realtime/client_spec.rb +13 -1
- data/lib/submodules/ably-ruby/spec/unit/realtime/connection_spec.rb +1 -1
- data/lib/submodules/ably-ruby/spec/unit/realtime/push_channel_spec.rb +36 -0
- data/lib/submodules/ably-ruby/spec/unit/rest/channel_spec.rb +8 -1
- data/lib/submodules/ably-ruby/spec/unit/rest/client_spec.rb +30 -0
- data/lib/submodules/ably-ruby/spec/unit/rest/push_channel_spec.rb +36 -0
- metadata +46 -21
@@ -198,12 +198,42 @@ module Ably::Models
|
|
198
198
|
|
199
199
|
# @api private
|
200
200
|
def has_backlog_flag?
|
201
|
-
flags & 2 == 2
|
201
|
+
flags & 2 == 2 # 2^1
|
202
202
|
end
|
203
203
|
|
204
204
|
# @api private
|
205
205
|
def has_channel_resumed_flag?
|
206
|
-
flags & 4 == 4
|
206
|
+
flags & 4 == 4 # 2^2
|
207
|
+
end
|
208
|
+
|
209
|
+
# @api private
|
210
|
+
def has_local_presence_flag?
|
211
|
+
flags & 8 == 8 # 2^3
|
212
|
+
end
|
213
|
+
|
214
|
+
# @api private
|
215
|
+
def has_transient_flag?
|
216
|
+
flags & 16 == 16 # 2^4
|
217
|
+
end
|
218
|
+
|
219
|
+
# @api private
|
220
|
+
def has_attach_presence_flag?
|
221
|
+
flags & 65536 == 65536 # 2^16
|
222
|
+
end
|
223
|
+
|
224
|
+
# @api private
|
225
|
+
def has_attach_publish_flag?
|
226
|
+
flags & 131072 == 131072 # 2^17
|
227
|
+
end
|
228
|
+
|
229
|
+
# @api private
|
230
|
+
def has_attach_subscribe_flag?
|
231
|
+
flags & 262144 == 262144 # 2^18
|
232
|
+
end
|
233
|
+
|
234
|
+
# @api private
|
235
|
+
def has_attach_presence_subscribe_flag?
|
236
|
+
flags & 524288 == 524288 # 2^19
|
207
237
|
end
|
208
238
|
|
209
239
|
def connection_details
|
@@ -0,0 +1,89 @@
|
|
1
|
+
module Ably::Modules
|
2
|
+
module Conversions
|
3
|
+
private
|
4
|
+
# Convert push_channel_subscription argument to a {Ably::Models::PushChannelSubscription} object
|
5
|
+
#
|
6
|
+
# @param push_channel_subscription [Ably::Models::PushChannelSubscription,Hash,nil] A device details object
|
7
|
+
#
|
8
|
+
# @return [Ably::Models::PushChannelSubscription]
|
9
|
+
def PushChannelSubscription(push_channel_subscription)
|
10
|
+
case push_channel_subscription
|
11
|
+
when Ably::Models::PushChannelSubscription
|
12
|
+
push_channel_subscription
|
13
|
+
else
|
14
|
+
Ably::Models::PushChannelSubscription.new(push_channel_subscription)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
module Ably::Models
|
21
|
+
# An object representing a devices details, used currently for push notifications
|
22
|
+
#
|
23
|
+
# @!attribute [r] channel
|
24
|
+
# @return [String] The realtime pub/sub channel this subscription is registered to
|
25
|
+
# @!attribute [r] client_id
|
26
|
+
# @return [String] Client ID that is assigned to one or more registered push devices
|
27
|
+
# @!attribute [r] device_id
|
28
|
+
# @return [String] Unique device identifier assigned to the push device
|
29
|
+
#
|
30
|
+
class PushChannelSubscription < Ably::Exceptions::BaseAblyException
|
31
|
+
include Ably::Modules::ModelCommon
|
32
|
+
|
33
|
+
# @param hash_object [Hash,nil] Device detail attributes
|
34
|
+
#a
|
35
|
+
def initialize(hash_object = {})
|
36
|
+
@raw_hash_object = hash_object || {}
|
37
|
+
@hash_object = IdiomaticRubyWrapper(hash_object)
|
38
|
+
|
39
|
+
if !attributes[:client_id] && !attributes[:device_id]
|
40
|
+
raise ArgumentError, 'Either client_id or device_id must be provided'
|
41
|
+
end
|
42
|
+
if attributes[:client_id] && attributes[:device_id]
|
43
|
+
raise ArgumentError, 'client_id and device_id cannot both be provided, they are mutually exclusive'
|
44
|
+
end
|
45
|
+
if !attributes[:channel]
|
46
|
+
raise ArgumentError, 'channel is required'
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Constructor for channel subscription by device ID
|
51
|
+
#
|
52
|
+
# @param channel [String] the realtime pub/sub channel this subscription is registered to
|
53
|
+
# @param device_id [String] Unique device identifier assigned to the push device
|
54
|
+
#
|
55
|
+
# @return [PushChannelSubscription]
|
56
|
+
#
|
57
|
+
def self.for_device(channel, device_id)
|
58
|
+
PushChannelSubscription.new(channel: channel, device_id: device_id)
|
59
|
+
end
|
60
|
+
|
61
|
+
# Constructor for channel subscription by client ID
|
62
|
+
#
|
63
|
+
# @param channel [String] the realtime pub/sub channel this subscription is registered to
|
64
|
+
# @param client_id [String] Client ID that is assigned to one or more registered push devices
|
65
|
+
#
|
66
|
+
# @return [PushChannelSubscription]
|
67
|
+
#
|
68
|
+
def self.for_client_id(channel, client_id)
|
69
|
+
PushChannelSubscription.new(channel: channel, client_id: client_id)
|
70
|
+
end
|
71
|
+
|
72
|
+
%w(channel client_id device_id).each do |attribute|
|
73
|
+
define_method attribute do
|
74
|
+
attributes[attribute.to_sym]
|
75
|
+
end
|
76
|
+
|
77
|
+
define_method "#{attribute}=" do |val|
|
78
|
+
unless val.nil? || val.kind_of?(String)
|
79
|
+
raise ArgumentError, "#{attribute} must be nil or a string value"
|
80
|
+
end
|
81
|
+
attributes[attribute.to_sym] = val
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def attributes
|
86
|
+
@hash_object
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -113,7 +113,7 @@ module Ably::Modules
|
|
113
113
|
payload.kind_of?(Array) ||
|
114
114
|
payload.nil?
|
115
115
|
|
116
|
-
raise Ably::Exceptions::UnsupportedDataType.new('Invalid data payload', 400,
|
116
|
+
raise Ably::Exceptions::UnsupportedDataType.new('Invalid data payload', 400, Ably::Exceptions::Codes::INVALID_MESSAGE_DATA_OR_ENCODING)
|
117
117
|
end
|
118
118
|
end
|
119
119
|
end
|
@@ -27,7 +27,7 @@ module Ably::Modules
|
|
27
27
|
end
|
28
28
|
|
29
29
|
# Return an Array of Message or Presence objects from the encoded Array of JSON-like objects, using the optional channel options
|
30
|
-
# @param
|
30
|
+
# @param message_object_array [Array<Hash>] Array of JSON-like objects with encoded messages
|
31
31
|
# @param channel_options [Hash] Channel options, currently reserved for Encryption options
|
32
32
|
# @return [Array<Message,Presence>]
|
33
33
|
def from_encoded_array(message_object_array, channel_options = {})
|
@@ -0,0 +1,128 @@
|
|
1
|
+
# This file is generated by running `rake :generate_error_codes`
|
2
|
+
# Do not manually modify this file
|
3
|
+
# Generated at: 2018-09-18 18:28:58 UTC
|
4
|
+
#
|
5
|
+
module Ably
|
6
|
+
module Exceptions
|
7
|
+
module Codes
|
8
|
+
NO_ERROR = 10000
|
9
|
+
BAD_REQUEST = 40000
|
10
|
+
INVALID_REQUEST_BODY = 40001
|
11
|
+
INVALID_PARAMETER_NAME = 40002
|
12
|
+
INVALID_PARAMETER_VALUE = 40003
|
13
|
+
INVALID_HEADER = 40004
|
14
|
+
INVALID_CREDENTIAL = 40005
|
15
|
+
INVALID_CONNECTION_ID = 40006
|
16
|
+
INVALID_MESSAGE_ID = 40007
|
17
|
+
INVALID_CONTENT_LENGTH = 40008
|
18
|
+
MAXIMUM_MESSAGE_LENGTH_EXCEEDED = 40009
|
19
|
+
INVALID_CHANNEL_NAME = 40010
|
20
|
+
STALE_RING_STATE = 40011
|
21
|
+
INVALID_CLIENT_ID = 40012
|
22
|
+
INVALID_MESSAGE_DATA_OR_ENCODING = 40013
|
23
|
+
RESOURCE_DISPOSED = 40014
|
24
|
+
INVALID_DEVICE_ID = 40015
|
25
|
+
BATCH_ERROR = 40020
|
26
|
+
INVALID_PUBLISH_REQUEST_UNSPECIFIED = 40030
|
27
|
+
INVALID_PUBLISH_REQUEST_INVALID_CLIENTSPECIFIED_ID = 40031
|
28
|
+
UNAUTHORIZED = 40100
|
29
|
+
INVALID_CREDENTIALS = 40101
|
30
|
+
INCOMPATIBLE_CREDENTIALS = 40102
|
31
|
+
INVALID_USE_OF_BASIC_AUTH_OVER_NONTLS_TRANSPORT = 40103
|
32
|
+
TIMESTAMP_NOT_CURRENT = 40104
|
33
|
+
NONCE_VALUE_REPLAYED = 40105
|
34
|
+
UNABLE_TO_OBTAIN_CREDENTIALS_FROM_GIVEN_PARAMETERS = 40106
|
35
|
+
ACCOUNT_DISABLED = 40110
|
36
|
+
ACCOUNT_RESTRICTED_CONNECTION_LIMITS_EXCEEDED = 40111
|
37
|
+
ACCOUNT_BLOCKED_MESSAGE_LIMITS_EXCEEDED = 40112
|
38
|
+
ACCOUNT_BLOCKED = 40113
|
39
|
+
ACCOUNT_RESTRICTED_CHANNEL_LIMITS_EXCEEDED = 40114
|
40
|
+
APPLICATION_DISABLED = 40120
|
41
|
+
KEY_ERROR_UNSPECIFIED = 40130
|
42
|
+
KEY_REVOKED = 40131
|
43
|
+
KEY_EXPIRED = 40132
|
44
|
+
KEY_DISABLED = 40133
|
45
|
+
TOKEN_ERROR_UNSPECIFIED = 40140
|
46
|
+
TOKEN_REVOKED = 40141
|
47
|
+
TOKEN_EXPIRED = 40142
|
48
|
+
TOKEN_UNRECOGNISED = 40143
|
49
|
+
INVALID_JWT_FORMAT = 40144
|
50
|
+
INVALID_TOKEN_FORMAT = 40145
|
51
|
+
CONNECTION_BLOCKED_LIMITS_EXCEEDED = 40150
|
52
|
+
OPERATION_NOT_PERMITTED_WITH_PROVIDED_CAPABILITY = 40160
|
53
|
+
ERROR_FROM_CLIENT_TOKEN_CALLBACK = 40170
|
54
|
+
FORBIDDEN = 40300
|
55
|
+
ACCOUNT_DOES_NOT_PERMIT_TLS_CONNECTION = 40310
|
56
|
+
OPERATION_REQUIRES_TLS_CONNECTION = 40311
|
57
|
+
APPLICATION_REQUIRES_AUTHENTICATION = 40320
|
58
|
+
UNABLE_TO_ACTIVATE_ACCOUNT_DUE_TO_PLACEMENT_CONSTRAINT_UNSPECIFIED = 40330
|
59
|
+
UNABLE_TO_ACTIVATE_ACCOUNT_DUE_TO_PLACEMENT_CONSTRAINT_INCOMPATIBLE_ENVIRONMENT = 40331
|
60
|
+
UNABLE_TO_ACTIVATE_ACCOUNT_DUE_TO_PLACEMENT_CONSTRAINT_INCOMPATIBLE_SITE = 40332
|
61
|
+
NOT_FOUND = 40400
|
62
|
+
METHOD_NOT_ALLOWED = 40500
|
63
|
+
RATE_LIMIT_EXCEEDED_NONFATAL_REQUEST_REJECTED_UNSPECIFIED = 42910
|
64
|
+
MAX_PERCONNECTION_PUBLISH_RATE_LIMIT_EXCEEDED_NONFATAL_UNABLE_TO_PUBLISH_MESSAGE = 42911
|
65
|
+
RATE_LIMIT_EXCEEDED_FATAL = 42920
|
66
|
+
MAX_PERCONNECTION_PUBLISH_RATE_LIMIT_EXCEEDED_FATAL_CLOSING_CONNECTION = 42921
|
67
|
+
INTERNAL_ERROR = 50000
|
68
|
+
INTERNAL_CHANNEL_ERROR = 50001
|
69
|
+
INTERNAL_CONNECTION_ERROR = 50002
|
70
|
+
TIMEOUT_ERROR = 50003
|
71
|
+
REQUEST_FAILED_DUE_TO_OVERLOADED_INSTANCE = 50004
|
72
|
+
REACTOR_OPERATION_FAILED = 70000
|
73
|
+
REACTOR_OPERATION_FAILED_POST_OPERATION_FAILED = 70001
|
74
|
+
REACTOR_OPERATION_FAILED_POST_OPERATION_RETURNED_UNEXPECTED_CODE = 70002
|
75
|
+
REACTOR_OPERATION_FAILED_MAXIMUM_NUMBER_OF_CONCURRENT_INFLIGHT_REQUESTS_EXCEEDED = 70003
|
76
|
+
EXCHANGE_ERROR_UNSPECIFIED = 71000
|
77
|
+
FORCED_REATTACHMENT_DUE_TO_PERMISSIONS_CHANGE = 71001
|
78
|
+
EXCHANGE_PUBLISHER_ERROR_UNSPECIFIED = 71100
|
79
|
+
NO_SUCH_PUBLISHER = 71101
|
80
|
+
PUBLISHER_NOT_ENABLED_AS_AN_EXCHANGE_PUBLISHER = 71102
|
81
|
+
EXCHANGE_PRODUCT_ERROR_UNSPECIFIED = 71200
|
82
|
+
NO_SUCH_PRODUCT = 71201
|
83
|
+
PRODUCT_DISABLED = 71202
|
84
|
+
NO_SUCH_CHANNEL_IN_THIS_PRODUCT = 71203
|
85
|
+
EXCHANGE_SUBSCRIPTION_ERROR_UNSPECIFIED = 71300
|
86
|
+
SUBSCRIPTION_DISABLED = 71301
|
87
|
+
REQUESTER_HAS_NO_SUBSCRIPTION_TO_THIS_PRODUCT = 71302
|
88
|
+
CONNECTION_FAILED = 80000
|
89
|
+
CONNECTION_FAILED_NO_COMPATIBLE_TRANSPORT = 80001
|
90
|
+
CONNECTION_SUSPENDED = 80002
|
91
|
+
DISCONNECTED = 80003
|
92
|
+
ALREADY_CONNECTED = 80004
|
93
|
+
INVALID_CONNECTION_ID_REMOTE_NOT_FOUND = 80005
|
94
|
+
UNABLE_TO_RECOVER_CONNECTION_MESSAGES_EXPIRED = 80006
|
95
|
+
UNABLE_TO_RECOVER_CONNECTION_MESSAGE_LIMIT_EXCEEDED = 80007
|
96
|
+
UNABLE_TO_RECOVER_CONNECTION_CONNECTION_EXPIRED = 80008
|
97
|
+
CONNECTION_NOT_ESTABLISHED_NO_TRANSPORT_HANDLE = 80009
|
98
|
+
INVALID_OPERATION_INVALID_TRANSPORT_HANDLE = 80010
|
99
|
+
UNABLE_TO_RECOVER_CONNECTION_INCOMPATIBLE_AUTH_PARAMS = 80011
|
100
|
+
UNABLE_TO_RECOVER_CONNECTION_INVALID_OR_UNSPECIFIED_CONNECTION_SERIAL = 80012
|
101
|
+
PROTOCOL_ERROR = 80013
|
102
|
+
CONNECTION_TIMED_OUT = 80014
|
103
|
+
INCOMPATIBLE_CONNECTION_PARAMETERS = 80015
|
104
|
+
OPERATION_ON_SUPERSEDED_TRANSPORT = 80016
|
105
|
+
CONNECTION_CLOSED = 80017
|
106
|
+
INVALID_CONNECTION_ID_INVALID_FORMAT = 80018
|
107
|
+
CLIENT_CONFIGURED_AUTHENTICATION_PROVIDER_REQUEST_FAILED = 80019
|
108
|
+
CONTINUITY_LOSS_DUE_TO_MAXIMUM_SUBSCRIBE_MESSAGE_RATE_EXCEEDED = 80020
|
109
|
+
CLIENT_RESTRICTION_NOT_SATISFIED = 80030
|
110
|
+
CHANNEL_OPERATION_FAILED = 90000
|
111
|
+
CHANNEL_OPERATION_FAILED_INVALID_CHANNEL_STATE = 90001
|
112
|
+
CHANNEL_OPERATION_FAILED_EPOCH_EXPIRED_OR_NEVER_EXISTED = 90002
|
113
|
+
UNABLE_TO_RECOVER_CHANNEL_MESSAGES_EXPIRED = 90003
|
114
|
+
UNABLE_TO_RECOVER_CHANNEL_MESSAGE_LIMIT_EXCEEDED = 90004
|
115
|
+
UNABLE_TO_RECOVER_CHANNEL_NO_MATCHING_EPOCH = 90005
|
116
|
+
UNABLE_TO_RECOVER_CHANNEL_UNBOUNDED_REQUEST = 90006
|
117
|
+
CHANNEL_OPERATION_FAILED_NO_RESPONSE_FROM_SERVER = 90007
|
118
|
+
MAXIMUM_NUMBER_OF_CHANNELS_PER_CONNECTION_EXCEEDED = 90010
|
119
|
+
UNABLE_TO_ENTER_PRESENCE_CHANNEL_NO_CLIENTID = 91000
|
120
|
+
UNABLE_TO_ENTER_PRESENCE_CHANNEL_INVALID_CHANNEL_STATE = 91001
|
121
|
+
UNABLE_TO_LEAVE_PRESENCE_CHANNEL_THAT_IS_NOT_ENTERED = 91002
|
122
|
+
UNABLE_TO_ENTER_PRESENCE_CHANNEL_MAXIMUM_MEMBER_LIMIT_EXCEEDED = 91003
|
123
|
+
UNABLE_TO_AUTOMATICALLY_REENTER_PRESENCE_CHANNEL = 91004
|
124
|
+
PRESENCE_STATE_IS_OUT_OF_SYNC = 91005
|
125
|
+
MEMBER_IMPLICITLY_LEFT_PRESENCE_CHANNEL_CONNECTION_CLOSED = 91100
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
@@ -42,10 +42,23 @@ module Ably::Modules
|
|
42
42
|
attributes.hash
|
43
43
|
end
|
44
44
|
|
45
|
+
def to_s
|
46
|
+
representation = attributes.map do |key, val|
|
47
|
+
if val.nil?
|
48
|
+
nil
|
49
|
+
else
|
50
|
+
val_str = val.to_s
|
51
|
+
val_str = "#{val_str[0...80]}..." if val_str.length > 80
|
52
|
+
"#{key}=#{val_str}"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
"<#{self.class.name}: #{representation.compact.join(', ')}>"
|
56
|
+
end
|
57
|
+
|
45
58
|
module ClassMethods
|
46
59
|
# Return a new instance of this object using the provided JSON-like object or JSON string
|
47
|
-
# @param [Hash, String]
|
48
|
-
# @return a new instance
|
60
|
+
# @param json_like_object [Hash, String] JSON-like object or JSON string
|
61
|
+
# @return a new instance to this object
|
49
62
|
def from_json(json_like_object)
|
50
63
|
if json_like_object.kind_of?(String)
|
51
64
|
new(JSON.parse(json_like_object))
|
@@ -23,7 +23,7 @@ module Ably::Modules
|
|
23
23
|
def transition_state(state, *args)
|
24
24
|
unless result = transition_to(state.to_sym, *args)
|
25
25
|
exception = exception_for_state_change_to(state)
|
26
|
-
logger.fatal { "#{self.class}: #{exception.message}" }
|
26
|
+
logger.fatal { "#{self.class}: #{exception.message}\n#{caller[0..20].join("\n")}" }
|
27
27
|
end
|
28
28
|
result
|
29
29
|
end
|
@@ -41,7 +41,7 @@ module Ably::Modules
|
|
41
41
|
# @return [Ably::Exceptions::InvalidStateChange]
|
42
42
|
def exception_for_state_change_to(state)
|
43
43
|
error_message = "#{self.class}: Unable to transition from #{current_state} => #{state}"
|
44
|
-
Ably::Exceptions::InvalidStateChange.new(error_message, nil,
|
44
|
+
Ably::Exceptions::InvalidStateChange.new(error_message, nil, Ably::Exceptions::Codes::CHANNEL_OPERATION_FAILED_INVALID_CHANNEL_STATE)
|
45
45
|
end
|
46
46
|
|
47
47
|
module ClassMethods
|
@@ -239,7 +239,7 @@ module Ably
|
|
239
239
|
# Use base exception if it exists carrying forward the status codes
|
240
240
|
deferrable.fail Ably::Exceptions::AuthenticationFailed.new(error.message, nil, nil, error)
|
241
241
|
else
|
242
|
-
deferrable.fail Ably::Exceptions::AuthenticationFailed.new(error.message, 500,
|
242
|
+
deferrable.fail Ably::Exceptions::AuthenticationFailed.new(error.message, 500, Ably::Exceptions::Codes::CLIENT_CONFIGURED_AUTHENTICATION_PROVIDER_REQUEST_FAILED)
|
243
243
|
end
|
244
244
|
end
|
245
245
|
async_wrap(success_callback, fail_callback) do
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'ably/realtime/channel/publisher'
|
2
|
+
|
1
3
|
module Ably
|
2
4
|
module Realtime
|
3
5
|
# The Channel class represents a Channel belonging to this application.
|
@@ -32,6 +34,7 @@ module Ably
|
|
32
34
|
include Ably::Modules::EventMachineHelpers
|
33
35
|
include Ably::Modules::AsyncWrapper
|
34
36
|
include Ably::Modules::MessageEmitter
|
37
|
+
include Ably::Realtime::Channel::Publisher
|
35
38
|
extend Ably::Modules::Enum
|
36
39
|
|
37
40
|
# ChannelState
|
@@ -61,12 +64,17 @@ module Ably
|
|
61
64
|
|
62
65
|
# {Ably::Realtime::Client} associated with this channel
|
63
66
|
# @return [Ably::Realtime::Client]
|
67
|
+
# @api private
|
64
68
|
attr_reader :client
|
65
69
|
|
66
70
|
# Channel name
|
67
71
|
# @return [String]
|
68
72
|
attr_reader :name
|
69
73
|
|
74
|
+
# Push channel used for push notification
|
75
|
+
# @return [Ably::Realtime::Channel::PushChannel]
|
76
|
+
attr_reader :push
|
77
|
+
|
70
78
|
# Channel options configured for this channel, see {#initialize} for channel_options
|
71
79
|
# @return [Hash]
|
72
80
|
attr_reader :options
|
@@ -103,6 +111,7 @@ module Ably
|
|
103
111
|
@state_machine = ChannelStateMachine.new(self)
|
104
112
|
@state = STATE(state_machine.current_state)
|
105
113
|
@manager = ChannelManager.new(self, client.connection)
|
114
|
+
@push = PushChannel.new(self)
|
106
115
|
|
107
116
|
setup_event_handlers
|
108
117
|
setup_presence
|
@@ -116,7 +125,7 @@ module Ably
|
|
116
125
|
# @param data [String, ByteArray, nil] The message payload unless an Array of [Ably::Model::Message] objects passed in the first argument
|
117
126
|
# @param attributes [Hash, nil] Optional additional message attributes such as :client_id or :connection_id, applied when name attribute is nil or a string
|
118
127
|
#
|
119
|
-
# @yield [Ably::Models::Message,Array<Ably::Models::Message>] On success, will call the block with the {Ably::Models::Message} if a single message is
|
128
|
+
# @yield [Ably::Models::Message,Array<Ably::Models::Message>] On success, will call the block with the {Ably::Models::Message} if a single message is published, or an Array of {Ably::Models::Message} when multiple messages are published
|
120
129
|
# @return [Ably::Util::SafeDeferrable] Deferrable that supports both success (callback) and failure (errback) callbacks
|
121
130
|
#
|
122
131
|
# @example
|
@@ -146,13 +155,13 @@ module Ably
|
|
146
155
|
# end
|
147
156
|
#
|
148
157
|
def publish(name, data = nil, attributes = {}, &success_block)
|
149
|
-
if
|
158
|
+
if suspended? || failed?
|
150
159
|
error = Ably::Exceptions::ChannelInactive.new("Cannot publish messages on a channel in state #{state}")
|
151
160
|
return Ably::Util::SafeDeferrable.new_and_fail_immediately(logger, error)
|
152
161
|
end
|
153
162
|
|
154
163
|
if !connection.can_publish_messages?
|
155
|
-
error = Ably::Exceptions::MessageQueueingDisabled.new("Message cannot be published. Client is
|
164
|
+
error = Ably::Exceptions::MessageQueueingDisabled.new("Message cannot be published. Client is not allowed to queue messages when connection is in state #{connection.state}")
|
156
165
|
return Ably::Util::SafeDeferrable.new_and_fail_immediately(logger, error)
|
157
166
|
end
|
158
167
|
|
@@ -164,7 +173,12 @@ module Ably
|
|
164
173
|
[{ name: name, data: data }.merge(attributes)]
|
165
174
|
end
|
166
175
|
|
167
|
-
|
176
|
+
if messages.length > Realtime::Connection::MAX_PROTOCOL_MESSAGE_BATCH_SIZE
|
177
|
+
error = Ably::Exceptions::InvalidRequest.new("It is not possible to publish more than #{Realtime::Connection::MAX_PROTOCOL_MESSAGE_BATCH_SIZE} messages with a single publish request.")
|
178
|
+
return Ably::Util::SafeDeferrable.new_and_fail_immediately(logger, error)
|
179
|
+
end
|
180
|
+
|
181
|
+
enqueue_messages_on_connection(client, messages, channel_name, options).tap do |deferrable|
|
168
182
|
deferrable.callback(&success_block) if block_given?
|
169
183
|
end
|
170
184
|
end
|
@@ -321,12 +335,6 @@ module Ably
|
|
321
335
|
client.logger
|
322
336
|
end
|
323
337
|
|
324
|
-
# Internal queue used for messages published that cannot yet be enqueued on the connection
|
325
|
-
# @api private
|
326
|
-
def __queue__
|
327
|
-
@queue
|
328
|
-
end
|
329
|
-
|
330
338
|
# As we are using a state machine, do not allow change_state to be used
|
331
339
|
# #transition_state_machine must be used instead
|
332
340
|
private :change_state
|
@@ -339,98 +347,6 @@ module Ably
|
|
339
347
|
end
|
340
348
|
emit_message message.name, message
|
341
349
|
end
|
342
|
-
|
343
|
-
unsafe_on(STATE.Attached) do
|
344
|
-
process_queue
|
345
|
-
end
|
346
|
-
end
|
347
|
-
|
348
|
-
# Queue messages and process queue if channel is attached.
|
349
|
-
# If channel is not yet attached, attempt to attach it before the message queue is processed.
|
350
|
-
# @return [Ably::Util::SafeDeferrable]
|
351
|
-
def queue_messages(raw_messages)
|
352
|
-
messages = Array(raw_messages).map do |raw_msg|
|
353
|
-
create_message(raw_msg).tap do |message|
|
354
|
-
next if message.client_id.nil?
|
355
|
-
if message.client_id == '*'
|
356
|
-
raise Ably::Exceptions::IncompatibleClientId.new('Wildcard client_id is reserved and cannot be used when publishing messages')
|
357
|
-
end
|
358
|
-
if message.client_id && !message.client_id.kind_of?(String)
|
359
|
-
raise Ably::Exceptions::IncompatibleClientId.new('client_id must be a String when publishing messages')
|
360
|
-
end
|
361
|
-
unless client.auth.can_assume_client_id?(message.client_id)
|
362
|
-
raise Ably::Exceptions::IncompatibleClientId.new("Cannot publish with client_id '#{message.client_id}' as it is incompatible with the current configured client_id '#{client.client_id}'")
|
363
|
-
end
|
364
|
-
end
|
365
|
-
end
|
366
|
-
|
367
|
-
__queue__.push(*messages)
|
368
|
-
|
369
|
-
if attached?
|
370
|
-
process_queue
|
371
|
-
else
|
372
|
-
attach
|
373
|
-
end
|
374
|
-
|
375
|
-
if messages.count == 1
|
376
|
-
# A message is a Deferrable so, if publishing only one message, simply return that Deferrable
|
377
|
-
messages.first
|
378
|
-
else
|
379
|
-
deferrable_for_multiple_messages(messages)
|
380
|
-
end
|
381
|
-
end
|
382
|
-
|
383
|
-
# A deferrable object that calls the success callback once all messages are delivered
|
384
|
-
# If any message fails, the errback is called immediately
|
385
|
-
# Only one callback or errback is ever called i.e. if a group of messages all fail, only once
|
386
|
-
# errback will be invoked
|
387
|
-
def deferrable_for_multiple_messages(messages)
|
388
|
-
expected_deliveries = messages.count
|
389
|
-
actual_deliveries = 0
|
390
|
-
failed = false
|
391
|
-
|
392
|
-
Ably::Util::SafeDeferrable.new(logger).tap do |deferrable|
|
393
|
-
messages.each do |message|
|
394
|
-
message.callback do
|
395
|
-
next if failed
|
396
|
-
actual_deliveries += 1
|
397
|
-
deferrable.succeed messages if actual_deliveries == expected_deliveries
|
398
|
-
end
|
399
|
-
message.errback do |error|
|
400
|
-
next if failed
|
401
|
-
failed = true
|
402
|
-
deferrable.fail error, message
|
403
|
-
end
|
404
|
-
end
|
405
|
-
end
|
406
|
-
end
|
407
|
-
|
408
|
-
def messages_in_queue?
|
409
|
-
!__queue__.empty?
|
410
|
-
end
|
411
|
-
|
412
|
-
# Move messages from Channel Queue into Outgoing Connection Queue
|
413
|
-
def process_queue
|
414
|
-
condition = -> { attached? && messages_in_queue? }
|
415
|
-
non_blocking_loop_while(condition) do
|
416
|
-
send_messages_within_protocol_message __queue__.shift(MAX_PROTOCOL_MESSAGE_BATCH_SIZE)
|
417
|
-
end
|
418
|
-
end
|
419
|
-
|
420
|
-
def send_messages_within_protocol_message(messages)
|
421
|
-
connection.send_protocol_message(
|
422
|
-
action: Ably::Models::ProtocolMessage::ACTION.Message.to_i,
|
423
|
-
channel: name,
|
424
|
-
messages: messages
|
425
|
-
)
|
426
|
-
end
|
427
|
-
|
428
|
-
def create_message(message)
|
429
|
-
Ably::Models::Message(message.dup).tap do |msg|
|
430
|
-
msg.encode(client.encoders, options) do |encode_error, error_message|
|
431
|
-
client.logger.error error_message
|
432
|
-
end
|
433
|
-
end
|
434
350
|
end
|
435
351
|
|
436
352
|
def rest_channel
|
@@ -444,9 +360,15 @@ module Ably
|
|
444
360
|
def setup_presence
|
445
361
|
@presence ||= Presence.new(self)
|
446
362
|
end
|
363
|
+
|
364
|
+
# Alias useful for methods with a name argument
|
365
|
+
def channel_name
|
366
|
+
name
|
367
|
+
end
|
447
368
|
end
|
448
369
|
end
|
449
370
|
end
|
450
371
|
|
451
372
|
require 'ably/realtime/channel/channel_manager'
|
452
373
|
require 'ably/realtime/channel/channel_state_machine'
|
374
|
+
require 'ably/realtime/channel/push_channel'
|