outboxable 0.1.7 → 1.0.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: b35b65aa492459dcaf6262e1f1a531eeccdf5a146ba1007d1a47068c55f44337
4
- data.tar.gz: a74c84eed72b6bd893ef6d9afc79917618adc9cde39d5afef5ba83bf99f9dd1d
3
+ metadata.gz: 6289db937af7c6072908dce5da1a44a5145c9a4065bcd3705f847ea39e6c7c57
4
+ data.tar.gz: 89a5d2581f353528fd78e0c19443163d625d2981fa443b5db99a31554001e93d
5
5
  SHA512:
6
- metadata.gz: 303468322166f4c59132e3e405d005f1e40e1d36802a493b6ddcd0fed54ab831770a7cc8f19d52f08ecd3c5644181bf9cdb4f46a47c1adc6a39662332da091a1
7
- data.tar.gz: 51c9e821c2b7b908ea9358793d4e0007faabe324f03de74d7dca882a720bc77ecbd2aa0d5933ce360f25403ebb79c780977e8f156e24bf616324587aef8b27b0
6
+ metadata.gz: dcefad48f356f8d18e44ac7431464f3b1687505fa6241e4d472ad67f215a00e0b5d0da5f690b028aae34c97564d60c5db1c331a37151b02c69d5b60823c029e9
7
+ data.tar.gz: 810dd5e03320ddc4812e5f15db86521fe3e29f4dc69bb92d64dbff822cceddccb71c25e99573edf8cf6d191aa8992d58e7a8fd144a28598def81b63e6614c567
data/Gemfile.lock CHANGED
@@ -1,9 +1,10 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- outboxable (0.1.6)
4
+ outboxable (1.0.0)
5
5
  bunny (>= 2.19.0)
6
6
  connection_pool (~> 2.3.0)
7
+ simple_enum (>= 2.3)
7
8
 
8
9
  GEM
9
10
  remote: https://rubygems.org/
@@ -84,6 +85,8 @@ GEM
84
85
  fugit (~> 1.8)
85
86
  globalid (>= 1.0.1)
86
87
  sidekiq (>= 6)
88
+ simple_enum (2.3.2)
89
+ activesupport (>= 4.0.0)
87
90
  sorted_set (1.0.3)
88
91
  rbtree
89
92
  set (~> 1.0)
@@ -3,24 +3,37 @@ module Outboxable
3
3
  include Rails::Generators::Migration
4
4
 
5
5
  source_root File.expand_path('../../templates', __dir__)
6
+ class_option :orm, type: :string, default: 'activerecord'
7
+
8
+ def initialize
9
+ super
10
+
11
+ @orm = options[:orm] || 'activerecord'
12
+ %w[activerecord mongoid].include?(@orm) || raise(ArgumentError, 'Invalid ORM. Only ActiveRecord and Mongoid are supported.')
13
+ end
6
14
 
7
15
  # Copy initializer into user app
8
16
  def copy_initializer
9
- copy_file('initializer.rb', 'config/initializers/z_outboxable.rb')
17
+ copy_file('activerecod_initializer.rb', 'config/initializers/z_outboxable.rb') if @orm == 'activerecord'
18
+ copy_file('mongoid_initializer.rb', 'config/initializers/z_outboxable.rb') if @orm == 'mongoid'
10
19
  end
11
20
 
12
21
  # Copy user information (model & Migrations) into user app
13
22
  def create_user_model
14
23
  target_path = 'app/models/outbox.rb'
24
+
15
25
  if Rails.root.join(target_path).exist?
16
26
  say_status('skipped', 'Model outbox already exists')
17
27
  else
18
- template('outbox.rb', target_path)
28
+ template('activerecrod_outbox.rb', target_path) if @orm == 'activerecord'
29
+ template('mongoid_outbox.rb', target_path) if @orm == 'mongoid'
19
30
  end
20
31
  end
21
32
 
22
33
  # Copy migrations
23
34
  def copy_migrations
35
+ return if @orm == 'mongoid'
36
+
24
37
  if self.class.migration_exists?('db/migrate', 'create_outboxable_outboxes')
25
38
  say_status('skipped', 'Migration create_outboxable_outboxes already exists')
26
39
  else
@@ -10,7 +10,7 @@ module Outboxable
10
10
 
11
11
  class Configuration
12
12
  ALLOWED_MESSAGE_BROKERS = %i[rabbitmq].freeze
13
- ALLOWED_ORMS = %i[activerecord].freeze
13
+ ALLOWED_ORMS = %i[activerecord mongoid].freeze
14
14
 
15
15
  attr_accessor :rabbitmq_host,
16
16
  :rabbitmq_port,
@@ -4,13 +4,25 @@ module Outboxable
4
4
  sidekiq_options queue: 'critical'
5
5
 
6
6
  def perform
7
+ Outboxable.configuration.orm == :mongoid ? perform_mongoid : perform_activerecord
8
+ end
9
+
10
+ def perform_activerecord
7
11
  Outbox.pending.where(last_attempted_at: [..Time.zone.now, nil]).find_in_batches(batch_size: 100).each do |batch|
8
12
  batch.each do |outbox|
9
13
  # This is to prevent a job from being retried too many times. Worst-case scenario is 1 minute delay in jobs.
10
14
  Outboxable::Worker.perform_async(outbox.id)
11
- outbox.update(last_attempted_at: 1.minute.from_now, status: :processing)
15
+ outbox.update(last_attempted_at: 1.minute.from_now, status: :processing, allow_publish: false)
12
16
  end
13
17
  end
14
18
  end
19
+
20
+ def perform_mongoid
21
+ Outbox.pending.where(last_attempted_at: [..Time.zone.now, nil]).each do |outbox|
22
+ # 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.id)
24
+ outbox.update(last_attempted_at: 1.minute.from_now, status: :processing, allow_publish: false)
25
+ end
26
+ end
15
27
  end
16
28
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Outboxable
4
- VERSION = '0.1.7'
4
+ VERSION = '1.0.0'
5
5
  end
data/lib/outboxable.rb CHANGED
@@ -20,7 +20,7 @@ module Outboxable
20
20
  after_create :instantiate_outbox_for_create, if: proc { |object| object.check_outbox_condition(object:, operation: :create) }
21
21
  after_update :instantiate_outbox_for_update, if: proc { |object| object.check_outbox_condition(object:, operation: :update) }
22
22
 
23
- has_many :outboxes, as: :outboxable, autosave: false
23
+ has_many :outboxes, as: :outboxable, dependent: :destroy
24
24
 
25
25
  def instantiate_outbox(routing_key:)
26
26
  outboxes.new(
@@ -1,9 +1,9 @@
1
1
  class Outbox < ApplicationRecord
2
2
  attribute :allow_publish, :boolean, default: true
3
3
 
4
+ before_save :check_publishing
4
5
  # Callbacks
5
6
  before_create :set_last_attempted_at
6
- before_save :check_publishing
7
7
  after_commit :publish, if: :allow_publish?
8
8
  # Enums
9
9
  enum status: { pending: 0, processing: 1, published: 2, failed: 3 }
@@ -21,7 +21,7 @@ class Outbox < ApplicationRecord
21
21
 
22
22
  def publish
23
23
  Outboxable::Worker.perform_async(id)
24
- update(status: :processing, last_attempted_at: 1.minute.from_now)
24
+ update(status: :processing, last_attempted_at: 1.minute.from_now, allow_publish: false)
25
25
  end
26
26
 
27
27
  def check_publishing
@@ -0,0 +1,38 @@
1
+ require 'simple_enum/mongoid'
2
+
3
+ # This monkey patch allows you to customize the message format that you publish to your broker.
4
+ # By default, Outboxable publishes a CloudEvent message to your broker.
5
+ module Outboxable
6
+ module RabbitMq
7
+ class Publisher
8
+ # Override this method to customize the message format that you publish to your broker
9
+ # DO NOT CHANGE THE METHOD SIGNATURE
10
+ def to_envelope(resource:)
11
+ {
12
+ id: resource.id,
13
+ source: 'http://localhost:3000',
14
+ specversion: '1.0',
15
+ type: resource.routing_key,
16
+ datacontenttype: 'application/json',
17
+ data: resource.payload
18
+ }.to_json
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ Outboxable.configure do |config|
25
+ # Specify the ORM you are using. For now, only ActiveRecord is supported.
26
+ config.orm = :mongoid
27
+
28
+ # Specify the message broker you are using. For now, only RabbitMQ is supported.
29
+ config.message_broker = :rabbitmq
30
+
31
+ # RabbitMQ configurations
32
+ config.rabbitmq_host = ENV.fetch('RABBITMQ__HOST')
33
+ config.rabbitmq_port = ENV.fetch('RABBITMQ__PORT', 5672)
34
+ config.rabbitmq_user = ENV.fetch('RABBITMQ__USERNAME')
35
+ config.rabbitmq_password = ENV.fetch('RABBITMQ__PASSWORD')
36
+ config.rabbitmq_vhost = ENV.fetch('RABBITMQ__VHOST')
37
+ config.rabbitmq_event_bus_exchange = ENV.fetch('EVENTBUS__EXCHANGE_NAME')
38
+ end
@@ -0,0 +1,56 @@
1
+ class Outbox
2
+ include Mongoid::Document
3
+ include Mongoid::Timestamps
4
+ include SimpleEnum::Mongoid
5
+
6
+ attr_accessor :allow_publish
7
+
8
+ # Fields
9
+ field :status, type: String, default: 'pending'
10
+ field :size, type: String, default: 'single'
11
+
12
+ field :exchange, type: String, default: ''
13
+ field :routing_key, type: String, default: ''
14
+
15
+ field :attempts, type: Integer, default: 0
16
+
17
+ field :last_attempted_at, type: DateTime, default: nil
18
+
19
+ field :retry_at, type: DateTime, default: nil
20
+
21
+ field :payload, type: Hash, default: {}
22
+ field :headers, type: Hash, default: {}
23
+
24
+ before_save :check_publishing
25
+
26
+ # Callbacks
27
+ before_create :set_last_attempted_at
28
+ after_commit :publish, if: :allow_publish?
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
33
+
34
+ # Validations
35
+ validates :payload, :exchange, :routing_key, presence: true
36
+
37
+ # Associations
38
+ belongs_to :outboxable, polymorphic: true, optional: true
39
+
40
+ def set_last_attempted_at
41
+ self.last_attempted_at = 10.seconds.from_now
42
+ end
43
+
44
+ def publish
45
+ Outboxable::Worker.perform_async(id)
46
+ update(status: :processing, last_attempted_at: 1.minute.from_now, allow_publish: false)
47
+ end
48
+
49
+ def check_publishing
50
+ self.allow_publish = false if published?
51
+ end
52
+
53
+ def allow_publish
54
+ @allow_publish || true
55
+ end
56
+ 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: 0.1.7
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brusk Awat
@@ -38,6 +38,20 @@ 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'
41
55
  description: The Outboxable Gem is tailored for Rails applications to implement the
42
56
  transactional outbox pattern. It currently only supports ActiveRecord.
43
57
  email:
@@ -64,9 +78,11 @@ files:
64
78
  - lib/outboxable/rabbitmq/publisher.rb
65
79
  - lib/outboxable/version.rb
66
80
  - lib/outboxable/worker.rb
81
+ - lib/templates/activerecord_initializer.rb
82
+ - lib/templates/activerecrod_outbox.rb
67
83
  - lib/templates/create_outboxable_outboxes.rb
68
- - lib/templates/initializer.rb
69
- - lib/templates/outbox.rb
84
+ - lib/templates/mongoid_initializer..rb
85
+ - lib/templates/mongoid_outbox.rb
70
86
  - sig/outboxable.rbs
71
87
  homepage: https://github.com/broosk1993/outboxable
72
88
  licenses: