Class: InstantRecord::EventsController

Inherits:
ActionController::Base
  • Object
show all
Defined in:
app/controllers/instant_record/events_controller.rb

Defined Under Namespace

Classes: EventStream

Constant Summary collapse

EVENT_STREAM_HEADERS =

SSE change stream as a lazily-enumerated response body — not ActionController::Live (which burns a thread per stream and bypasses the fiber scheduler). An #each body is the portable Rack streaming interface: Puma and Falcon both write each chunk as it is yielded. Under Falcon each stream is a fiber, so sleep and pg queries suspend the fiber; under Puma the body holds the request thread.

The change-log row id is the event id, which doubles as the client's cursor: catch-up from ?after= (or the Last-Event-ID reconnect header), then tail for a bounded window and close. ?window= lets a client shorten the tail — the gem's own sync loop polls with window=0 (catch-up only) so a tick never holds a long stream.

{
  "content-type" => "text/event-stream",
  "cache-control" => "no-store",
  "x-accel-buffering" => "no"
}.freeze

Instance Method Summary collapse

Instance Method Details

#indexObject



40
41
42
43
44
45
# File 'app/controllers/instant_record/events_controller.rb', line 40

def index
  cursor = (request.headers["Last-Event-ID"] || params[:after] || 0).to_i

  headers.merge!(EVENT_STREAM_HEADERS).merge!(InstantRecord::CORS_HEADERS)
  self.response_body = EventStream.new(cursor: cursor, deadline: Time.current + window_seconds)
end