lib/submodules/ably-ruby/lib/ably/rest/channel.rb in ably-rest-1.0.6 vs lib/submodules/ably-ruby/lib/ably/rest/channel.rb in ably-rest-1.1.0
- old
+ new
@@ -1,21 +1,31 @@
module Ably
module Rest
# The Ably Realtime service organises the traffic within any application into named channels.
# Channels are the "unit" of message distribution; clients attach to channels to subscribe to messages, and every message broadcast by the service is associated with a unique channel.
#
- # @!attribute [r] client
- # @return {Ably::Realtime::Client} Ably client associated with this channel
# @!attribute [r] name
# @return {String} channel name
# @!attribute [r] options
# @return {Hash} channel options configured for this channel, see {#initialize} for channel_options
class Channel
include Ably::Modules::Conversions
- attr_reader :client, :name, :options
+ # Ably client associated with this channel
+ # @return [Ably::Realtime::Client]
+ # @api private
+ attr_reader :client
+ attr_reader :name, :options
+
+ # Push channel used for push notification (client-side)
+ # @return [Ably::Rest::Channel::PushChannel]
+ # @api private
+ attr_reader :push
+
+ IDEMPOTENT_LIBRARY_GENERATED_ID_LENGTH = 9 # See spec RSL1k1
+
# Initialize a new Channel object
#
# @param client [Ably::Rest::Client]
# @param name [String] The name of the channel
# @param channel_options [Hash] Channel options, currently reserved for Encryption options
@@ -25,17 +35,18 @@
name = (ensure_utf_8 :name, name)
update_options channel_options
@client = client
@name = name
+ @push = PushChannel.new(self)
end
# Publish one or more messages to the channel.
#
# @param name [String, Array<Ably::Models::Message|Hash>, 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
# @param data [String, ByteArray, nil] The message payload unless an Array of [Ably::Model::Message] objects passed in the first argument
- # @param attributes [Hash, nil] Optional additional message attributes such as :client_id or :connection_id, applied when name attribute is nil or a string
+ # @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
# @return [Boolean] true if the message was published, otherwise false
#
# @example
# # Publish a single message
# channel.publish 'click', { x: 1, y: 2 }
@@ -56,16 +67,20 @@
#
def publish(name, data = nil, attributes = {})
messages = if name.kind_of?(Enumerable)
name
else
+ if name.kind_of?(Ably::Models::Message)
+ raise ArgumentError, "name argument does not support single Message objects, only arrays of Message objects"
+ end
+
name = ensure_utf_8(:name, name, allow_nil: true)
ensure_supported_payload data
[{ name: name, data: data }.merge(attributes)]
end
- payload = messages.map do |message|
+ payload = messages.each_with_index.map do |message, index|
Ably::Models::Message(message.dup).tap do |msg|
msg.encode client.encoders, options
next if msg.client_id.nil?
if msg.client_id == '*'
@@ -73,10 +88,21 @@
end
unless client.auth.can_assume_client_id?(msg.client_id)
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}'")
end
end.as_json
+ end.tap do |payload|
+ if client.idempotent_rest_publishing
+ # We cannot mutate for idempotent publishing if one or more messages already has an ID
+ if payload.all? { |msg| !msg['id'] }
+ # Mutate the JSON to support idempotent publishing where a Message.id does not exist
+ idempotent_publish_id = SecureRandom.base64(IDEMPOTENT_LIBRARY_GENERATED_ID_LENGTH)
+ payload.each_with_index do |msg, idx|
+ msg['id'] = "#{idempotent_publish_id}:#{idx}"
+ end
+ end
+ end
end
response = client.post("#{base_path}/publish", payload.length == 1 ? payload.first : payload)
[201, 204].include?(response.status)
@@ -139,5 +165,7 @@
client.logger.error { "Decoding Error on channel '#{name}', message event name '#{message.name}'. #{e.class.name}: #{e.message}" }
end
end
end
end
+
+require 'ably/rest/channel/push_channel'