rails-transactional-outbox 0.2.0 → 0.3.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: 60bbddad0806646606ec74645b6cdeb9e4cb36775f661f9a5226822d12e9cd78
4
- data.tar.gz: c7e9b82b9f3c84b9f09b8b27728a55562e524be4ce2e0f16653baeee965941f0
3
+ metadata.gz: 7981d03fa1319ccf83fe5f66ac64869ef024e8add13de49f6af43b26ff39ac3e
4
+ data.tar.gz: e2f5048f5c4f5700b95b247064cc4e2fe9d8601b6df63d39b1e06896aeb1e915
5
5
  SHA512:
6
- metadata.gz: 3848c22971da6d9e727ae2a9430995ad225cbdd06df4fdcc7a6dcb93c98ec0fef7f1e9102ab9eec01d30889449d9ac9a6c33d87a5e239309ebb8bd2ec3366532
7
- data.tar.gz: 4895905ed12adead29478d3d2b235625587c2ad43f65b6e87592a1b19010af2097dfd149c2567c9ef91fee4838e45aa353a0f7a0202bb977bbdbd5e7065d6574
6
+ metadata.gz: e903bcb6ee6c1b58d77b7c9b0dff41297e44b81c45457df0888caf6ecbdf2fa0f7254f9424cac14db2d31933e6f9790438cf2a9e232cb6af06405f9985221ceb
7
+ data.tar.gz: 8296fbab0324e8b0fa6410187e0fb59392121aecfccab2301fecff8fc1b51d815eaa71af78fdbd1d7c67f11573fc06d9598ec9e719d01738fc72d92646a33e0a
data/CHANGELOG.md CHANGED
@@ -1,8 +1,16 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.3.0] - 2022-12-20
4
+
5
+ - Move to file-based healthchecks, instead of using Redis-based ones.
6
+
7
+ ## [0.2.1] - 2022-09-08
8
+
9
+ - Simplify update to 0.2 (`causality_key` is not required if `outbox_entry_causality_key_resolver` is not used)
10
+
3
11
  ## [0.2.0] - 2022-09-08
4
12
 
5
- - Introduce `RailsTransactionalOutbox::OutboxEntriesProcessors::OrderedByCausalityKeyProcessor`
13
+ - Introduce `RailsTransactionalOutbox::OutboxEntriesProcessors::OrderedByCausalityKeyProcessor`
6
14
 
7
15
  ## [0.1.0] - 2022-08-23
8
16
 
data/Gemfile.lock CHANGED
@@ -9,12 +9,12 @@ GIT
9
9
  PATH
10
10
  remote: .
11
11
  specs:
12
- rails-transactional-outbox (0.2.0)
12
+ rails-transactional-outbox (0.3.0)
13
13
  activerecord (>= 5)
14
14
  activesupport (>= 3.2)
15
15
  concurrent-ruby
16
16
  dry-monitor
17
- redis
17
+ file-based-healthcheck
18
18
  sigurd
19
19
  zeitwerk
20
20
 
@@ -40,21 +40,23 @@ GEM
40
40
  msgpack
41
41
  debase-ruby_core_source (0.10.16)
42
42
  diff-lcs (1.5.0)
43
- dry-configurable (0.15.0)
43
+ dry-configurable (1.0.1)
44
+ dry-core (~> 1.0, < 2)
45
+ zeitwerk (~> 2.6)
46
+ dry-core (1.0.0)
44
47
  concurrent-ruby (~> 1.0)
45
- dry-core (~> 0.6)
46
- dry-core (0.8.1)
48
+ zeitwerk (~> 2.6)
49
+ dry-events (1.0.1)
47
50
  concurrent-ruby (~> 1.0)
48
- dry-events (0.3.0)
49
- concurrent-ruby (~> 1.0)
50
- dry-core (~> 0.5, >= 0.5)
51
- dry-monitor (0.6.3)
52
- dry-configurable (~> 0.13, >= 0.13.0)
53
- dry-core (~> 0.5, >= 0.5)
54
- dry-events (~> 0.2)
55
- zeitwerk (~> 2.5)
51
+ dry-core (~> 1.0, < 2)
52
+ dry-monitor (1.0.1)
53
+ dry-configurable (~> 1.0, < 2)
54
+ dry-core (~> 1.0, < 2)
55
+ dry-events (~> 1.0, < 2)
56
56
  exponential-backoff (0.0.4)
57
57
  ffi (1.15.5)
58
+ file-based-healthcheck (0.1.1)
59
+ activesupport (>= 3.2)
58
60
  i18n (1.12.0)
59
61
  concurrent-ruby (~> 1.0)
60
62
  json (2.6.2)
@@ -119,7 +121,7 @@ GEM
119
121
  tzinfo (2.0.5)
120
122
  concurrent-ruby (~> 1.0)
121
123
  unicode-display_width (2.2.0)
122
- zeitwerk (2.6.0)
124
+ zeitwerk (2.6.6)
123
125
 
124
126
  PLATFORMS
125
127
  x86_64-darwin-18
data/README.md CHANGED
@@ -29,21 +29,21 @@ Create the initializer with the following content:
29
29
  ``` rb
30
30
  Rails.application.config.to_prepare do
31
31
  RailsTransactionalOutbox.configure do |config|
32
- config.database_connection_provider = ActiveRecord::Base # required
32
+ config.database_connection_provider = ActiveRecord::Base # required
33
33
  config.transaction_provider = ActiveRecord::Base # required
34
34
  config.logger = Rails.logger # required
35
35
  config.outbox_model = OutboxEntry # required
36
- config.error_handler = Sentry # non-required, but highly recommended, defaults to RailsTransactionalOutbox::ErrorHandlers::NullErrorHandler
37
-
36
+ config.error_handler = Sentry # non-required, but highly recommended, defaults to RailsTransactionalOutbox::ErrorHandlers::NullErrorHandler. When using Sentry, you will probably want to exclude SignalException `config.excluded_exceptions += ["SignalException"]`.
37
+
38
38
  config.transactional_outbox_worker_sleep_seconds = 1 # optional, defaults to 0.5
39
- config.transactional_outbox_worker_idle_delay_multiplier = 5 # optional, defaults to 1, if there are no outbox entries to be processed, then the sleep time for the thread will be equal to transactional_outbox_worker_idle_delay_multiplier * transactional_outbox_worker_sleep_seconds
39
+ config.transactional_outbox_worker_idle_delay_multiplier = 5 # optional, defaults to 1, if there are no outbox entries to be processed, then the sleep time for the thread will be equal to transactional_outbox_worker_idle_delay_multiplier * transactional_outbox_worker_sleep_seconds
40
40
  config.outbox_batch_size = 100 # optional, defaults to 100
41
41
  config.add_record_processor(MyCustomOperationProcerssor) # optional, by default it contains only one processor for ActiveRecord, but you could add more
42
-
42
+
43
43
  config.lock_client = Redlock::Client.new([ENV["REDIS_URL"]]) # required if you want to use RailsTransactionalOutbox::OutboxEntriesProcessors::OrderedByCausalityKeyProcessor, defaults to RailsTransactionalOutbox::NullLockClient. Check its interface and the interface of `redlock` gem. To cut the long story short, when the lock is acquired, a hash with the structure outlined in RailsTransactionalOutbox::NullLockClient should be yielded, if the lock is not acquired, a nil should be yielded.
44
44
  config.lock_expiry_time = 10_000 # not required, defaults to 10_000, the unit is milliseconds
45
45
  config.outbox_entries_processor = `RailsTransactionalOutbox::OutboxEntriesProcessors::OrderedByCausalityKeyProcessor`.new # not required, defaults to RailsTransactionalOutbox::OutboxEntriesProcessors::NonOrderedProcessor.new
46
- config.outbox_entry_causality_key_resolver = ->(model) { model.tenant_id } # not required, defaults to a lambda returning nil. Needed when using `outbox_entry_causality_key_resolver`
46
+ config.outbox_entry_causality_key_resolver = ->(model) { model.tenant_id } # not required, defaults to a lambda returning nil. Needed when using `outbox_entry_causality_key_resolver`
47
47
  end
48
48
  end
49
49
  ```
@@ -53,7 +53,7 @@ Create OutboxEntry model (or use a different name, just make sure to adjust conf
53
53
  ``` rb
54
54
  class OutboxEntry < ApplicationRecord
55
55
  include RailsTransactionalOutbox::OutboxModel
56
-
56
+
57
57
  # optional, if you want to use encryption
58
58
  crypt_keeper :changeset, :arguments, encryptor: :postgres_pgp, key: ENV.fetch("CRYPT_KEEPER_KEY"), encoding: "UTF-8"
59
59
  outbox_encrypt_json_for :changeset, :arguments
@@ -93,7 +93,7 @@ end
93
93
 
94
94
  Keep in mind that `arguments` and `changeset` are `text` columns here. If you don't want to use encryption, replace them with `jsonb` columns:
95
95
 
96
- ```rb
96
+ ```rb
97
97
  t.jsonb "arguments", null: false, default: {}
98
98
  t.jsonb "changeset", null: false, default: {}
99
99
  ```
@@ -105,7 +105,7 @@ As the last step, include `RailsTransactionalOutbox::ReliableModel` module in th
105
105
  ``` ruby
106
106
  class User < ActiveRecord::Base
107
107
  include RailsTransactionalOutbox::ReliableModel
108
- end
108
+ end
109
109
  ```
110
110
 
111
111
  Now, you can just replace `after_commit` callbacks with `reliable_after_commit`. The interface is going to be the same as for `after_commit`:
@@ -247,9 +247,8 @@ end
247
247
 
248
248
  ### Health Checks
249
249
 
250
- First, you need to set `REDIS_URL` ENV variable to provide the URL for Redis.
251
250
 
252
- Then, you need to explicitly enable the health check (e.g. in the initializer):
251
+ Then, Uou need to explicitly enable the health check (e.g. in the initializer):
253
252
 
254
253
  ``` rb
255
254
  RailsTransactionalOutbox.enable_outbox_worker_healthcheck
@@ -261,8 +260,6 @@ To perform the actual health check, use `bin/rails_transactional_outbox_health_c
261
260
  bundle exec rails_transactional_outbox_health_check
262
261
  ```
263
262
 
264
- The logic is based on checking a special value in Redis that is set (and unset) for a given container when Outbox workers are initialized/stopped/processing messages.
265
-
266
263
  It works for both readiness and liveness checks.
267
264
 
268
265
  #### Events, hooks and monitors
@@ -1,46 +1,45 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "redis"
4
-
5
3
  class RailsTransactionalOutbox
6
4
  class HealthCheck
7
5
  KEY_PREFIX = "__rails_transactional__outbox_worker__running__"
8
- VALUE = "OK"
9
- private_constant :KEY_PREFIX, :VALUE
6
+ TMP_DIR = "/tmp"
7
+ private_constant :KEY_PREFIX, :TMP_DIR
10
8
 
11
- def self.check(redis_url: ENV.fetch("REDIS_URL", nil), hostname: ENV.fetch("HOSTNAME", nil),
12
- expiry_time_in_seconds: 120)
13
- new(redis_url: redis_url, hostname: hostname, expiry_time_in_seconds: expiry_time_in_seconds).check
9
+ def self.check(hostname: ENV.fetch("HOSTNAME", nil), expiry_time_in_seconds: 120)
10
+ new(hostname: hostname, expiry_time_in_seconds: expiry_time_in_seconds).check
14
11
  end
15
12
 
16
- attr_reader :redis_client, :hostname, :expiry_time_in_seconds
13
+ attr_reader :hostname, :expiry_time_in_seconds
17
14
 
18
- def initialize(redis_url: ENV.fetch("REDIS_URL", nil), hostname: ENV.fetch("HOSTNAME", nil),
19
- expiry_time_in_seconds: 120)
20
- @redis_client = Redis.new(url: redis_url)
15
+ def initialize(hostname: ENV.fetch("HOSTNAME", nil), expiry_time_in_seconds: 120)
21
16
  @hostname = hostname
22
17
  @expiry_time_in_seconds = expiry_time_in_seconds
23
18
  end
24
19
 
25
20
  def check
26
- value = redis_client.get(key)
27
- if value == VALUE
21
+ if healthcheck_storage.running?
28
22
  ""
29
23
  else
30
- "[Rails Transactional Outbox Worker - expected #{VALUE} under #{key}, found: #{value}] "
24
+ "[Rails Transactional Outbox Worker healthcheck failed]"
31
25
  end
32
26
  end
33
27
 
34
28
  def register_heartbeat
35
- redis_client.set(key, VALUE, ex: expiry_time_in_seconds)
29
+ healthcheck_storage.touch
36
30
  end
37
31
 
38
32
  def worker_stopped
39
- redis_client.del(key)
33
+ healthcheck_storage.remove
40
34
  end
41
35
 
42
36
  private
43
37
 
38
+ def healthcheck_storage
39
+ @healthcheck_storage ||= FileBasedHealthcheck.new(directory: TMP_DIR, filename: key,
40
+ time_threshold: expiry_time_in_seconds)
41
+ end
42
+
44
43
  def key
45
44
  "#{KEY_PREFIX}#{hostname}"
46
45
  end
@@ -25,7 +25,7 @@ class RailsTransactionalOutbox
25
25
  event_name: "#{model.model_name.singular}_#{event_name_suffix(event_type)}",
26
26
  context: RailsTransactionalOutbox::RecordProcessors::ActiveRecordProcessor.context,
27
27
  causality_key: outbox_entry_causality_key_resolver.call(model)
28
- }
28
+ }.compact
29
29
  end
30
30
 
31
31
  def event_name_suffix(event_type)
@@ -3,5 +3,5 @@
3
3
  class RailsTransactionalOutbox
4
4
  module Version
5
5
  end
6
- VERSION = "0.2.0"
6
+ VERSION = "0.3.0"
7
7
  end
@@ -5,6 +5,7 @@ require "logger"
5
5
  require "dry-monitor"
6
6
  require "sigurd"
7
7
  require "concurrent-ruby"
8
+ require "file-based-healthcheck"
8
9
 
9
10
  class RailsTransactionalOutbox
10
11
  def self.loader
@@ -34,7 +34,7 @@ Gem::Specification.new do |spec|
34
34
  spec.add_dependency "activesupport", ">= 3.2"
35
35
  spec.add_dependency "concurrent-ruby"
36
36
  spec.add_dependency "dry-monitor"
37
- spec.add_dependency "redis"
37
+ spec.add_dependency "file-based-healthcheck"
38
38
  spec.add_dependency "sigurd"
39
39
  spec.add_dependency "zeitwerk"
40
40
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails-transactional-outbox
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Karol Galanciak
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-09-08 00:00:00.000000000 Z
11
+ date: 2022-12-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -67,7 +67,7 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: redis
70
+ name: file-based-healthcheck
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - ">="