standard_ledger 0.6.0 → 0.7.0

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: 8f6aa5d56ba73fe170790d016b50f00aec95f563346a08c36f8823d05fbddd98
4
- data.tar.gz: dc1ef4c96e69b6a8d4832ce1f80dc6a979d63dc25ff059ed77794b829f414e7f
3
+ metadata.gz: ddedb70c2937f7108178cce27f7150b58c39c5aadfdab2561947b626bd345d9c
4
+ data.tar.gz: be910d616703d17691bdc6f184247b5efe78bc959006c24f43ee4bfbeb5df263
5
5
  SHA512:
6
- metadata.gz: 54f927af7564ee7e9319a2fd87358a86e91ab55c7d3fea872dc9f821efc40cde0cd31b55cdf4b90e7bfb138bb501a7e9888358a2645f27c662058ba2fd2ef869
7
- data.tar.gz: 108ce4c242c054512e6f3f173cf683dc9f71ee08882ed82dd505be092af6fb08f7b97b635aa5685ed5c08f7257e6ad285d327a2b4a9bd1f07c2ee1bcfcda19d2
6
+ metadata.gz: 1bd764a4596fb6468f5ffa9b2d51e39a5203f6135bbdbde6cacec33091aa0e86cedaa1393392f417378a720f6e26987438c8a46fc80028204ecf0250ed3a7c49
7
+ data.tar.gz: 829aad11a875317df036555736281f0ca6d961045bd3a5b2dd6090592ce0aabce772583b34d7fd403c69a4f331bb11f46e6a9622ccc62f510fb0574dea8bd85a
data/CHANGELOG.md CHANGED
@@ -6,6 +6,51 @@ project adheres to [Semantic Versioning](https://semver.org/).
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.7.0] - 2026-09-24
10
+
11
+ The Phase 4 release. The removals the cleanup plan scheduled for it (the
12
+ `scheduler` config, `PartialFailure`, and the engine's no-op initializer)
13
+ already shipped in 0.6.0, and 0.6.0 deprecated nothing, so this release only
14
+ changes how `refresh!` reports failures. It is a minor bump because hosts that
15
+ report refresh failures themselves should delete that code.
16
+
17
+ ### Changed
18
+ - **`StandardLedger.refresh!` reports SQL failures through `Rails.error`.**
19
+ When the `REFRESH` statement raises, the gem emits `projection.failed` (as
20
+ before), then calls `Rails.error.report(error, handled: false,
21
+ severity: :error, context: { view:, concurrently: }, source:
22
+ "standard_ledger")`, then re-raises. It falls back to
23
+ `ActiveSupport.error_reporter` outside Rails. A reporter that raises is
24
+ ignored, so it can never mask the refresh error. Input errors raised before
25
+ any SQL runs are not reported (`ArgumentError`, `RefreshInsideTransaction`).
26
+ **No double reports:** Rails' `ErrorReporter` flags a reported exception
27
+ and skips it when the same object is reported again. That covers a host
28
+ rescue that reports and re-raises, and the executor wrapping the job.
29
+ - The `:auto` catalog-probe failure report (handled, `:warning`) now goes
30
+ through the same `StandardLedger.report_error` helper (`@api private`).
31
+ Its payload is unchanged.
32
+
33
+ ### Upgrade notes (0.6.x → 0.7.0)
34
+ 1. Bump to `gem "standard_ledger", "~> 0.7"`. Nothing was removed, so no code
35
+ change is required.
36
+ 2. **Optional cleanup:** delete any report-and-re-raise rescue around
37
+ `refresh!`. Grepped `origin/main` of all consumers on 2026-09-24:
38
+ - luminality-web `app/jobs/refresh_admin_dashboard_metrics_job.rb:20-27`
39
+ (`rescue StandardError => e; Rails.error.report(e, handled: true,
40
+ context: { view: "admin_dashboard_metrics" }); raise`). Delete the rescue
41
+ and fix the header comment ("…does not report").
42
+ - sidekick-web `app/jobs/refresh_materialized_views_job.rb` has no rescue.
43
+ Its refresh failures are now reported by the gem, with view context,
44
+ before the job runner sees them.
45
+ - jumpdrive-web and fundbright-web don't call `refresh!`.
46
+ 3. **Expect a different Sentry grouping context** for refresh failures:
47
+ `source: "standard_ledger"` and `context.view`. The error class and
48
+ backtrace are unchanged.
49
+ 4. Sorbet apps: regenerate the gem RBI (`bin/tapioca gem standard_ledger`).
50
+ jumpdrive-web's `control-plane/config/initializers/standard_ledger.rb:12-13`
51
+ still mentions the removed `scheduler`/`default_async_*` config in a
52
+ comment. The comment is historical and harmless.
53
+
9
54
  ## [0.6.0] - 2026-09-24
10
55
 
11
56
  A breaking release. The declarative projection engine is removed, and the gem
data/README.md CHANGED
@@ -129,14 +129,21 @@ with `concurrently: false` can pass `concurrently: :auto` instead.
129
129
 
130
130
  `refresh!` returns a success Result with
131
131
  `projections[:refreshed] = [{ view:, concurrently: }]` (the concurrency mode
132
- that was actually used). If the SQL fails, it emits `projection.failed` and
133
- re-raises so your job runner can retry. View names must be bare or
134
- `schema.view` identifiers. Anything else raises `ArgumentError`.
132
+ that was actually used). If the SQL fails, it emits `projection.failed`,
133
+ reports the error to `Rails.error` (`handled: false`, `severity: :error`,
134
+ `context: { view:, concurrently: }`, `source: "standard_ledger"`), and
135
+ re-raises so your job runner can retry. Since 0.7 you don't need a
136
+ report-and-re-raise rescue around `refresh!` in your job. An existing one is
137
+ harmless: Rails skips an exception object it has already reported, so the
138
+ failure is reported once. Input errors (an invalid view name, an unknown
139
+ `concurrently:`, `RefreshInsideTransaction`) are raised before any SQL runs
140
+ and are not reported by the gem. View names must be bare or `schema.view`
141
+ identifiers. Anything else raises `ArgumentError`.
135
142
 
136
143
  ## Installation
137
144
 
138
145
  ```ruby
139
- gem "standard_ledger", "~> 0.6"
146
+ gem "standard_ledger", "~> 0.7"
140
147
  ```
141
148
 
142
149
  (Don't reintroduce a `git:` reference. It makes a bare `bundle install` a
@@ -44,8 +44,15 @@ module StandardLedger
44
44
  end
45
45
 
46
46
  # Issue `REFRESH MATERIALIZED VIEW [CONCURRENTLY] <view_name>` and emit
47
- # `<prefix>.projection.refreshed` on success, or
48
- # `<prefix>.projection.failed` before re-raising on SQL failure.
47
+ # `<prefix>.projection.refreshed` on success. On SQL failure, emit
48
+ # `<prefix>.projection.failed`, report the error through `Rails.error`
49
+ # (`handled: false`, `severity: :error`) and re-raise.
50
+ #
51
+ # Reporting before the re-raise means host jobs no longer need their
52
+ # own report-and-re-raise rescue. It cannot double-report: Rails'
53
+ # ErrorReporter flags a reported exception and skips it when the same
54
+ # object is reported again (by a host rescue, or by the executor that
55
+ # wraps the job).
49
56
  #
50
57
  # The view name is validated against a SQL-identifier regex at the
51
58
  # boundary as defence in depth — a careless host could pass through a
@@ -72,6 +79,10 @@ module StandardLedger
72
79
  "#{prefix}.projection.failed",
73
80
  view: view_name.to_s, concurrently: concurrently, mode: :matview, error: e
74
81
  )
82
+ StandardLedger.report_error(
83
+ e, handled: false, severity: :error,
84
+ context: { view: view_name.to_s, concurrently: concurrently }
85
+ )
75
86
  raise
76
87
  end
77
88
 
@@ -140,23 +151,13 @@ module StandardLedger
140
151
 
141
152
  boolean(row["populated"]) && boolean(row["unique_index"])
142
153
  rescue StandardError => e
143
- report_error(e, view: view_name.to_s)
154
+ StandardLedger.report_error(e, handled: true, severity: :warning, context: { view: view_name.to_s })
144
155
  false
145
156
  end
146
157
 
147
158
  def boolean(value)
148
159
  ActiveModel::Type::Boolean.new.cast(value) == true
149
160
  end
150
-
151
- def report_error(error, context)
152
- reporter =
153
- if defined?(::Rails) && ::Rails.respond_to?(:error)
154
- ::Rails.error
155
- elsif ActiveSupport.respond_to?(:error_reporter)
156
- ActiveSupport.error_reporter
157
- end
158
- reporter&.report(error, handled: true, severity: :warning, context: context, source: "standard_ledger")
159
- end
160
161
  end
161
162
  end
162
163
  end
@@ -1,3 +1,3 @@
1
1
  module StandardLedger
2
- VERSION = "0.6.0"
2
+ VERSION = "0.7.0"
3
3
  end
@@ -92,9 +92,16 @@ module StandardLedger
92
92
 
93
93
  # Refresh a host-owned materialized view. Issues
94
94
  # `REFRESH MATERIALIZED VIEW [CONCURRENTLY] <view_name>` against the
95
- # active connection and emits `<prefix>.projection.refreshed` on success
96
- # (or `<prefix>.projection.failed` on raise, before re-raising — the
97
- # host's job runner needs to see the failure to drive its retry path).
95
+ # active connection and emits `<prefix>.projection.refreshed` on success.
96
+ # When the refresh SQL raises, it emits `<prefix>.projection.failed`,
97
+ # reports the error through `Rails.error` (`handled: false`,
98
+ # `severity: :error`, `context: { view:, concurrently: }`,
99
+ # `source: "standard_ledger"`) and re-raises, so the host's job runner
100
+ # still drives its retry path. Hosts don't need their own
101
+ # report-and-re-raise; Rails skips an exception it has already reported,
102
+ # so an existing one is harmless. Argument errors and
103
+ # `RefreshInsideTransaction` are programming errors raised before any
104
+ # SQL runs; they are not reported by the gem.
98
105
  #
99
106
  # @example scheduled job refreshing a list of views
100
107
  # VIEWS.each { |view| StandardLedger.refresh!(view, concurrently: :auto) }
@@ -130,6 +137,23 @@ module StandardLedger
130
137
  )
131
138
  end
132
139
 
140
+ # Report +error+ through `Rails.error` (or `ActiveSupport.error_reporter`
141
+ # outside Rails) with `source: "standard_ledger"`. A reporter failure is
142
+ # swallowed so it can never mask the error being reported.
143
+ #
144
+ # @api private
145
+ def report_error(error, handled:, severity:, context:)
146
+ reporter =
147
+ if defined?(::Rails) && ::Rails.respond_to?(:error)
148
+ ::Rails.error
149
+ elsif ActiveSupport.respond_to?(:error_reporter)
150
+ ActiveSupport.error_reporter
151
+ end
152
+ reporter&.report(error, handled: handled, severity: severity, context: context, source: "standard_ledger")
153
+ rescue StandardError
154
+ nil
155
+ end
156
+
133
157
  private
134
158
 
135
159
  # Resolve the kind column name for an entry class. Falls back to `:kind`
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: standard_ledger
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jaryl Sim