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.
Files changed (97) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1 -1
  3. data/README.md +23 -15
  4. data/ably-rest.gemspec +6 -6
  5. data/lib/submodules/ably-ruby/.editorconfig +14 -0
  6. data/lib/submodules/ably-ruby/.travis.yml +10 -8
  7. data/lib/submodules/ably-ruby/CHANGELOG.md +75 -3
  8. data/lib/submodules/ably-ruby/LICENSE +1 -3
  9. data/lib/submodules/ably-ruby/README.md +12 -7
  10. data/lib/submodules/ably-ruby/Rakefile +32 -0
  11. data/lib/submodules/ably-ruby/SPEC.md +1277 -835
  12. data/lib/submodules/ably-ruby/ably.gemspec +15 -10
  13. data/lib/submodules/ably-ruby/lib/ably/auth.rb +30 -4
  14. data/lib/submodules/ably-ruby/lib/ably/exceptions.rb +10 -4
  15. data/lib/submodules/ably-ruby/lib/ably/logger.rb +7 -1
  16. data/lib/submodules/ably-ruby/lib/ably/models/channel_state_change.rb +1 -1
  17. data/lib/submodules/ably-ruby/lib/ably/models/connection_state_change.rb +1 -1
  18. data/lib/submodules/ably-ruby/lib/ably/models/device_details.rb +87 -0
  19. data/lib/submodules/ably-ruby/lib/ably/models/device_push_details.rb +86 -0
  20. data/lib/submodules/ably-ruby/lib/ably/models/error_info.rb +23 -2
  21. data/lib/submodules/ably-ruby/lib/ably/models/idiomatic_ruby_wrapper.rb +4 -4
  22. data/lib/submodules/ably-ruby/lib/ably/models/protocol_message.rb +32 -2
  23. data/lib/submodules/ably-ruby/lib/ably/models/push_channel_subscription.rb +89 -0
  24. data/lib/submodules/ably-ruby/lib/ably/modules/conversions.rb +1 -1
  25. data/lib/submodules/ably-ruby/lib/ably/modules/encodeable.rb +1 -1
  26. data/lib/submodules/ably-ruby/lib/ably/modules/exception_codes.rb +128 -0
  27. data/lib/submodules/ably-ruby/lib/ably/modules/model_common.rb +15 -2
  28. data/lib/submodules/ably-ruby/lib/ably/modules/state_machine.rb +2 -2
  29. data/lib/submodules/ably-ruby/lib/ably/realtime.rb +1 -0
  30. data/lib/submodules/ably-ruby/lib/ably/realtime/auth.rb +1 -1
  31. data/lib/submodules/ably-ruby/lib/ably/realtime/channel.rb +24 -102
  32. data/lib/submodules/ably-ruby/lib/ably/realtime/channel/channel_manager.rb +2 -6
  33. data/lib/submodules/ably-ruby/lib/ably/realtime/channel/channel_state_machine.rb +2 -2
  34. data/lib/submodules/ably-ruby/lib/ably/realtime/channel/publisher.rb +74 -0
  35. data/lib/submodules/ably-ruby/lib/ably/realtime/channel/push_channel.rb +62 -0
  36. data/lib/submodules/ably-ruby/lib/ably/realtime/client.rb +91 -3
  37. data/lib/submodules/ably-ruby/lib/ably/realtime/client/incoming_message_dispatcher.rb +6 -2
  38. data/lib/submodules/ably-ruby/lib/ably/realtime/client/outgoing_message_dispatcher.rb +1 -1
  39. data/lib/submodules/ably-ruby/lib/ably/realtime/connection.rb +34 -20
  40. data/lib/submodules/ably-ruby/lib/ably/realtime/connection/connection_manager.rb +25 -9
  41. data/lib/submodules/ably-ruby/lib/ably/realtime/connection/websocket_transport.rb +1 -1
  42. data/lib/submodules/ably-ruby/lib/ably/realtime/presence.rb +4 -4
  43. data/lib/submodules/ably-ruby/lib/ably/realtime/presence/members_map.rb +3 -3
  44. data/lib/submodules/ably-ruby/lib/ably/realtime/push.rb +40 -0
  45. data/lib/submodules/ably-ruby/lib/ably/realtime/push/admin.rb +61 -0
  46. data/lib/submodules/ably-ruby/lib/ably/realtime/push/channel_subscriptions.rb +108 -0
  47. data/lib/submodules/ably-ruby/lib/ably/realtime/push/device_registrations.rb +105 -0
  48. data/lib/submodules/ably-ruby/lib/ably/rest.rb +1 -0
  49. data/lib/submodules/ably-ruby/lib/ably/rest/channel.rb +53 -17
  50. data/lib/submodules/ably-ruby/lib/ably/rest/channel/push_channel.rb +62 -0
  51. data/lib/submodules/ably-ruby/lib/ably/rest/client.rb +162 -35
  52. data/lib/submodules/ably-ruby/lib/ably/rest/middleware/fail_if_unsupported_mime_type.rb +4 -1
  53. data/lib/submodules/ably-ruby/lib/ably/rest/middleware/parse_message_pack.rb +17 -1
  54. data/lib/submodules/ably-ruby/lib/ably/rest/presence.rb +1 -0
  55. data/lib/submodules/ably-ruby/lib/ably/rest/push.rb +42 -0
  56. data/lib/submodules/ably-ruby/lib/ably/rest/push/admin.rb +54 -0
  57. data/lib/submodules/ably-ruby/lib/ably/rest/push/channel_subscriptions.rb +121 -0
  58. data/lib/submodules/ably-ruby/lib/ably/rest/push/device_registrations.rb +103 -0
  59. data/lib/submodules/ably-ruby/lib/ably/version.rb +7 -2
  60. data/lib/submodules/ably-ruby/spec/acceptance/realtime/auth_spec.rb +245 -17
  61. data/lib/submodules/ably-ruby/spec/acceptance/realtime/channel_history_spec.rb +26 -20
  62. data/lib/submodules/ably-ruby/spec/acceptance/realtime/channel_spec.rb +177 -59
  63. data/lib/submodules/ably-ruby/spec/acceptance/realtime/client_spec.rb +153 -0
  64. data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_failures_spec.rb +72 -6
  65. data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_spec.rb +129 -18
  66. data/lib/submodules/ably-ruby/spec/acceptance/realtime/message_spec.rb +36 -34
  67. data/lib/submodules/ably-ruby/spec/acceptance/realtime/presence_spec.rb +201 -167
  68. data/lib/submodules/ably-ruby/spec/acceptance/realtime/push_admin_spec.rb +736 -0
  69. data/lib/submodules/ably-ruby/spec/acceptance/realtime/push_spec.rb +27 -0
  70. data/lib/submodules/ably-ruby/spec/acceptance/rest/auth_spec.rb +41 -3
  71. data/lib/submodules/ably-ruby/spec/acceptance/rest/base_spec.rb +2 -2
  72. data/lib/submodules/ably-ruby/spec/acceptance/rest/channel_spec.rb +79 -4
  73. data/lib/submodules/ably-ruby/spec/acceptance/rest/channels_spec.rb +6 -0
  74. data/lib/submodules/ably-ruby/spec/acceptance/rest/client_spec.rb +129 -10
  75. data/lib/submodules/ably-ruby/spec/acceptance/rest/message_spec.rb +158 -6
  76. data/lib/submodules/ably-ruby/spec/acceptance/rest/push_admin_spec.rb +952 -0
  77. data/lib/submodules/ably-ruby/spec/acceptance/rest/push_spec.rb +25 -0
  78. data/lib/submodules/ably-ruby/spec/acceptance/rest/time_spec.rb +1 -1
  79. data/lib/submodules/ably-ruby/spec/run_parallel_tests +33 -0
  80. data/lib/submodules/ably-ruby/spec/spec_helper.rb +1 -1
  81. data/lib/submodules/ably-ruby/spec/support/debug_failure_helper.rb +9 -5
  82. data/lib/submodules/ably-ruby/spec/support/test_app.rb +2 -2
  83. data/lib/submodules/ably-ruby/spec/unit/logger_spec.rb +10 -3
  84. data/lib/submodules/ably-ruby/spec/unit/models/device_details_spec.rb +102 -0
  85. data/lib/submodules/ably-ruby/spec/unit/models/device_push_details_spec.rb +101 -0
  86. data/lib/submodules/ably-ruby/spec/unit/models/error_info_spec.rb +51 -3
  87. data/lib/submodules/ably-ruby/spec/unit/models/message_spec.rb +17 -2
  88. data/lib/submodules/ably-ruby/spec/unit/models/presence_message_spec.rb +1 -1
  89. data/lib/submodules/ably-ruby/spec/unit/models/push_channel_subscription_spec.rb +86 -0
  90. data/lib/submodules/ably-ruby/spec/unit/modules/enum_spec.rb +1 -1
  91. data/lib/submodules/ably-ruby/spec/unit/realtime/client_spec.rb +13 -1
  92. data/lib/submodules/ably-ruby/spec/unit/realtime/connection_spec.rb +1 -1
  93. data/lib/submodules/ably-ruby/spec/unit/realtime/push_channel_spec.rb +36 -0
  94. data/lib/submodules/ably-ruby/spec/unit/rest/channel_spec.rb +8 -1
  95. data/lib/submodules/ably-ruby/spec/unit/rest/client_spec.rb +30 -0
  96. data/lib/submodules/ably-ruby/spec/unit/rest/push_channel_spec.rb +36 -0
  97. 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, 40011)
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 message_objects [Array<Hash>] Array of JSON-like objects with encoded messages
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] JSON-like object or JSON string
48
- # @return a new instance o this object
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, 80020)
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
@@ -9,6 +9,7 @@ require 'ably/realtime/channel'
9
9
  require 'ably/realtime/channels'
10
10
  require 'ably/realtime/client'
11
11
  require 'ably/realtime/connection'
12
+ require 'ably/realtime/push'
12
13
  require 'ably/realtime/presence'
13
14
 
14
15
  require 'ably/models/message_encoders/base'
@@ -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, 80019)
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 publishde, or an Array of {Ably::Models::Message} when multiple messages are published
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 detached? || detaching? || failed?
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 configured to disallow queueing of messages and connection is currently #{connection.state}")
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
- queue_messages(messages).tap do |deferrable|
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'