rails-transactional-outbox 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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
  - - ">="