rails_pulse 0.4.0.pre.1 → 0.4.0.pre.2
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 +4 -4
- data/CHANGELOG.md +27 -0
- data/lib/generators/rails_pulse/schema_parser.rb +22 -2
- data/lib/generators/rails_pulse/templates/migrations/upgrade_rails_pulse_tables.rb +1 -1
- data/lib/generators/rails_pulse/templates/rails_pulse.rb +5 -0
- data/lib/rails_pulse/tracker.rb +17 -1
- data/lib/rails_pulse/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b102fc4776d7fe701b47011e02d682f47a2784500103f3cb7d7598a757b174ff
|
|
4
|
+
data.tar.gz: 34f4055047c1bb9151c9e811f14c4e90fe83e52508c61ea4433929b2b431d568
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 974fcf20833ab11e46a00db96d21590f32a699a73de8d2af229d1fa5559f0817c107ba684f4ada34cdb067a77f6293ecc11ee3d24f7911f9fe074353a2991d79
|
|
7
|
+
data.tar.gz: 507afdae03f11fef23d0bbd7cc5ee8e8123656e41efbc219a10f8b6682602bfb7dcfa91e9ac424352d68ad05b3bceed4070eead220d053713f56aa1ade7bec01
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,33 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.4.0.pre.2] - 2026-09-04
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- **`rails generate rails_pulse:upgrade` wrote a migration that would not parse.**
|
|
15
|
+
The schema parser matched a column comment with `comment: "([^"]*)"`, which stops
|
|
16
|
+
at the first escaped quote. The `http_methods` comment embeds a `["GET","POST"]`
|
|
17
|
+
example, so it was truncated mid-escape and the trailing backslash escaped the
|
|
18
|
+
closing quote of the generated `comment:` string — the copied
|
|
19
|
+
`upgrade_rails_pulse_tables.rb` then failed to load with
|
|
20
|
+
`unterminated string meets end of file`. Comments are now matched as complete Ruby
|
|
21
|
+
string literals, decoded with `String#undump`, and re-escaped with `String#inspect`
|
|
22
|
+
when the migration is rendered.
|
|
23
|
+
|
|
24
|
+
- **Background tracking writes corrupted the host app's test database connection.**
|
|
25
|
+
Under `use_transactional_tests` Rails pins one connection per pool and hands that
|
|
26
|
+
same connection to every thread, so the tracker's writer thread interleaved its
|
|
27
|
+
INSERTs with the test's own statements on a single socket. PostgreSQL reported
|
|
28
|
+
this as `message type 0x5a arrived from server while idle` and
|
|
29
|
+
`server sent data ("D" message) without prior row description`, and suites hung
|
|
30
|
+
or failed at random. The gem's own dummy app avoided it with
|
|
31
|
+
`config.async = false if Rails.env.test?`, but the installed initializer never
|
|
32
|
+
shipped that line. The tracker now writes inline whenever the pool's connection
|
|
33
|
+
is shared across threads, and `rails generate rails_pulse:install` adds the
|
|
34
|
+
test-environment line to the initializer. Existing installs should add
|
|
35
|
+
`config.async = false if Rails.env.test?` to `config/initializers/rails_pulse.rb`.
|
|
36
|
+
|
|
10
37
|
## [0.4.0.pre.1] - 2026-09-03
|
|
11
38
|
|
|
12
39
|
This release contains a **breaking schema change** and requires a one-time data
|
|
@@ -48,6 +48,25 @@ module RailsPulse
|
|
|
48
48
|
|
|
49
49
|
private
|
|
50
50
|
|
|
51
|
+
# Column definitions look like: t.text :column_name, comment: "..."
|
|
52
|
+
# The comment capture must tolerate escaped quotes — the http_methods
|
|
53
|
+
# comment embeds a JSON example, [\"GET\",\"POST\"] — so it matches a
|
|
54
|
+
# full Ruby string literal (quotes included) rather than stopping at the
|
|
55
|
+
# first quote character.
|
|
56
|
+
COLUMN_DEFINITION = /t\.(\w+)\s+:([a-zA-Z_][a-zA-Z0-9_]*)(?:.*?comment:\s*("(?:[^"\\]|\\.)*"))?/
|
|
57
|
+
|
|
58
|
+
# Turn the matched Ruby string literal back into the string it denotes, so
|
|
59
|
+
# callers hold the real comment text and re-escape it themselves (the
|
|
60
|
+
# upgrade migration template uses String#inspect). Falls back to stripping
|
|
61
|
+
# the quotes if the literal uses an escape String#undump rejects.
|
|
62
|
+
def decode_comment(literal)
|
|
63
|
+
return nil if literal.nil?
|
|
64
|
+
|
|
65
|
+
literal.undump
|
|
66
|
+
rescue RuntimeError
|
|
67
|
+
literal.delete_prefix('"').delete_suffix('"')
|
|
68
|
+
end
|
|
69
|
+
|
|
51
70
|
# Parse column definitions from a table block
|
|
52
71
|
# Returns hash of column_name => { type:, comment: }
|
|
53
72
|
def parse_table_columns(table_block)
|
|
@@ -55,9 +74,10 @@ module RailsPulse
|
|
|
55
74
|
|
|
56
75
|
table_block.split("\n").each do |line|
|
|
57
76
|
# Match column definitions: t.text :column_name, comment: "..."
|
|
58
|
-
next unless match = line.match(
|
|
77
|
+
next unless match = line.match(COLUMN_DEFINITION)
|
|
59
78
|
|
|
60
|
-
column_type, column_name,
|
|
79
|
+
column_type, column_name, comment_literal = match.captures
|
|
80
|
+
comment = decode_comment(comment_literal)
|
|
61
81
|
|
|
62
82
|
# Skip timestamps and references (Rails handles these)
|
|
63
83
|
next if %w[timestamps references].include?(column_type)
|
|
@@ -4,7 +4,7 @@ class UpgradeRailsPulseTables < ActiveRecord::Migration[<%= @migration_version %
|
|
|
4
4
|
<% @missing_columns.each do |table_name, columns| %>
|
|
5
5
|
<% columns.each do |column_name, definition| %>
|
|
6
6
|
# Add <%= column_name %> column to <%= table_name %>
|
|
7
|
-
add_column :<%= table_name %>, :<%= column_name %>, :<%= definition[:type] %><% if definition[:comment] %>, comment:
|
|
7
|
+
add_column :<%= table_name %>, :<%= column_name %>, :<%= definition[:type] %><% if definition[:comment] %>, comment: <%= definition[:comment].inspect %><% end %>
|
|
8
8
|
<% end %>
|
|
9
9
|
<% end %>
|
|
10
10
|
end
|
|
@@ -6,6 +6,11 @@ RailsPulse.configure do |config|
|
|
|
6
6
|
# Enable or disable Rails Pulse
|
|
7
7
|
config.enabled = true
|
|
8
8
|
|
|
9
|
+
# Tracking writes happen on a background thread by default (see `config.async`
|
|
10
|
+
# under ADVANCED). Transactional tests share one database connection across
|
|
11
|
+
# threads, so write inline there to keep the writer off the test's connection.
|
|
12
|
+
config.async = false if Rails.env.test?
|
|
13
|
+
|
|
9
14
|
# ====================================================================================================
|
|
10
15
|
# THRESHOLDS
|
|
11
16
|
# ====================================================================================================
|
data/lib/rails_pulse/tracker.rb
CHANGED
|
@@ -11,7 +11,7 @@ module RailsPulse
|
|
|
11
11
|
def track_request(data)
|
|
12
12
|
return if RequestStore.store[:skip_recording_rails_pulse_activity]
|
|
13
13
|
|
|
14
|
-
if RailsPulse.configuration.async
|
|
14
|
+
if RailsPulse.configuration.async && !connection_shared_across_threads?
|
|
15
15
|
Thread.new do
|
|
16
16
|
perform_tracking(data)
|
|
17
17
|
rescue => e
|
|
@@ -62,6 +62,22 @@ module RailsPulse
|
|
|
62
62
|
RequestStore.store[:skip_recording_rails_pulse_activity] = false
|
|
63
63
|
end
|
|
64
64
|
|
|
65
|
+
# Transactional tests pin one connection per pool and hand that same
|
|
66
|
+
# connection to every thread that asks for one. A background writer would
|
|
67
|
+
# then interleave its statements with the test's on a single socket, which
|
|
68
|
+
# PostgreSQL reports as "message type 0x5a arrived from server while idle".
|
|
69
|
+
# Rails 7.2+ records the pin in the pool's @pinned_connection; 7.1 sets a
|
|
70
|
+
# @lock_thread on the pool instead. Neither is public API, so read both
|
|
71
|
+
# defensively and treat any failure as "not shared".
|
|
72
|
+
def connection_shared_across_threads?
|
|
73
|
+
pool = RailsPulse::ApplicationRecord.connection_pool
|
|
74
|
+
return true if pool.instance_variable_get(:@pinned_connection)
|
|
75
|
+
|
|
76
|
+
pool.instance_variable_get(:@lock_thread) ? true : false
|
|
77
|
+
rescue StandardError
|
|
78
|
+
false
|
|
79
|
+
end
|
|
80
|
+
|
|
65
81
|
def clear_aborted_transaction(conn)
|
|
66
82
|
raw = conn.raw_connection
|
|
67
83
|
# Non-PostgreSQL adapters don't expose transaction_status, so this is a no-op for them.
|
data/lib/rails_pulse/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rails_pulse
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.4.0.pre.
|
|
4
|
+
version: 0.4.0.pre.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Scott Harvey
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-09-
|
|
11
|
+
date: 2026-09-04 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rails
|
|
@@ -543,7 +543,7 @@ metadata:
|
|
|
543
543
|
bug_tracker_uri: https://github.com/railspulse/rails_pulse/issues
|
|
544
544
|
rubygems_mfa_required: 'true'
|
|
545
545
|
post_install_message: |
|
|
546
|
-
Rails Pulse 0.4.0.pre.
|
|
546
|
+
Rails Pulse 0.4.0.pre.2 installed.
|
|
547
547
|
|
|
548
548
|
UPGRADING from any 0.3.x? This release changes route identity and DROPS
|
|
549
549
|
rails_pulse_routes.method. Back up your database first, then run:
|