lib/submodules/ably-ruby/lib/ably/realtime/client.rb in ably-rest-1.0.6 vs lib/submodules/ably-ruby/lib/ably/realtime/client.rb in ably-rest-1.1.0
- old
+ new
@@ -1,6 +1,7 @@
require 'uri'
+require 'ably/realtime/channel/publisher'
module Ably
module Realtime
# Client for the Ably Realtime API
#
@@ -19,10 +20,13 @@
# @!attribute [r] protocol_binary?
# (see Ably::Rest::Client#protocol_binary?)
#
class Client
include Ably::Modules::AsyncWrapper
+ include Ably::Realtime::Channel::Publisher
+ include Ably::Modules::Conversions
+
extend Forwardable
DOMAIN = 'realtime.ably.io'
# The collection of {Ably::Realtime::Channel}s that have been created
@@ -36,10 +40,11 @@
# @return [Aby::Realtime::Connection]
attr_reader :connection
# The {Ably::Rest::Client REST client} instantiated with the same credentials and configuration that is used for all REST operations such as authentication
# @return [Ably::Rest::Client]
+ # @private
attr_reader :rest_client
# When false the client suppresses messages originating from this connection being echoed back on the same connection. Defaults to true
# @return [Boolean]
attr_reader :echo_messages
@@ -160,20 +165,94 @@
# (see Ably::Realtime::Connection#connect)
def connect(&block)
connection.connect(&block)
end
+ # Push notification object for publishing and managing push notifications
+ # @return [Ably::Realtime::Push]
+ def push
+ @push ||= Push.new(self)
+ end
+
# (see Ably::Rest::Client#request)
# @yield [Ably::Models::HttpPaginatedResponse<>] An Array of Stats
#
# @return [Ably::Util::SafeDeferrable]
def request(method, path, params = {}, body = nil, headers = {}, &callback)
async_wrap(callback) do
rest_client.request(method, path, params, body, headers, async_blocking_operations: true)
end
end
+ # Publish one or more messages to the specified channel.
+ #
+ # This method allows messages to be efficiently published to Ably without instancing a {Ably::Realtime::Channel} object.
+ # If you want to publish a high rate of messages to Ably without instancing channels or using the REST API, then this method
+ # is recommended. However, channel options such as encryption are not supported with this method. If you need to specify channel options
+ # we recommend you use the {Ably::Realtime::Channel} +publish+ method without attaching to each channel, unless you also want to subscribe
+ # to published messages on that channel.
+ #
+ # Note: This feature is still in beta. As such, we cannot guarantee the API will not change in future.
+ #
+ # @param channel [String] The channel name you want to publish the message(s) to
+ # @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
+ #
+ # @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
+ # @return [Ably::Util::SafeDeferrable] Deferrable that supports both success (callback) and failure (errback) callbacks
+ #
+ # @example
+ # # Publish a single message
+ # client.publish 'activityChannel', click', { x: 1, y: 2 }
+ #
+ # # Publish an array of message Hashes
+ # messages = [
+ # { name: 'click', { x: 1, y: 2 } },
+ # { name: 'click', { x: 2, y: 3 } }
+ # ]
+ # client.publish 'activityChannel', messages
+ #
+ # # Publish an array of Ably::Models::Message objects
+ # messages = [
+ # Ably::Models::Message(name: 'click', { x: 1, y: 2 })
+ # Ably::Models::Message(name: 'click', { x: 2, y: 3 })
+ # ]
+ # client.publish 'activityChannel', messages
+ #
+ # client.publish('activityChannel', 'click', 'body') do |message|
+ # puts "#{message.name} event received with #{message.data}"
+ # end
+ #
+ # client.publish('activityChannel', 'click', 'body').errback do |error, message|
+ # puts "#{message.name} was not received, error #{error.message}"
+ # end
+ #
+ def publish(channel_name, name, data = nil, attributes = {}, &success_block)
+ if !connection.can_publish_messages?
+ error = Ably::Exceptions::MessageQueueingDisabled.new("Message cannot be published. Client is not allowed to queue messages when connection is in state #{connection.state}")
+ return Ably::Util::SafeDeferrable.new_and_fail_immediately(logger, error)
+ end
+
+ messages = if name.kind_of?(Enumerable)
+ name
+ else
+ name = ensure_utf_8(:name, name, allow_nil: true)
+ ensure_supported_payload data
+ [{ name: name, data: data }.merge(attributes)]
+ end
+
+ if messages.length > Realtime::Connection::MAX_PROTOCOL_MESSAGE_BATCH_SIZE
+ 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.")
+ return Ably::Util::SafeDeferrable.new_and_fail_immediately(logger, error)
+ end
+
+ enqueue_messages_on_connection(self, messages, channel_name).tap do |deferrable|
+ deferrable.callback(&success_block) if block_given?
+ end
+ end
+
# @!attribute [r] endpoint
# @return [URI::Generic] Default Ably Realtime endpoint used for all requests
def endpoint
endpoint_for_host(custom_realtime_host || [environment, DOMAIN].compact.join('-'))
end
@@ -210,9 +289,17 @@
end
fallback_endpoint_index = connection.manager.retry_count_for_state(:disconnected) + connection.manager.retry_count_for_state(:suspended) - 1
@fallback_endpoints[fallback_endpoint_index % @fallback_endpoints.count]
+ end
+
+ # The local device detilas
+ # @return [Ably::Models::LocalDevice]
+ #
+ # @note This is unsupported in the Ruby library
+ def device
+ raise Ably::Exceptions::PushNotificationsNotSupported, 'This device does not support receiving or subscribing to push notifications. The local device object is not unavailable'
end
private
def endpoint_for_host(host)
port = if use_tls?