pgbus 0.6.5 → 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:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e747f3644d06463ea9cd87dc79fbe19e1787ba7d4e9df0ba7512f729b6189224
|
|
4
|
+
data.tar.gz: 1b2f8a1eb8f2c10c32fa3f2c0eab5a59b2de1382e07537ee349d958393061d96
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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 {
|
|
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)
|
|
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:
|
|
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
|
|
@@ -84,6 +107,15 @@ module Pgbus
|
|
|
84
107
|
# `_` keeps RuboCop's Lint/Void from deleting the line.
|
|
85
108
|
_autoload_trigger = Pgbus::Streams::TurboBroadcastable
|
|
86
109
|
Pgbus::Streams.install_turbo_broadcastable_patch!
|
|
110
|
+
|
|
111
|
+
# Subscribe-side patch: override turbo_stream_from to render
|
|
112
|
+
# <pgbus-stream-source> (SSE) instead of <turbo-cable-stream-source>
|
|
113
|
+
# (ActionCable). Without this, third-party gems like
|
|
114
|
+
# hotwire-livereload that call turbo_stream_from in their views
|
|
115
|
+
# subscribe via ActionCable while the broadcast (patched above)
|
|
116
|
+
# goes through PGMQ — the message never arrives.
|
|
117
|
+
_autoload_trigger_override = Pgbus::Streams::TurboStreamOverride
|
|
118
|
+
Pgbus::Streams.install_turbo_stream_override!
|
|
87
119
|
end
|
|
88
120
|
end
|
|
89
121
|
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pgbus
|
|
4
|
+
module Streams
|
|
5
|
+
# Runtime patch that redirects `turbo_stream_from` (the view helper)
|
|
6
|
+
# through `pgbus_stream_from` when pgbus streams are enabled. This is
|
|
7
|
+
# the subscribe-side counterpart to `TurboBroadcastable` (which patches
|
|
8
|
+
# the publish-side `broadcast_stream_to`).
|
|
9
|
+
#
|
|
10
|
+
# Without this patch, third-party gems like hotwire-livereload call
|
|
11
|
+
# `turbo_stream_from "hotwire-livereload"` in their views, which
|
|
12
|
+
# renders a `<turbo-cable-stream-source>` element connected to
|
|
13
|
+
# ActionCable. Meanwhile, the `TurboBroadcastable` patch routes the
|
|
14
|
+
# broadcast through PGMQ/SSE. Publisher and subscriber end up on
|
|
15
|
+
# different transports — the message never arrives.
|
|
16
|
+
#
|
|
17
|
+
# After this patch, `turbo_stream_from` renders a `<pgbus-stream-source>`
|
|
18
|
+
# element instead, so both sides use PGMQ/SSE. When `streams_enabled`
|
|
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.
|
|
28
|
+
module TurboStreamOverride
|
|
29
|
+
include Pgbus::StreamsHelper
|
|
30
|
+
|
|
31
|
+
def turbo_stream_from(*streamables, **attributes)
|
|
32
|
+
if Pgbus.configuration.streams_enabled
|
|
33
|
+
pgbus_stream_from(*streamables, **attributes)
|
|
34
|
+
else
|
|
35
|
+
super
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Apply the patch to Turbo::StreamsHelper. Idempotent: prepending the
|
|
41
|
+
# same module twice is a no-op. Called from Pgbus::Engine's initializer
|
|
42
|
+
# when both turbo-rails and pgbus streams are enabled.
|
|
43
|
+
def self.install_turbo_stream_override!
|
|
44
|
+
return unless defined?(::Turbo::StreamsHelper)
|
|
45
|
+
return if ::Turbo::StreamsHelper.ancestors.include?(TurboStreamOverride)
|
|
46
|
+
|
|
47
|
+
::Turbo::StreamsHelper.prepend(TurboStreamOverride)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
data/lib/pgbus/version.rb
CHANGED
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.
|
|
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
|
|
@@ -297,6 +297,7 @@ files:
|
|
|
297
297
|
- lib/pgbus/streams/presence.rb
|
|
298
298
|
- lib/pgbus/streams/signed_name.rb
|
|
299
299
|
- lib/pgbus/streams/turbo_broadcastable.rb
|
|
300
|
+
- lib/pgbus/streams/turbo_stream_override.rb
|
|
300
301
|
- lib/pgbus/streams/watermark_cache_middleware.rb
|
|
301
302
|
- lib/pgbus/uniqueness.rb
|
|
302
303
|
- lib/pgbus/version.rb
|