module Redisse
Public: A HTTP API to serve Server-Sent Events via a Redis backend.
Constants
- TestEvent
Define then reopen instead of using the block of Struct.new for YARD.
- VERSION
Attributes
Public: The port on which the server listens.
Defaults to the REDISSE_PORT environment variable and if it is not set, to 8080.
Public: The internal URL hierarchy to redirect to with X-Accel-Redirect.
When this property is set, Redisse
will work totally differently. Your Ruby code will not be loaded by the events server itself, but only by the {#redirect_endpoint} Rack app that you will have to route to in your Rack app (e.g. using map
in config.ru
) and this endpoint will redirect to this internal URL hierarchy.
Defaults to /redisse.
Public: Gets/Sets the String URL of the Redis server to connect to.
Note that while the Redis pubsub mechanism works outside of the Redis key namespace and ignores the database (the path part of the URL), the database will still be used to store an history of the events sent to support Last-Event-Id.
Defaults to the REDISSE_REDIS environment variable and if it is not set, to redis://localhost:6379/.
Public Class Methods
Public: Define the list of channels to subscribe to.
Calls the given block with a Rack environment, the block is expected to return a list of channels the current user has access to. The list is then coerced using +Kernel#Array+.
Once the block is defined, other calls will be handled by the block directly, as if the method had been redefined directly. It simply gives a nicer API:
Redisse.channels do |env| end
vs
def Redisse.channels(env) end
block - The block that lists the channels for the given Rack environment.
Examples
Redisse.channels do |env| %w( comment post ) end # will result in subscriptions to 'comment' and 'post' channels. Redisse.channels({}) # => ["comment", "post"]
# File lib/redisse/configuration.rb, line 33 def self.channels(*, &block) if block # overwrite method with block define_singleton_method :channels, &block else super end end
Public Instance Methods
Public: The list of channels to subscribe to.
Once {Redisse.channels} has been called, the given block is this method. The block must satisfy this interface:
env - The Rack environment for this request.
Returns an Array of String naming the channels to subscribe to.
Raises NotImplementedError unless {Redisse.channels} has been called.
# File lib/redisse.rb, line 74 def channels(env) raise NotImplementedError, "you must call Redisse.channels first" end
Internal: List of middlewares defined with {#use}.
Used by Goliath to build the server.
# File lib/redisse.rb, line 127 def middlewares @middlewares ||= [] end
Public: Define a Goliath plugin to run with the server.
See {github.com/postrank-labs/goliath/wiki/Plugins Goliath plugins}.
# File lib/redisse.rb, line 145 def plugin(name, *args) plugins << [name, args] end
Public: Send an event to subscribers, of the given type.
All browsers subscribing to the events server will receive a Server-Sent Event of the chosen type.
channel - The channel to publish the message to. type_message - The type of the event and the content of the message, as a
Hash of form { type => message } or simply the message as a String, for the default event type :message.
Examples
Redisse.publish(:global, notice: 'This is a server-sent event.') Redisse.publish(:global, 'Hello, World!') # on the browser side: var source = new EventSource(eventsURL); source.addEventListener('notice', function(e) { console.log(e.data) // logs 'This is a server-sent event.' }, false) source.addEventListener('message', function(e) { console.log(e.data) // logs 'Hello, World!' }, false)
# File lib/redisse.rb, line 58 def publish(channel, message) type, message = Hash(message).first if message.respond_to?(:to_h) type ||= :message publisher.publish(channel, message, type) end
Public: Returns the published events.
Fails unless {#test_mode!} is set.
# File lib/redisse.rb, line 119 def published fail "Call #{self}.test_mode! first" unless publisher.respond_to?(:published) publisher.published end
Public: The Rack application that redirects to {#nginx_internal_url}.
If you set {#nginx_internal_url}, you need to call this Rack application to redirect to the Redisse
server.
Also note that when using the redirect endpoint, two channel names are reserved, and cannot be used: polling
and lastEventId
.
Examples
map "/events" { run Redisse.redirect_endpoint }
# File lib/redisse.rb, line 160 def redirect_endpoint @redirect_endpoint ||= RedirectEndpoint.new self end
Public: Run the server.
If you use the provided binary you don’t need to call this method.
By default, the {#channels} method is called directly.
If {#nginx_internal_url} is set, the channels will actually come from the internal redirect URL generated in the Rack app by {#redirect_endpoint}.
# File lib/redisse/server.rb, line 17 def run run_as_standalone if nginx_internal_url server = Server.new(self) runner = Goliath::Runner.new(ARGV, server) runner.app = Goliath::Rack::Builder.build(self, server) runner.load_plugins([Server::Stats] + plugins) runner.run end
Public: Filter events stored in test mode.
If set, only events whose type match with the filter are stored in {#published}. A filter matches by using case equality, which allows using a simple Symbol or a Proc for more advanced filters:
Automatically sets {#test_mode!}, so it also clears the previous events.
Examples
Redisse.test_filter = -> type { %i(foo baz).include? type } Redisse.publish :global, foo: 'stored' Redisse.publish :global, bar: 'skipped' Redisse.publish :global, baz: 'stored' Redisse.published.size # => 2
# File lib/redisse.rb, line 111 def test_filter=(filter) test_mode! publisher.filter = filter end
Public: Use test mode.
Instead of actually publishing to Redis, events will be stored in {#published} to use for tests.
Must be called before each test in order for published events to be emptied.
See also {#test_filter=}.
Examples
# RSpec before { Redisse.test_mode! }
# File lib/redisse.rb, line 92 def test_mode! @publisher = TestPublisher.new end
Public: Define a middleware for the server.
See {github.com/postrank-labs/goliath/wiki/Middleware Goliath middlewares}.
Examples
Redisse.use MyMiddleware, foo: true
# File lib/redisse.rb, line 138 def use(middleware, *args, &block) middlewares << [middleware, args, block] end
Private Instance Methods
# File lib/redisse.rb, line 168 def plugins @plugins ||= [] end
# File lib/redisse.rb, line 172 def publisher @publisher ||= RedisPublisher.new(redis) end
# File lib/redisse.rb, line 176 def redis @redis ||= Redis.new(url: redis_server) end
Internal: Redefine {#channels} to find channels in the redirect URL.
# File lib/redisse/server.rb, line 29 def run_as_standalone channels do |env| query_string = env['QUERY_STRING'] || '' channels = query_string.split('&').map { |channel| URI.decode_www_form_component(channel) } channels.delete('polling') channels.delete_if {|channel| channel.start_with?('lastEventId=') } end end