outboxable 1.0.0 → 1.0.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/Gemfile.lock +1 -4
- data/lib/generators/outboxable/install_generator.rb +2 -2
- data/lib/outboxable/configuration.rb +6 -6
- data/lib/outboxable/polling_publisher_worker.rb +7 -6
- data/lib/outboxable/version.rb +1 -1
- data/lib/outboxable/worker.rb +3 -2
- data/lib/templates/activerecrod_outbox.rb +1 -1
- data/lib/templates/{mongoid_initializer..rb → mongoid_initializer.rb} +0 -2
- data/lib/templates/mongoid_outbox.rb +25 -10
- metadata +2 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7ff24c145223dcc558818028a2866583266372e1a52cbb0dc63661fdad5f94ea
|
4
|
+
data.tar.gz: 64e19fa685b3f77a85c10bc60f9754a32bbe8534b9aaa5cb153253aefb5bbcb1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9dca7a575abbc63e9b033e3726229ce8abe6254ea049f220f66c9b675c4395efbfdac1a12da0dc5c31f50a65bfdab939ee23809c24d9e2182864fdd0b703754f
|
7
|
+
data.tar.gz: 6673eabf79e2daa9b36bd93c84589dc68f796a22c8b82cf93d035cd9eaaa1b3ba523ee16c9c121c719befe9b1527b3bf32a6c2467ee023b9bfd527b209575ef3
|
data/Gemfile.lock
CHANGED
@@ -1,10 +1,9 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
outboxable (1.0.
|
4
|
+
outboxable (1.0.2)
|
5
5
|
bunny (>= 2.19.0)
|
6
6
|
connection_pool (~> 2.3.0)
|
7
|
-
simple_enum (>= 2.3)
|
8
7
|
|
9
8
|
GEM
|
10
9
|
remote: https://rubygems.org/
|
@@ -85,8 +84,6 @@ GEM
|
|
85
84
|
fugit (~> 1.8)
|
86
85
|
globalid (>= 1.0.1)
|
87
86
|
sidekiq (>= 6)
|
88
|
-
simple_enum (2.3.2)
|
89
|
-
activesupport (>= 4.0.0)
|
90
87
|
sorted_set (1.0.3)
|
91
88
|
rbtree
|
92
89
|
set (~> 1.0)
|
@@ -5,8 +5,8 @@ module Outboxable
|
|
5
5
|
source_root File.expand_path('../../templates', __dir__)
|
6
6
|
class_option :orm, type: :string, default: 'activerecord'
|
7
7
|
|
8
|
-
def initialize
|
9
|
-
super
|
8
|
+
def initialize(*)
|
9
|
+
super(*)
|
10
10
|
|
11
11
|
@orm = options[:orm] || 'activerecord'
|
12
12
|
%w[activerecord mongoid].include?(@orm) || raise(ArgumentError, 'Invalid ORM. Only ActiveRecord and Mongoid are supported.')
|
@@ -6,6 +6,12 @@ module Outboxable
|
|
6
6
|
def self.configure
|
7
7
|
self.configuration ||= Configuration.new
|
8
8
|
yield(configuration)
|
9
|
+
|
10
|
+
# In accordance to sidekiq-cron README: https://github.com/sidekiq-cron/sidekiq-cron#under-the-hood
|
11
|
+
Sidekiq::Options[:cron_poll_interval] = 5
|
12
|
+
|
13
|
+
# Create the cron job for the polling publisher
|
14
|
+
Sidekiq::Cron::Job.create(name: 'OutboxablePollingPublisher', cron: '*/5 * * * * *', class: 'Outboxable::PollingPublisherWorker', args: [{ orm: configuration.orm }])
|
9
15
|
end
|
10
16
|
|
11
17
|
class Configuration
|
@@ -26,12 +32,6 @@ module Outboxable
|
|
26
32
|
raise Error, 'Outboxable Gem only supports Rails but you application does not seem to be a Rails app' unless Object.const_defined?('Rails')
|
27
33
|
raise Error, 'Outboxable Gem only support Rails version 7 and newer' if Rails::VERSION::MAJOR < 7
|
28
34
|
raise Error, 'Outboxable Gem uses the sidekiq-cron Gem. Make sure you add it to your project' unless Object.const_defined?('Sidekiq::Cron')
|
29
|
-
|
30
|
-
# In accordance to sidekiq-cron README: https://github.com/sidekiq-cron/sidekiq-cron#under-the-hood
|
31
|
-
Sidekiq::Options[:cron_poll_interval] = 5
|
32
|
-
|
33
|
-
# Create the cron job for the polling publisher
|
34
|
-
Sidekiq::Cron::Job.create(name: 'OutboxablePollingPublisher', cron: '*/5 * * * * *', class: 'Outboxable::PollingPublisherWorker')
|
35
35
|
end
|
36
36
|
|
37
37
|
def message_broker=(message_broker)
|
@@ -3,24 +3,25 @@ module Outboxable
|
|
3
3
|
include Sidekiq::Job
|
4
4
|
sidekiq_options queue: 'critical'
|
5
5
|
|
6
|
-
def perform
|
7
|
-
|
6
|
+
def perform(args)
|
7
|
+
orm = args['orm']
|
8
|
+
orm == 'mongoid' ? perform_mongoid(orm) : perform_activerecord(orm)
|
8
9
|
end
|
9
10
|
|
10
|
-
def perform_activerecord
|
11
|
+
def perform_activerecord(orm)
|
11
12
|
Outbox.pending.where(last_attempted_at: [..Time.zone.now, nil]).find_in_batches(batch_size: 100).each do |batch|
|
12
13
|
batch.each do |outbox|
|
13
14
|
# This is to prevent a job from being retried too many times. Worst-case scenario is 1 minute delay in jobs.
|
14
|
-
Outboxable::Worker.perform_async(outbox.id)
|
15
|
+
Outboxable::Worker.perform_async(outbox.id, orm)
|
15
16
|
outbox.update(last_attempted_at: 1.minute.from_now, status: :processing, allow_publish: false)
|
16
17
|
end
|
17
18
|
end
|
18
19
|
end
|
19
20
|
|
20
|
-
def perform_mongoid
|
21
|
+
def perform_mongoid(orm)
|
21
22
|
Outbox.pending.where(last_attempted_at: [..Time.zone.now, nil]).each do |outbox|
|
22
23
|
# This is to prevent a job from being retried too many times. Worst-case scenario is 1 minute delay in jobs.
|
23
|
-
Outboxable::Worker.perform_async(outbox.
|
24
|
+
Outboxable::Worker.perform_async(outbox.idempotency_key, orm)
|
24
25
|
outbox.update(last_attempted_at: 1.minute.from_now, status: :processing, allow_publish: false)
|
25
26
|
end
|
26
27
|
end
|
data/lib/outboxable/version.rb
CHANGED
data/lib/outboxable/worker.rb
CHANGED
@@ -4,8 +4,9 @@ module Outboxable
|
|
4
4
|
class Worker
|
5
5
|
include ::Sidekiq::Job
|
6
6
|
|
7
|
-
def perform(outbox_id)
|
8
|
-
Outboxable::PublishingManager.publish(resource: Outbox.find(outbox_id))
|
7
|
+
def perform(outbox_id, orm)
|
8
|
+
Outboxable::PublishingManager.publish(resource: Outbox.find(outbox_id)) if orm == 'activerecord'
|
9
|
+
Outboxable::PublishingManager.publish(resource: Outbox.find_by!(idempotency_key: outbox_id)) if orm == 'mongoid'
|
9
10
|
end
|
10
11
|
end
|
11
12
|
end
|
@@ -4,7 +4,7 @@ class Outbox < ApplicationRecord
|
|
4
4
|
before_save :check_publishing
|
5
5
|
# Callbacks
|
6
6
|
before_create :set_last_attempted_at
|
7
|
-
|
7
|
+
after_save :publish, if: :allow_publish
|
8
8
|
# Enums
|
9
9
|
enum status: { pending: 0, processing: 1, published: 2, failed: 3 }
|
10
10
|
enum size: { single: 0, batch: 1 }
|
@@ -1,13 +1,12 @@
|
|
1
1
|
class Outbox
|
2
2
|
include Mongoid::Document
|
3
3
|
include Mongoid::Timestamps
|
4
|
-
include SimpleEnum::Mongoid
|
5
4
|
|
6
|
-
|
5
|
+
attr_writer :allow_publish
|
7
6
|
|
8
7
|
# Fields
|
9
8
|
field :status, type: String, default: 'pending'
|
10
|
-
field :size,
|
9
|
+
field :size, type: String, default: 'single'
|
11
10
|
|
12
11
|
field :exchange, type: String, default: ''
|
13
12
|
field :routing_key, type: String, default: ''
|
@@ -18,18 +17,19 @@ class Outbox
|
|
18
17
|
|
19
18
|
field :retry_at, type: DateTime, default: nil
|
20
19
|
|
20
|
+
field :idempotency_key, type: String
|
21
|
+
|
21
22
|
field :payload, type: Hash, default: {}
|
22
23
|
field :headers, type: Hash, default: {}
|
23
24
|
|
25
|
+
index({ idempotency_key: 1 }, { unique: true, name: 'idempotency_key_unique_index' })
|
26
|
+
|
24
27
|
before_save :check_publishing
|
28
|
+
before_create :set_idempotency_key
|
25
29
|
|
26
30
|
# Callbacks
|
27
31
|
before_create :set_last_attempted_at
|
28
|
-
|
29
|
-
|
30
|
-
# Enums
|
31
|
-
as_enum :status, { pending: 0, processing: 1, published: 2, failed: 3 }, pluralize_scopes: false, map: :string
|
32
|
-
as_enum :size, { single: 0, batch: 1 }, pluralize_scopes: false, map: :string
|
32
|
+
after_save :publish, if: :allow_publish
|
33
33
|
|
34
34
|
# Validations
|
35
35
|
validates :payload, :exchange, :routing_key, presence: true
|
@@ -42,15 +42,30 @@ class Outbox
|
|
42
42
|
end
|
43
43
|
|
44
44
|
def publish
|
45
|
-
Outboxable::Worker.perform_async(
|
45
|
+
Outboxable::Worker.perform_async(idempotency_key)
|
46
46
|
update(status: :processing, last_attempted_at: 1.minute.from_now, allow_publish: false)
|
47
47
|
end
|
48
48
|
|
49
|
+
def set_idempotency_key
|
50
|
+
self.idempotency_key = SecureRandom.uuid if idempotency_key.blank?
|
51
|
+
end
|
52
|
+
|
49
53
|
def check_publishing
|
50
54
|
self.allow_publish = false if published?
|
51
55
|
end
|
52
56
|
|
53
57
|
def allow_publish
|
54
|
-
@allow_publish
|
58
|
+
return true if @allow_publish.nil?
|
59
|
+
|
60
|
+
@allow_publish
|
61
|
+
end
|
62
|
+
|
63
|
+
%w[pending processing published failed].each do |status|
|
64
|
+
define_method "#{status}?" do
|
65
|
+
self.status == status
|
66
|
+
end
|
67
|
+
|
68
|
+
# define scope
|
69
|
+
scope status, -> { where(status:) }
|
55
70
|
end
|
56
71
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: outboxable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brusk Awat
|
@@ -38,20 +38,6 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: 2.3.0
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: simple_enum
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - ">="
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '2.3'
|
48
|
-
type: :runtime
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - ">="
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '2.3'
|
55
41
|
description: The Outboxable Gem is tailored for Rails applications to implement the
|
56
42
|
transactional outbox pattern. It currently only supports ActiveRecord.
|
57
43
|
email:
|
@@ -81,7 +67,7 @@ files:
|
|
81
67
|
- lib/templates/activerecord_initializer.rb
|
82
68
|
- lib/templates/activerecrod_outbox.rb
|
83
69
|
- lib/templates/create_outboxable_outboxes.rb
|
84
|
-
- lib/templates/mongoid_initializer
|
70
|
+
- lib/templates/mongoid_initializer.rb
|
85
71
|
- lib/templates/mongoid_outbox.rb
|
86
72
|
- sig/outboxable.rbs
|
87
73
|
homepage: https://github.com/broosk1993/outboxable
|