Skip to content

Allow Dispatcher to inject a custom generator_class#21

Open
andriytyurnikov wants to merge 1 commit intostarfederation:mainfrom
rubakas:feature/dispatcher-generator-class
Open

Allow Dispatcher to inject a custom generator_class#21
andriytyurnikov wants to merge 1 commit intostarfederation:mainfrom
rubakas:feature/dispatcher-generator-class

Conversation

@andriytyurnikov
Copy link
Copy Markdown

Summary

Adds an optional generator_class: keyword to Datastar::Dispatcher#initialize (defaulting to ServerSentEventGenerator). The three internal generator instantiations — stream_one, stream_many's connection generator, and each per-stream generator inside spawned threads — now go through the injected class.

Why

Downstream wrappers around Datastar (e.g. vibes-datastar) need to layer behavior on top of the SSE generator: input scrubbing, logging, metrics, debug capture, etc. Today the only option is monkey-patching ServerSentEventGenerator, because the dispatcher hard-codes the class at three call sites — and the user code inside Dispatcher#stream { |sse| ... } always receives an SDK-instantiated generator. Letting the dispatcher accept a subclass is the standard "let the wrapper override the workhorse class" hook.

This is the smaller, orthogonal change discussed in the comment thread on #18.

API

class ScrubbingGenerator < Datastar::ServerSentEventGenerator
  def patch_elements(elements, options = BLANK_OPTIONS)
    super(scrub(elements), scrub_options(options))
  end
  # ...
end

datastar = Datastar.new(
  request:, response:, view_context:,
  generator_class: ScrubbingGenerator,
)

Tests

4 new specs under `Dispatcher :generator_class`:

  • defaults to `Datastar::ServerSentEventGenerator`
  • one-off responses (`stream_one`) use the injected class
  • multi-stream responses (`stream_many`) use it for the connection generator and every per-stream generator
  • a subclass overriding `#write` observes every event written to the stream

Full suite: 104 examples, 0 failures.

Notes

Test plan

  • CI green
  • Existing call sites still work (default behavior preserved)

Adds an optional generator_class: keyword to Dispatcher.new (defaulting
to ServerSentEventGenerator) and routes the three internal generator
instantiations — stream_one, stream_many's connection generator, and
each per-stream generator inside spawned threads — through it.

Lets downstream wrappers layer behavior (logging, metrics, input
scrubbing, etc.) on top of the SDK by passing a subclass, instead of
monkey-patching the SDK class.
@andriytyurnikov
Copy link
Copy Markdown
Author

Upstream CI hasn't fired on this PR (workflow is on: push only). Fork CI run on the same commit, green: https://github.com/rubakas/datastar-ruby/actions/runs/24990202698 (Ruby 4.0 on Linux + full Datastar SDK conformance suite). 104 examples, 0 failures — the 4 new specs cover default class, stream_one, stream_many (connection generator + per-stream generators), and a subclass observing #write.

@andriytyurnikov andriytyurnikov deleted the feature/dispatcher-generator-class branch April 27, 2026 11:29
@andriytyurnikov andriytyurnikov restored the feature/dispatcher-generator-class branch April 27, 2026 11:51
@andriytyurnikov andriytyurnikov deleted the feature/dispatcher-generator-class branch April 27, 2026 11:54
@andriytyurnikov andriytyurnikov restored the feature/dispatcher-generator-class branch April 27, 2026 12:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant