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,105 @@
1
+ module Ably::Realtime
2
+ class Push
3
+ # Manage device registrations for push notifications
4
+ class DeviceRegistrations
5
+ include Ably::Modules::Conversions
6
+ include Ably::Modules::AsyncWrapper
7
+
8
+ # @api private
9
+ attr_reader :client
10
+
11
+ # @api private
12
+ attr_reader :admin
13
+
14
+ def initialize(admin)
15
+ @admin = admin
16
+ @client = admin.client
17
+ end
18
+
19
+ # (see Ably::Rest::Push::DeviceRegistrations#get)
20
+ #
21
+ # @yield Block is invoked when request succeeds
22
+ # @return [Ably::Util::SafeDeferrable]
23
+ #
24
+ def get(device_id, &callback)
25
+ device_id = device_id.id if device_id.kind_of?(Ably::Models::DeviceDetails)
26
+ raise ArgumentError, "device_id must be a string or DeviceDetails object" unless device_id.kind_of?(String)
27
+
28
+ async_wrap(callback) do
29
+ rest_device_registrations.get(device_id)
30
+ end
31
+ end
32
+
33
+ # (see Ably::Rest::Push::DeviceRegistrations#list)
34
+ #
35
+ # @yield Block is invoked when request succeeds
36
+ # @return [Ably::Util::SafeDeferrable]
37
+ #
38
+ def list(params = {}, &callback)
39
+ params = {} if params.nil?
40
+ raise ArgumentError, "params must be a Hash" unless params.kind_of?(Hash)
41
+ raise ArgumentError, "device_id filter cannot be specified alongside a client_id filter. Use one or the other" if params[:client_id] && params[:device_id]
42
+
43
+ async_wrap(callback) do
44
+ rest_device_registrations.list(params.merge(async_blocking_operations: true))
45
+ end
46
+ end
47
+
48
+ # (see Ably::Rest::Push::DeviceRegistrations#save)
49
+ #
50
+ # @yield Block is invoked when request succeeds
51
+ # @return [Ably::Util::SafeDeferrable]
52
+ #
53
+ def save(device, &callback)
54
+ device_details = DeviceDetails(device)
55
+ raise ArgumentError, "Device ID is required yet is empty" if device_details.id.nil? || device_details == ''
56
+
57
+ async_wrap(callback) do
58
+ rest_device_registrations.save(device_details)
59
+ end
60
+ end
61
+
62
+ # (see Ably::Rest::Push::DeviceRegistrations#remove)
63
+ #
64
+ # @yield Block is invoked when request succeeds
65
+ # @return [Ably::Util::SafeDeferrable]
66
+ #
67
+ def remove(device_id, &callback)
68
+ device_id = device_id.id if device_id.kind_of?(Ably::Models::DeviceDetails)
69
+ raise ArgumentError, "device_id must be a string or DeviceDetails object" unless device_id.kind_of?(String)
70
+
71
+ async_wrap(callback) do
72
+ rest_device_registrations.remove(device_id)
73
+ end
74
+ end
75
+
76
+ # (see Ably::Rest::Push::DeviceRegistrations#remove_where)
77
+ #
78
+ # @yield Block is invoked when request succeeds
79
+ # @return [Ably::Util::SafeDeferrable]
80
+ #
81
+ def remove_where(params = {}, &callback)
82
+ filter = if params.kind_of?(Ably::Models::DeviceDetails)
83
+ { 'deviceId' => params.id }
84
+ else
85
+ raise ArgumentError, "params must be a Hash" unless params.kind_of?(Hash)
86
+ raise ArgumentError, "device_id filter cannot be specified alongside a client_id filter. Use one or the other" if params[:client_id] && params[:device_id]
87
+ IdiomaticRubyWrapper(params).as_json
88
+ end
89
+
90
+ async_wrap(callback) do
91
+ rest_device_registrations.remove_where(filter)
92
+ end
93
+ end
94
+
95
+ private
96
+ def rest_device_registrations
97
+ client.rest_client.push.admin.device_registrations
98
+ end
99
+
100
+ def logger
101
+ client.logger
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,25 @@
1
+ require 'ably/realtime/push/admin'
2
+
3
+ module Ably
4
+ module Realtime
5
+ # Class providing push notification functionality
6
+ class Push
7
+ # @private
8
+ attr_reader :client
9
+
10
+ def initialize(client)
11
+ @client = client
12
+ end
13
+
14
+ # A {Ably::Realtime::Push::Admin} object.
15
+ #
16
+ # @spec RSH1
17
+ #
18
+ # @return [Ably::Realtime::Push::Admin]
19
+ #
20
+ def admin
21
+ @admin ||= Admin.new(self)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,36 @@
1
+ require 'json'
2
+ # frozen_string_literal: true
3
+
4
+ module Ably
5
+ module Realtime
6
+ class RecoveryKeyContext
7
+ attr_reader :connection_key
8
+ attr_reader :msg_serial
9
+ attr_reader :channel_serials
10
+
11
+ def initialize(connection_key, msg_serial, channel_serials)
12
+ @connection_key = connection_key
13
+ @msg_serial = msg_serial
14
+ @channel_serials = channel_serials
15
+ if @channel_serials.nil?
16
+ @channel_serials = {}
17
+ end
18
+ end
19
+
20
+ def to_json
21
+ { 'connection_key' => @connection_key, 'msg_serial' => @msg_serial, 'channel_serials' => @channel_serials }.to_json
22
+ end
23
+
24
+ def self.from_json(obj, logger = nil)
25
+ begin
26
+ data = JSON.load obj
27
+ self.new data['connection_key'], data['msg_serial'], data['channel_serials']
28
+ rescue => e
29
+ logger.warn "unable to decode recovery key, found error #{e}" unless logger.nil?
30
+ return nil
31
+ end
32
+ end
33
+
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,60 @@
1
+ require 'eventmachine'
2
+ require 'websocket/driver'
3
+ require 'em-http-request'
4
+
5
+ require 'ably/modules/event_emitter'
6
+
7
+ require 'ably/realtime/auth'
8
+ require 'ably/realtime/channel'
9
+ require 'ably/realtime/channels'
10
+ require 'ably/realtime/client'
11
+ require 'ably/realtime/connection'
12
+ require 'ably/realtime/push'
13
+ require 'ably/realtime/presence'
14
+
15
+ require 'ably/models/message_encoders/base'
16
+
17
+ Dir.glob(File.expand_path("models/*.rb", File.dirname(__FILE__))).each do |file|
18
+ require file
19
+ end
20
+
21
+ Dir.glob(File.expand_path("realtime/models/*.rb", File.dirname(__FILE__))).each do |file|
22
+ require file
23
+ end
24
+
25
+ require 'ably/models/message_encoders/base'
26
+
27
+ require 'ably/realtime/client/incoming_message_dispatcher'
28
+ require 'ably/realtime/client/outgoing_message_dispatcher'
29
+
30
+ module Ably
31
+ # Realtime provides the top-level class to be instanced for the Ably Realtime library
32
+ #
33
+ # @example
34
+ # client = Ably::Realtime.new("xxxxx")
35
+ # channel = client.channel("test")
36
+ # channel.subscribe do |message|
37
+ # message[:name] #=> "greeting"
38
+ # end
39
+ # channel.publish "greeting", "data"
40
+ #
41
+ module Realtime
42
+ # Convenience method providing an alias to {Ably::Realtime::Client} constructor.
43
+ #
44
+ # @param (see Ably::Realtime::Client#initialize)
45
+ # @option options (see Ably::Realtime::Client#initialize)
46
+ #
47
+ # @return [Ably::Realtime::Client]
48
+ #
49
+ # @example
50
+ # # create a new client authenticating with basic auth
51
+ # client = Ably::Realtime.new('key.id:secret')
52
+ #
53
+ # # create a new client authenticating with basic auth and a client_id
54
+ # client = Ably::Realtime.new(key: 'key.id:secret', client_id: 'john')
55
+ #
56
+ def self.new(options)
57
+ Ably::Realtime::Client.new(options)
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,59 @@
1
+ module Ably::Rest
2
+ class Channel
3
+ # A push channel used for push notifications
4
+ # Each PushChannel maps to exactly one Rest Channel
5
+ #
6
+ class PushChannel
7
+ attr_reader :channel
8
+
9
+ def initialize(channel)
10
+ raise ArgumentError, "Unsupported channel type '#{channel.class}'" unless channel.kind_of?(Ably::Rest::Channel)
11
+ @channel = channel
12
+ end
13
+
14
+ def to_s
15
+ "<PushChannel: name=#{channel.name}>"
16
+ end
17
+
18
+ # Subscribe local device for push notifications on this channel
19
+ #
20
+ # @note This is unsupported in the Ruby library
21
+ def subscribe_device(*args)
22
+ raise_unsupported
23
+ end
24
+
25
+ # Subscribe all devices registered to this client's authenticated client_id for push notifications on this channel
26
+ #
27
+ # @note This is unsupported in the Ruby library
28
+ def subscribe_client_id(*args)
29
+ raise_unsupported
30
+ end
31
+
32
+ # Unsubscribe local device for push notifications on this channel
33
+ #
34
+ # @note This is unsupported in the Ruby library
35
+ def unsubscribe_device(*args)
36
+ raise_unsupported
37
+ end
38
+
39
+ # Unsubscribe all devices registered to this client's authenticated client_id for push notifications on this channel
40
+ #
41
+ # @note This is unsupported in the Ruby library
42
+ def unsubscribe_client_id(*args)
43
+ raise_unsupported
44
+ end
45
+
46
+ # Get list of subscriptions on this channel for this device or authenticate client_id
47
+ #
48
+ # @note This is unsupported in the Ruby library
49
+ def get_subscriptions(*args)
50
+ raise_unsupported
51
+ end
52
+
53
+ private
54
+ def raise_unsupported
55
+ raise Ably::Exceptions::PushNotificationsNotSupported, 'This device does not support receiving or subscribing to push notifications. All PushChannel methods are unavailable'
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,194 @@
1
+ module Ably
2
+ module Rest
3
+ # Enables messages to be published and historic messages to be retrieved for a channel.
4
+ #
5
+ class Channel
6
+ include Ably::Modules::Conversions
7
+
8
+ # Ably client associated with this channel
9
+ # @return [Ably::Realtime::Client]
10
+ # @api private
11
+ attr_reader :client
12
+
13
+ # The channel name.
14
+ # @return [String]
15
+ attr_reader :name
16
+
17
+ attr_reader :options
18
+
19
+ # A {Ably::Rest::Channel::PushChannel} object
20
+ # @spec RSH4
21
+ # @return [Ably::Rest::Channel::PushChannel]
22
+ # @api private
23
+ attr_reader :push
24
+
25
+ IDEMPOTENT_LIBRARY_GENERATED_ID_LENGTH = 9 # See spec RSL1k1
26
+
27
+ # Initialize a new Channel object
28
+ #
29
+ # @param client [Ably::Rest::Client]
30
+ # @param name [String] The name of the channel
31
+ # @param channel_options [Hash, Ably::Models::ChannelOptions] A hash of options or a {Ably::Models::ChannelOptions}
32
+ #
33
+ def initialize(client, name, channel_options = {})
34
+ name = (ensure_utf_8 :name, name)
35
+
36
+ @options = Ably::Models::ChannelOptions(channel_options)
37
+ @client = client
38
+ @name = name
39
+ @push = PushChannel.new(self)
40
+ end
41
+
42
+ # Publishes a message to the channel. A callback may optionally be passed in to this call to be notified of success or failure of the operation.
43
+ #
44
+ # @spec RSL1
45
+ #
46
+ # @param name [String, Array<Ably::Models::Message|Hash>, Ably::Models::Message, nil] The event name of the message to publish, or an Array of [Ably::Model::Message] objects or [Hash] objects with +:name+ and +:data+ pairs, or a single Ably::Model::Message object
47
+ # @param data [String, Array, Hash, nil] The message payload unless an Array of [Ably::Model::Message] objects passed in the first argument, in which case an optional hash of query parameters
48
+ # @param attributes [Hash, nil] Optional additional message attributes such as :extras, :id, :client_id or :connection_id, applied when name attribute is nil or a string (Deprecated, will be removed in 2.0 in favour of constructing a Message object)
49
+ # @return [Boolean] true if the message was published, otherwise false
50
+ #
51
+ # @example
52
+ # # Publish a single message with (name, data) form
53
+ # channel.publish 'click', { x: 1, y: 2 }
54
+ #
55
+ # # Publish a single message with single Hash form
56
+ # message = { name: 'click', data: { x: 1, y: 2 } }
57
+ # channel.publish message
58
+ #
59
+ # # Publish an array of message Hashes form
60
+ # messages = [
61
+ # { name: 'click', data: { x: 1, y: 2 } },
62
+ # { name: 'click', data: { x: 2, y: 3 } }
63
+ # ]
64
+ # channel.publish messages
65
+ #
66
+ # # Publish an array of Ably::Models::Message objects form
67
+ # messages = [
68
+ # Ably::Models::Message(name: 'click', data: { x: 1, y: 2 })
69
+ # Ably::Models::Message(name: 'click', data: { x: 2, y: 3 })
70
+ # ]
71
+ # channel.publish messages
72
+ #
73
+ # # Publish a single Ably::Models::Message object form
74
+ # message = Ably::Models::Message(name: 'click', data: { x: 1, y: 2 })
75
+ # channel.publish message
76
+ #
77
+ def publish(name, data = nil, attributes = {})
78
+ qs_params = nil
79
+ qs_params = data if name.kind_of?(Enumerable) || name.kind_of?(Ably::Models::Message)
80
+
81
+ messages = build_messages(name, data, attributes) # (RSL1a, RSL1b)
82
+
83
+ if messages.sum(&:size) > (max_message_size = client.max_message_size || Ably::Rest::Client::MAX_MESSAGE_SIZE)
84
+ raise Ably::Exceptions::MaxMessageSizeExceeded.new("Maximum message size exceeded #{max_message_size} bytes.")
85
+ end
86
+
87
+ payload = messages.map do |message|
88
+ Ably::Models::Message(message.dup).tap do |msg|
89
+ msg.encode client.encoders, options
90
+
91
+ next if msg.client_id.nil?
92
+ if msg.client_id == '*'
93
+ raise Ably::Exceptions::IncompatibleClientId.new('Wildcard client_id is reserved and cannot be used when publishing messages')
94
+ end
95
+ unless client.auth.can_assume_client_id?(msg.client_id)
96
+ raise Ably::Exceptions::IncompatibleClientId.new("Cannot publish with client_id '#{msg.client_id}' as it is incompatible with the current configured client_id '#{client.client_id}'")
97
+ end
98
+ end.as_json
99
+ end.tap do |payload|
100
+ if client.idempotent_rest_publishing
101
+ # We cannot mutate for idempotent publishing if one or more messages already has an ID
102
+ if payload.all? { |msg| !msg['id'] }
103
+ # Mutate the JSON to support idempotent publishing where a Message.id does not exist
104
+ idempotent_publish_id = SecureRandom.base64(IDEMPOTENT_LIBRARY_GENERATED_ID_LENGTH)
105
+ payload.each_with_index do |msg, idx|
106
+ msg['id'] = "#{idempotent_publish_id}:#{idx}"
107
+ end
108
+ end
109
+ end
110
+ end
111
+
112
+ options = qs_params ? { qs_params: qs_params } : {}
113
+ response = client.post("#{base_path}/publish", payload.length == 1 ? payload.first : payload, options)
114
+
115
+ [201, 204].include?(response.status)
116
+ end
117
+
118
+ # Retrieves a {Ably::Models::PaginatedResult} object, containing an array of historical {Ably::Models::Message}
119
+ # objects for the channel. If the channel is configured to persist messages, then messages can be retrieved from
120
+ # history for up to 72 hours in the past. If not, messages can only be retrieved from history for up to two minutes in the past.
121
+ #
122
+ # @spec RSL2a
123
+ #
124
+ # @param [Hash] options the options for the message history request
125
+ # @option options [Integer,Time] :start The time from which messages are retrieved, specified as milliseconds since the Unix epoch. RSL2b1
126
+ # @option options [Integer,Time] :end The time until messages are retrieved, specified as milliseconds since the Unix epoch. RSL2b1
127
+ # @option options [Symbol] :direction The order for which messages are returned in. Valid values are backwards which orders messages from most recent to oldest, or forwards which orders messages from oldest to most recent. The default is backwards. RSL2b2
128
+ # @option options [Integer] :limit An upper limit on the number of messages returned. The default is 100, and the maximum is 1000. RSL2b3
129
+ #
130
+ # @return [Ably::Models::PaginatedResult<Ably::Models::Message>] A {Ably::Models::PaginatedResult} object containing an array of {Ably::Models::Message} objects.
131
+ #
132
+ def history(options = {})
133
+ url = "#{base_path}/messages"
134
+ options = {
135
+ :direction => :backwards,
136
+ :limit => 100
137
+ }.merge(options)
138
+
139
+ [:start, :end].each { |option| options[option] = as_since_epoch(options[option]) if options.has_key?(option) }
140
+ raise ArgumentError, ":end must be equal to or after :start" if options[:start] && options[:end] && (options[:start] > options[:end])
141
+
142
+ paginated_options = {
143
+ coerce_into: 'Ably::Models::Message',
144
+ async_blocking_operations: options.delete(:async_blocking_operations),
145
+ }
146
+
147
+ response = client.get(url, options)
148
+
149
+ Ably::Models::PaginatedResult.new(response, url, client, paginated_options) do |message|
150
+ message.tap do |msg|
151
+ decode_message msg
152
+ end
153
+ end
154
+ end
155
+
156
+ # A {Ably::Rest::Presence} object.
157
+ # @spec RSL3
158
+ # @return [Ably::Rest::Presence]
159
+ def presence
160
+ @presence ||= Presence.new(client, self)
161
+ end
162
+
163
+ # Sets the {Ably::Models::ChannelOptions} for the channel.
164
+ # @spec RSL7
165
+ # @param channel_options [Hash, Ably::Models::ChannelOptions] A hash of options or a {Ably::Models::ChannelOptions}
166
+ # @return [Ably::Models::ChannelOptions]
167
+ def set_options(channel_options)
168
+ @options = Ably::Models::ChannelOptions(channel_options)
169
+ end
170
+ alias options= set_options
171
+
172
+ # Retrieves a {Ably::Models::ChannelDetails} object for the channel, which includes status and occupancy metrics.
173
+ # @spec RSL8
174
+ # @return [Ably::Models::ChannelDetails] A {Ably::Models::ChannelDetails} object.
175
+ def status
176
+ Ably::Models::ChannelDetails.new(client.get(base_path).body)
177
+ end
178
+
179
+ private
180
+
181
+ def base_path
182
+ "/channels/#{URI.encode_www_form_component(name)}"
183
+ end
184
+
185
+ def decode_message(message)
186
+ message.decode client.encoders, options
187
+ rescue Ably::Exceptions::CipherError, Ably::Exceptions::EncoderError => e
188
+ client.logger.error { "Decoding Error on channel '#{name}', message event name '#{message.name}'. #{e.class.name}: #{e.message}" }
189
+ end
190
+ end
191
+ end
192
+ end
193
+
194
+ require 'ably/rest/channel/push_channel'
@@ -0,0 +1,47 @@
1
+ module Ably
2
+ module Rest
3
+ class Channels
4
+ include Ably::Modules::ChannelsCollection
5
+
6
+ # @return [Ably::Rest::Channels]
7
+ def initialize(client)
8
+ super client, Ably::Rest::Channel
9
+ end
10
+
11
+ # Return a {Ably::Rest::Channel} for the given name
12
+ #
13
+ # @param name [String] The name of the channel
14
+ # @param channel_options [Hash] Channel options, currently reserved for Encryption options
15
+ #
16
+ # @return [Ably::Rest::Channel]
17
+ #
18
+ def get(*args)
19
+ super
20
+ end
21
+
22
+ # Return a {Ably::Rest::Channel} for the given name if it exists, else the block will be called.
23
+ # 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
24
+ #
25
+ # @param name [String] The name of the channel
26
+ # @yield [options] (optional) if a missing_block is passed to this method and no channel exists matching the name, this block is called
27
+ # @yieldparam [String] name of the missing channel
28
+ #
29
+ # @return [Ably::Rest::Channel]
30
+ #
31
+ def fetch(*args)
32
+ super
33
+ end
34
+
35
+ # Destroy the {Ably::Rest::Channel} and releases the associated resources.
36
+ #
37
+ # Releasing a {Ably::Rest::Channel} is not typically necessary as a channel consumes no resources other than the memory footprint of the
38
+ # {Ably::Rest::Channel} object. Explicitly release channels to free up resources if required
39
+ #
40
+ # @return [void]
41
+ #
42
+ def release(*args)
43
+ super
44
+ end
45
+ end
46
+ end
47
+ end