pgbus 0.6.6 → 0.6.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1a4669f7150717428ced89a13b5c8e7f9cf5d61d6eae6b19919d6408fefad06a
4
- data.tar.gz: 4dc1c6db2f50ce6e0de5c845cd2813cbb299ad096dab2dcfa5169db368dfa0af
3
+ metadata.gz: e747f3644d06463ea9cd87dc79fbe19e1787ba7d4e9df0ba7512f729b6189224
4
+ data.tar.gz: 1b2f8a1eb8f2c10c32fa3f2c0eab5a59b2de1382e07537ee349d958393061d96
5
5
  SHA512:
6
- metadata.gz: 3184e872126937ec8660530143c610a64a0649bd60ab7c9bca6663e6883af3ec16144cfb3d7b74713ff0a5487b7f1edacba973e387a52f802237f9ff3a2c7b2c
7
- data.tar.gz: bc0f72ace6413ad27899d7968b3fe6df822fd35f3b495bdbf24ccd95c9add029f5ebb3b11e462c0a30937bfca3082460e3c655533464becf73d6cb328ded8621
6
+ metadata.gz: b60516dfce1ba05b77afd21ab8e6ad3d227a2dde4edefc662221217533e22d1fa810f5056cc0f7d4470dbc220a7ae920408b785b088f8155c6a0bcb802283243
7
+ data.tar.gz: b386c96b0b493a00b196926fc014797e807538a6039fd772a4b0bafefd2b019d9a4f2f25136b264c03aa6a88a1533899e156341e57b81afdda0c9bf88de6a477
@@ -35,7 +35,8 @@
35
35
  // automatically based on the last id: we observed. The native
36
36
  // client is more battle-tested for reconnection backoff.
37
37
 
38
- import { connectStreamSource, disconnectStreamSource } from "@hotwired/turbo"
38
+ import { Turbo } from "@hotwired/turbo-rails"
39
+ const { connectStreamSource, disconnectStreamSource } = Turbo
39
40
 
40
41
  class PgbusStreamSourceElement extends HTMLElement {
41
42
  static get observedAttributes() {
@@ -51,6 +52,7 @@ class PgbusStreamSourceElement extends HTMLElement {
51
52
  }
52
53
 
53
54
  connectedCallback() {
55
+ this.closed = false
54
56
  connectStreamSource(this)
55
57
  const sinceId = this.getAttribute("since-id")
56
58
  this.lastEventId = sinceId && sinceId !== "" ? sinceId : null
@@ -106,7 +108,11 @@ class PgbusStreamSourceElement extends HTMLElement {
106
108
 
107
109
  while (!this.closed) {
108
110
  const { value, done } = await reader.read()
109
- if (done) break
111
+ if (done) {
112
+ this.removeAttribute("connected")
113
+ this.switchToEventSource()
114
+ return
115
+ }
110
116
 
111
117
  buffer += decoder.decode(value, { stream: true })
112
118
  const events = buffer.split("\n\n")
@@ -131,7 +137,7 @@ class PgbusStreamSourceElement extends HTMLElement {
131
137
  switchToEventSource() {
132
138
  if (this.closed) return
133
139
 
134
- const url = this.buildUrl({ includeSince: false })
140
+ const url = this.buildUrl({ includeSince: true })
135
141
  this.eventSource = new EventSource(url, { withCredentials: true })
136
142
 
137
143
  this.eventSource.addEventListener("open", () => {
@@ -46,7 +46,11 @@ module Pgbus
46
46
  "channel" => "Turbo::StreamsChannel"
47
47
  }.merge(html_attributes.transform_keys(&:to_s))
48
48
 
49
- render_tag("pgbus-stream-source", attributes)
49
+ element = render_tag("pgbus-stream-source", attributes)
50
+ script = pgbus_stream_source_script_tag
51
+ return element unless script
52
+
53
+ safe_concat(script, element)
50
54
  end
51
55
 
52
56
  private
@@ -118,6 +122,34 @@ module Pgbus
118
122
  cache[stream_name] ||= Pgbus.stream(stream_name).current_msg_id
119
123
  end
120
124
 
125
+ # Emits a <script type="module"> tag that imports the custom element
126
+ # definition exactly once per request. Without this, <pgbus-stream-source>
127
+ # is an inert unknown element — no SSE connection opens. Uses a
128
+ # thread-local flag cleared by the WatermarkCacheMiddleware.
129
+ def pgbus_stream_source_script_tag
130
+ cache = Thread.current[:pgbus_streams_watermark_cache] ||= {}
131
+ return nil if cache[:script_emitted]
132
+
133
+ cache[:script_emitted] = true
134
+ script = '<script type="module">import "pgbus/stream_source_element"</script>'
135
+ script.respond_to?(:html_safe) ? script.html_safe : script
136
+ end
137
+
138
+ # Concatenates two HTML-safe strings without losing the safety flag.
139
+ # ActiveSupport::SafeBuffer#+ preserves safety when both operands
140
+ # are safe. Plain string interpolation ("#{a}#{b}") creates a new
141
+ # String, dropping html_safe — which causes Phlex and safe_join to
142
+ # HTML-escape the output.
143
+ def safe_concat(*parts)
144
+ if defined?(ActiveSupport::SafeBuffer)
145
+ buf = ActiveSupport::SafeBuffer.new
146
+ parts.each { |p| buf.safe_concat(p) }
147
+ buf
148
+ else
149
+ parts.join
150
+ end
151
+ end
152
+
121
153
  def render_tag(name, attributes)
122
154
  attr_string = attributes.map { |k, v| %(#{k}="#{CGI.escape_html(v.to_s)}") }.join(" ")
123
155
  html = "<#{name} #{attr_string}></#{name}>"
data/lib/pgbus/engine.rb CHANGED
@@ -66,6 +66,29 @@ module Pgbus
66
66
  app.middleware.use Pgbus::Streams::WatermarkCacheMiddleware if Pgbus.configuration.streams_enabled
67
67
  end
68
68
 
69
+ # Make stream_source_element.js available to the host app's asset
70
+ # pipeline (Propshaft or Sprockets) so it can be included via
71
+ # `javascript_include_tag "pgbus/stream_source_element"` or pinned
72
+ # in importmap. When importmap-rails is loaded, auto-pin it so
73
+ # host apps get it without manual configuration.
74
+ initializer "pgbus.streams.assets" do |app|
75
+ if Pgbus.configuration.streams_enabled && app.config.respond_to?(:assets)
76
+ app.config.assets.precompile += %w[pgbus/stream_source_element.js]
77
+ end
78
+ end
79
+
80
+ initializer "pgbus.streams.importmap" do
81
+ if Pgbus.configuration.streams_enabled && defined?(::Importmap::Map)
82
+ ActiveSupport.on_load(:after_initialize) do
83
+ next unless Rails.application.respond_to?(:importmap)
84
+
85
+ Rails.application.importmap.pin(
86
+ "pgbus/stream_source_element", to: "pgbus/stream_source_element.js"
87
+ )
88
+ end
89
+ end
90
+ end
91
+
69
92
  # Install the Turbo::StreamsChannel patch after turbo-rails has been
70
93
  # loaded. The patch redirects broadcast_stream_to through Pgbus.stream
71
94
  # instead of ActionCable. When turbo-rails is not loaded, this is a
@@ -17,7 +17,17 @@ module Pgbus
17
17
  # After this patch, `turbo_stream_from` renders a `<pgbus-stream-source>`
18
18
  # element instead, so both sides use PGMQ/SSE. When `streams_enabled`
19
19
  # is false, the original turbo-rails behavior is preserved via `super`.
20
+ #
21
+ # The `include Pgbus::StreamsHelper` is required because some callers
22
+ # invoke `turbo_stream_from` from a Rack middleware context (e.g.
23
+ # hotwire-livereload's Middleware uses `ActionController::Base.helpers`)
24
+ # where `Turbo::StreamsHelper` is available but `Pgbus::StreamsHelper`
25
+ # is not — the engine's `isolate_namespace` scopes helpers to its own
26
+ # views. Including it here ensures `pgbus_stream_from` is always
27
+ # reachable on the receiver.
20
28
  module TurboStreamOverride
29
+ include Pgbus::StreamsHelper
30
+
21
31
  def turbo_stream_from(*streamables, **attributes)
22
32
  if Pgbus.configuration.streams_enabled
23
33
  pgbus_stream_from(*streamables, **attributes)
data/lib/pgbus/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Pgbus
4
- VERSION = "0.6.6"
4
+ VERSION = "0.6.7"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pgbus
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.6
4
+ version: 0.6.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mikael Henriksson
@@ -121,6 +121,7 @@ files:
121
121
  - LICENSE.txt
122
122
  - README.md
123
123
  - Rakefile
124
+ - app/assets/javascripts/pgbus/stream_source_element.js
124
125
  - app/controllers/pgbus/api/insights_controller.rb
125
126
  - app/controllers/pgbus/api/metrics_controller.rb
126
127
  - app/controllers/pgbus/api/stats_controller.rb
@@ -145,7 +146,6 @@ files:
145
146
  - app/frontend/pgbus/vendor/turbo.js
146
147
  - app/helpers/pgbus/application_helper.rb
147
148
  - app/helpers/pgbus/streams_helper.rb
148
- - app/javascript/pgbus/stream_source_element.js
149
149
  - app/models/pgbus/application_record.rb
150
150
  - app/models/pgbus/batch_entry.rb
151
151
  - app/models/pgbus/blocked_execution.rb