journaled 2.1.0 → 2.4.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
- SHA1:
3
- metadata.gz: fd948588d9c1d876db7b98ca2f23a0d5d6dce08e
4
- data.tar.gz: fc7edb7bef6fcb50e0c32081c86ab036fe3f6b25
2
+ SHA256:
3
+ metadata.gz: a57088ffa5913d3e80f1d6d978bfe3f0a4ff090bd78f20f3fcbed1c32b84bdbc
4
+ data.tar.gz: 75c470723ae03dd2695300c0a8a2aaf0d05202fac8fdb5157efd248214a7eb6d
5
5
  SHA512:
6
- metadata.gz: 0e16247d3f7e8c67a7c9ff79dc4205fcf4ca89c335108d646c3fcb8edd1ca1a666dac6ed170d17ab97fdf5c89b4895aef52ca8ada6e80002d8f739bc3a9e2ed8
7
- data.tar.gz: 6206fde79a179858d4c8e57f5396d23d29e9316bec634f339b6db5728ebb022884963ce5293bb8de3a89548f7be95bd8dc02cf1fc43a83c1b0ba03a1c21db12e
6
+ metadata.gz: ffcbd7201f572423fa304c440d18b2993e7a97050b5ac7b1be68143da64a8c7caaa430aa3ef64d8a99940380b67361e50ef55cb9ce01cecb9dd017f977e08934
7
+ data.tar.gz: a6c33d7c56b1fbd9558d219617a12dbfa0b704dac7b9ca3171cd2387477a3b00a6fe6dac592ed6a8cc4a4f6de2cbb806ff49d670134131a6e2eddfe5d64be0d7
data/README.md CHANGED
@@ -88,6 +88,29 @@ Journaling provides a number of different configuation options that can be set i
88
88
  This can be used to configure what `priority` the Delayed Jobs are enqueued with. This will be applied to all the Journaled::Devivery jobs that are created by this application.
89
89
  Ex: `Journaled.job_priority = 14`
90
90
 
91
+ #### `Journaled.http_idle_timeout` (default: 1 second)
92
+
93
+ The number of seconds a persistent connection is allowed to sit idle before it should no longer be used.
94
+
95
+ #### `Journaled.http_open_timeout` (default: 15 seconds)
96
+
97
+ The number of seconds before the :http_handler should timeout while trying to open a new HTTP session.
98
+
99
+ #### `Journaled.http_read_timeout` (default: 60 seconds)
100
+
101
+ The number of seconds before the :http_handler should timeout while waiting for a HTTP response.
102
+
103
+ #### DJ `enqueue` options
104
+
105
+ Both model-level directives accept additional options to be passed into DelayedJob's `enqueue` method:
106
+
107
+ ```ruby
108
+ # For change journaling:
109
+ journal_changes_to :email, as: :identity_change, enqueue_with: { priority: 10 }
110
+
111
+ # Or for custom journaling:
112
+ journal_attributes :email, enqueue_with: { priority: 20, queue: 'journaled' }
113
+ ```
91
114
 
92
115
  ### Change Journaling
93
116
 
@@ -12,6 +12,7 @@ module Journaled::Actor
12
12
  class_methods do
13
13
  def journaled_actor=(method_name)
14
14
  raise "Must provide a symbol method name" unless method_name.is_a?(Symbol)
15
+
15
16
  self._journaled_actor_method_name = method_name
16
17
  end
17
18
  end
@@ -2,10 +2,9 @@ module Journaled::Changes
2
2
  extend ActiveSupport::Concern
3
3
 
4
4
  included do
5
- cattr_accessor :_journaled_change_definitions
6
- cattr_accessor :journaled_attribute_names
7
- self._journaled_change_definitions = []
8
- self.journaled_attribute_names = []
5
+ cattr_accessor(:_journaled_change_definitions) { [] }
6
+ cattr_accessor(:journaled_attribute_names) { [] }
7
+ cattr_accessor(:journaled_enqueue_opts, instance_writer: false) { {} }
9
8
 
10
9
  after_create do
11
10
  self.class._journaled_change_definitions.each do |definition|
@@ -57,7 +56,7 @@ module Journaled::Changes
57
56
  end
58
57
 
59
58
  class_methods do
60
- def journal_changes_to(*attribute_names, as:) # rubocop:disable Naming/UncommunicativeMethodParamName
59
+ def journal_changes_to(*attribute_names, as:, enqueue_with: {}) # rubocop:disable Naming/UncommunicativeMethodParamName
61
60
  if attribute_names.empty? || attribute_names.any? { |n| !n.is_a?(Symbol) }
62
61
  raise "one or more symbol attribute_name arguments is required"
63
62
  end
@@ -66,6 +65,7 @@ module Journaled::Changes
66
65
 
67
66
  _journaled_change_definitions << Journaled::ChangeDefinition.new(attribute_names: attribute_names, logical_operation: as)
68
67
  journaled_attribute_names.concat(attribute_names)
68
+ journaled_enqueue_opts.merge!(enqueue_with)
69
69
  end
70
70
 
71
71
  if Rails::VERSION::MAJOR > 5 || (Rails::VERSION::MAJOR == 5 && Rails::VERSION::MINOR >= 2)
@@ -7,6 +7,7 @@ class Journaled::Change
7
7
  :logical_operation,
8
8
  :changes,
9
9
  :journaled_app_name,
10
+ :journaled_enqueue_opts,
10
11
  :actor
11
12
 
12
13
  journal_attributes :table_name,
@@ -16,12 +17,13 @@ class Journaled::Change
16
17
  :changes,
17
18
  :actor
18
19
 
19
- def initialize(table_name:, # rubocop:disable Metrics/ParameterLists
20
+ def initialize(table_name:,
20
21
  record_id:,
21
22
  database_operation:,
22
23
  logical_operation:,
23
24
  changes:,
24
25
  journaled_app_name:,
26
+ journaled_enqueue_opts:,
25
27
  actor:)
26
28
  @table_name = table_name
27
29
  @record_id = record_id
@@ -29,6 +31,7 @@ class Journaled::Change
29
31
  @logical_operation = logical_operation
30
32
  @changes = changes
31
33
  @journaled_app_name = journaled_app_name
34
+ @journaled_enqueue_opts = journaled_enqueue_opts
32
35
  @actor = actor
33
36
  end
34
37
  end
@@ -19,6 +19,7 @@ class Journaled::ChangeDefinition
19
19
 
20
20
  #{nonexistent_attribute_names.join(', ')}
21
21
  ERROR
22
+
22
23
  @validated = true
23
24
  end
24
25
  end
@@ -28,7 +28,8 @@ class Journaled::ChangeWriter
28
28
  logical_operation: logical_operation,
29
29
  changes: JSON.dump(changes),
30
30
  journaled_app_name: journaled_app_name,
31
- actor: actor_uri
31
+ journaled_enqueue_opts: model.journaled_enqueue_opts,
32
+ actor: actor_uri,
32
33
  )
33
34
  end
34
35
 
@@ -1,4 +1,4 @@
1
- class Journaled::Delivery
1
+ class Journaled::Delivery # rubocop:disable Betterment/ActiveJobPerformable
2
2
  DEFAULT_REGION = 'us-east-1'.freeze
3
3
 
4
4
  def initialize(serialized_event:, partition_key:, app_name:)
@@ -25,7 +25,10 @@ class Journaled::Delivery
25
25
  def kinesis_client_config
26
26
  {
27
27
  region: ENV.fetch('AWS_DEFAULT_REGION', DEFAULT_REGION),
28
- retry_limit: 0
28
+ retry_limit: 0,
29
+ http_idle_timeout: Journaled.http_idle_timeout,
30
+ http_open_timeout: Journaled.http_open_timeout,
31
+ http_read_timeout: Journaled.http_read_timeout,
29
32
  }.merge(credentials)
30
33
  end
31
34
 
@@ -37,7 +40,7 @@ class Journaled::Delivery
37
40
  {
38
41
  stream_name: stream_name,
39
42
  data: serialized_event,
40
- partition_key: partition_key
43
+ partition_key: partition_key,
41
44
  }
42
45
  end
43
46
 
@@ -48,7 +51,7 @@ class Journaled::Delivery
48
51
  def credentials
49
52
  if ENV.key?('JOURNALED_IAM_ROLE_ARN')
50
53
  {
51
- credentials: iam_assume_role_credentials
54
+ credentials: iam_assume_role_credentials,
52
55
  }
53
56
  else
54
57
  legacy_credentials_hash_if_present
@@ -59,7 +62,7 @@ class Journaled::Delivery
59
62
  if ENV.key?('RUBY_AWS_ACCESS_KEY_ID')
60
63
  {
61
64
  access_key_id: ENV.fetch('RUBY_AWS_ACCESS_KEY_ID'),
62
- secret_access_key: ENV.fetch('RUBY_AWS_SECRET_ACCESS_KEY')
65
+ secret_access_key: ENV.fetch('RUBY_AWS_SECRET_ACCESS_KEY'),
63
66
  }
64
67
  else
65
68
  {}
@@ -68,7 +71,7 @@ class Journaled::Delivery
68
71
 
69
72
  def sts_client
70
73
  Aws::STS::Client.new({
71
- region: ENV.fetch('AWS_DEFAULT_REGION', DEFAULT_REGION)
74
+ region: ENV.fetch('AWS_DEFAULT_REGION', DEFAULT_REGION),
72
75
  }.merge(legacy_credentials_hash_if_present))
73
76
  end
74
77
 
@@ -76,7 +79,7 @@ class Journaled::Delivery
76
79
  @iam_assume_role_credentials ||= Aws::AssumeRoleCredentials.new(
77
80
  client: sts_client,
78
81
  role_arn: ENV.fetch('JOURNALED_IAM_ROLE_ARN'),
79
- role_session_name: "JournaledAssumeRoleAccess"
82
+ role_session_name: "JournaledAssumeRoleAccess",
80
83
  )
81
84
  end
82
85
 
@@ -2,7 +2,7 @@ module Journaled::Event
2
2
  extend ActiveSupport::Concern
3
3
 
4
4
  def journal!
5
- Journaled::Writer.new(journaled_event: self, priority: Journaled.job_priority).journal!
5
+ Journaled::Writer.new(journaled_event: self).journal!
6
6
  end
7
7
 
8
8
  # Base attributes
@@ -42,8 +42,9 @@ module Journaled::Event
42
42
  private
43
43
 
44
44
  class_methods do
45
- def journal_attributes(*args)
45
+ def journal_attributes(*args, enqueue_with: {})
46
46
  journaled_attributes.concat(args)
47
+ journaled_enqueue_opts.merge!(enqueue_with)
47
48
  end
48
49
 
49
50
  def journaled_attributes
@@ -56,6 +57,8 @@ module Journaled::Event
56
57
  end
57
58
 
58
59
  included do
60
+ cattr_accessor(:journaled_enqueue_opts, instance_writer: false) { {} }
61
+
59
62
  journal_attributes :id, :event_type, :created_at
60
63
  end
61
64
  end
@@ -4,9 +4,10 @@ class Journaled::Writer
4
4
  journaled_partition_key
5
5
  journaled_attributes
6
6
  journaled_app_name
7
+ journaled_enqueue_opts
7
8
  ).freeze
8
9
 
9
- def initialize(journaled_event:, priority:)
10
+ def initialize(journaled_event:)
10
11
  raise "An enqueued event must respond to: #{EVENT_METHOD_NAMES.to_sentence}" unless respond_to_all?(journaled_event, EVENT_METHOD_NAMES)
11
12
 
12
13
  unless journaled_event.journaled_schema_name.present? &&
@@ -21,25 +22,24 @@ class Journaled::Writer
21
22
  end
22
23
 
23
24
  @journaled_event = journaled_event
24
- @priority = priority
25
25
  end
26
26
 
27
27
  def journal!
28
28
  base_event_json_schema_validator.validate! serialized_event
29
29
  json_schema_validator.validate! serialized_event
30
- Delayed::Job.enqueue journaled_delivery, priority: priority
30
+ Journaled.enqueue!(journaled_delivery, journaled_enqueue_opts)
31
31
  end
32
32
 
33
33
  private
34
34
 
35
- attr_reader :journaled_event, :priority
36
- delegate :journaled_schema_name, :journaled_attributes, :journaled_partition_key, :journaled_app_name, to: :journaled_event
35
+ attr_reader :journaled_event
36
+ delegate(*EVENT_METHOD_NAMES, to: :journaled_event)
37
37
 
38
38
  def journaled_delivery
39
39
  @journaled_delivery ||= Journaled::Delivery.new(
40
40
  serialized_event: serialized_event,
41
41
  partition_key: journaled_partition_key,
42
- app_name: journaled_app_name
42
+ app_name: journaled_app_name,
43
43
  )
44
44
  end
45
45
 
@@ -1,14 +1,17 @@
1
- require "aws-sdk-resources"
1
+ require "aws-sdk-kinesis"
2
2
  require "delayed_job"
3
3
  require "json-schema"
4
4
  require "request_store"
5
5
 
6
6
  require "journaled/engine"
7
- require "journaled/job_priority"
7
+ require 'journaled/enqueue'
8
8
 
9
9
  module Journaled
10
10
  mattr_accessor :default_app_name
11
- mattr_accessor(:job_priority) { Journaled::JobPriority::EVENTUAL }
11
+ mattr_accessor(:job_priority) { 20 }
12
+ mattr_accessor(:http_idle_timeout) { 5 }
13
+ mattr_accessor(:http_open_timeout) { 15 }
14
+ mattr_accessor(:http_read_timeout) { 60 }
12
15
 
13
16
  def development_or_test?
14
17
  %w(development test).include?(Rails.env)
@@ -0,0 +1,13 @@
1
+ module Journaled
2
+ class << self
3
+ def enqueue!(*args)
4
+ delayed_job_enqueue(*args)
5
+ end
6
+
7
+ private
8
+
9
+ def delayed_job_enqueue(*args, **opts)
10
+ Delayed::Job.enqueue(*args, **opts.reverse_merge(priority: Journaled.job_priority))
11
+ end
12
+ end
13
+ end
@@ -1,7 +1,15 @@
1
1
  module Journaled::RelationChangeProtection
2
- def update_all(updates, force: false)
2
+ def update_all(updates, force: false) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/PerceivedComplexity
3
3
  unless force || !@klass.respond_to?(:journaled_attribute_names) || @klass.journaled_attribute_names.empty?
4
- conflicting_journaled_attribute_names = @klass.journaled_attribute_names & updates.keys.map(&:to_sym)
4
+ conflicting_journaled_attribute_names = if updates.is_a?(Hash)
5
+ @klass.journaled_attribute_names & updates.keys.map(&:to_sym)
6
+ elsif updates.is_a?(String)
7
+ @klass.journaled_attribute_names.select do |a|
8
+ updates.match?(/\b(?<!')#{a}(?!')\b/)
9
+ end
10
+ else
11
+ raise "unsupported type '#{updates.class}' for 'updates'"
12
+ end
5
13
  raise(<<~ERROR) if conflicting_journaled_attribute_names.present?
6
14
  .update_all aborted by Journaled::Changes due to journaled attributes:
7
15
 
@@ -1,3 +1,3 @@
1
1
  module Journaled
2
- VERSION = "2.1.0".freeze
2
+ VERSION = "2.4.0".freeze
3
3
  end
@@ -3,49 +3,50 @@ require 'rails_helper'
3
3
  RSpec.describe Journaled do
4
4
  it "is enabled in production" do
5
5
  allow(Rails).to receive(:env).and_return("production")
6
- expect(Journaled).to be_enabled
6
+ expect(described_class).to be_enabled
7
7
  end
8
8
 
9
9
  it "is disabled in development" do
10
10
  allow(Rails).to receive(:env).and_return("development")
11
- expect(Journaled).not_to be_enabled
11
+ expect(described_class).not_to be_enabled
12
12
  end
13
13
 
14
14
  it "is disabled in test" do
15
15
  allow(Rails).to receive(:env).and_return("test")
16
- expect(Journaled).not_to be_enabled
16
+ expect(described_class).not_to be_enabled
17
17
  end
18
18
 
19
19
  it "is enabled in whatevs" do
20
20
  allow(Rails).to receive(:env).and_return("whatevs")
21
- expect(Journaled).to be_enabled
21
+ expect(described_class).to be_enabled
22
22
  end
23
23
 
24
24
  it "is enabled when explicitly enabled in development" do
25
25
  with_env(JOURNALED_ENABLED: true) do
26
26
  allow(Rails).to receive(:env).and_return("development")
27
- expect(Journaled).to be_enabled
27
+ expect(described_class).to be_enabled
28
28
  end
29
29
  end
30
30
 
31
31
  it "is disabled when explicitly disabled in production" do
32
32
  with_env(JOURNALED_ENABLED: false) do
33
33
  allow(Rails).to receive(:env).and_return("production")
34
- expect(Journaled).not_to be_enabled
34
+ expect(described_class).not_to be_enabled
35
35
  end
36
36
  end
37
37
 
38
38
  it "is disabled when explicitly disabled with empty string" do
39
39
  with_env(JOURNALED_ENABLED: '') do
40
40
  allow(Rails).to receive(:env).and_return("production")
41
- expect(Journaled).not_to be_enabled
41
+ expect(described_class).not_to be_enabled
42
42
  end
43
43
  end
44
44
 
45
45
  describe "#actor_uri" do
46
46
  it "delegates to ActorUriProvider" do
47
- allow(Journaled::ActorUriProvider).to receive(:instance).and_return(double(actor_uri: "my actor uri"))
48
- expect(Journaled.actor_uri).to eq "my actor uri"
47
+ allow(Journaled::ActorUriProvider).to receive(:instance)
48
+ .and_return(instance_double(Journaled::ActorUriProvider, actor_uri: "my actor uri"))
49
+ expect(described_class.actor_uri).to eq "my actor uri"
49
50
  end
50
51
  end
51
52
  end
@@ -17,6 +17,7 @@ RSpec.describe Journaled::Changes do
17
17
  def self.after_save(opts, &hook)
18
18
  # This is a back-door assertion to prevent regressions in the module's hook definition behavior
19
19
  raise "expected `unless: :saved_change_to_id?`" unless opts[:unless] == :saved_change_to_id?
20
+
20
21
  after_save_hooks << hook
21
22
  end
22
23
 
@@ -91,4 +92,15 @@ RSpec.describe Journaled::Changes do
91
92
  expect(change_writer).to have_received(:delete)
92
93
  expect(Journaled::ChangeWriter).to have_received(:new)
93
94
  end
95
+
96
+ context 'when DJ opts are provided' do
97
+ before do
98
+ klass.journal_changes_to :thing, as: :other_thing, enqueue_with: { asdf: 1, foo: 'bar' }
99
+ end
100
+
101
+ it 'sets them on the model' do
102
+ expect(klass.journaled_enqueue_opts).to eq(asdf: 1, foo: 'bar')
103
+ expect(klass.new.journaled_enqueue_opts).to eq(asdf: 1, foo: 'bar')
104
+ end
105
+ end
94
106
  end
@@ -19,10 +19,17 @@ if Rails::VERSION::MAJOR > 5 || (Rails::VERSION::MAJOR == 5 && Rails::VERSION::M
19
19
 
20
20
  describe "the relation" do
21
21
  describe "#update_all" do
22
- it "refuses on journaled columns" do
22
+ it "refuses on journaled columns passed as hash" do
23
23
  expect { journaled_class.update_all(locked_at: nil) }.to raise_error(/aborted by Journaled/)
24
24
  end
25
25
 
26
+ it "refuses on journaled columns passed as string" do
27
+ expect { journaled_class.update_all("\"locked_at\" = NULL") }.to raise_error(/aborted by Journaled/)
28
+ expect { journaled_class.update_all("locked_at = null") }.to raise_error(/aborted by Journaled/)
29
+ expect { journaled_class.update_all("delayed_jobs.locked_at = null") }.to raise_error(/aborted by Journaled/)
30
+ expect { journaled_class.update_all("last_error = 'locked_at'") }.not_to raise_error
31
+ end
32
+
26
33
  it "succeeds on unjournaled columns" do
27
34
  expect { journaled_class.update_all(handler: "") }.not_to raise_error
28
35
  end
@@ -11,12 +11,13 @@ RSpec.describe Journaled::ChangeWriter do
11
11
  "name" => "bob",
12
12
  "rank" => "first lieutenant",
13
13
  "serial_number" => "foobar",
14
- "last_sign_in_at" => now
14
+ "last_sign_in_at" => now,
15
15
  },
16
16
  saved_changes: {
17
17
  "name" => %w(bill bob),
18
- "last_sign_in_at" => now
19
- }
18
+ "last_sign_in_at" => now,
19
+ },
20
+ journaled_enqueue_opts: {},
20
21
  )
21
22
  end
22
23
 
@@ -24,21 +25,21 @@ RSpec.describe Journaled::ChangeWriter do
24
25
  double(
25
26
  "SoldierClass",
26
27
  table_name: "soldiers",
27
- attribute_names: %w(id name rank serial_number last_sign_in_at)
28
+ attribute_names: %w(id name rank serial_number last_sign_in_at),
28
29
  )
29
30
  end
30
31
 
31
32
  let(:change_definition) do
32
33
  Journaled::ChangeDefinition.new(
33
34
  attribute_names: %i(name rank serial_number),
34
- logical_operation: "identity_change"
35
+ logical_operation: "identity_change",
35
36
  )
36
37
  end
37
38
 
38
39
  let(:faulty_change_definition) do
39
40
  Journaled::ChangeDefinition.new(
40
41
  attribute_names: %i(name rank serial_number nonexistent_thingie),
41
- logical_operation: "identity_change"
42
+ logical_operation: "identity_change",
42
43
  )
43
44
  end
44
45
 
@@ -58,9 +59,10 @@ RSpec.describe Journaled::ChangeWriter do
58
59
  "name" => "bill",
59
60
  "rank" => "first lieutenant",
60
61
  "serial_number" => "foobar",
61
- "last_sign_in_at" => Time.zone.now
62
+ "last_sign_in_at" => Time.zone.now,
62
63
  },
63
- saved_changes: {}
64
+ saved_changes: {},
65
+ journaled_enqueue_opts: {},
64
66
  )
65
67
  end
66
68
 
@@ -68,7 +70,7 @@ RSpec.describe Journaled::ChangeWriter do
68
70
  expect(subject.relevant_attributes).to eq(
69
71
  "name" => "bill",
70
72
  "rank" => "first lieutenant",
71
- "serial_number" => "foobar"
73
+ "serial_number" => "foobar",
72
74
  )
73
75
  end
74
76
  end
@@ -83,11 +85,12 @@ RSpec.describe Journaled::ChangeWriter do
83
85
  "name" => "bill",
84
86
  "rank" => "first lieutenant",
85
87
  "serial_number" => "foobar",
86
- "last_sign_in_at" => Time.zone.now
88
+ "last_sign_in_at" => Time.zone.now,
87
89
  },
88
90
  changes: {
89
- "name" => %w(bob bill)
90
- }
91
+ "name" => %w(bob bill),
92
+ },
93
+ journaled_enqueue_opts: {},
91
94
  )
92
95
  end
93
96
 
@@ -95,7 +98,7 @@ RSpec.describe Journaled::ChangeWriter do
95
98
  expect(subject.relevant_unperturbed_attributes).to eq(
96
99
  "name" => "bob",
97
100
  "rank" => "first lieutenant",
98
- "serial_number" => "foobar"
101
+ "serial_number" => "foobar",
99
102
  )
100
103
  end
101
104
  end
@@ -180,9 +183,10 @@ RSpec.describe Journaled::ChangeWriter do
180
183
  "name" => "bill",
181
184
  "rank" => "first lieutenant",
182
185
  "serial_number" => "foobar",
183
- "last_sign_in_at" => Time.zone.now
186
+ "last_sign_in_at" => Time.zone.now,
184
187
  },
185
- saved_changes: {}
188
+ saved_changes: {},
189
+ journaled_enqueue_opts: {},
186
190
  )
187
191
  end
188
192
 
@@ -222,9 +226,9 @@ RSpec.describe Journaled::ChangeWriter do
222
226
  "name" => "bill",
223
227
  "rank" => "first lieutenant",
224
228
  "serial_number" => "foobar",
225
- "last_sign_in_at" => Time.zone.now
229
+ "last_sign_in_at" => Time.zone.now,
226
230
  },
227
- saved_changes: {}
231
+ saved_changes: {},
228
232
  )
229
233
  end
230
234
 
@@ -248,11 +252,12 @@ RSpec.describe Journaled::ChangeWriter do
248
252
  "name" => "bob",
249
253
  "rank" => "first lieutenant",
250
254
  "serial_number" => "foobar",
251
- "last_sign_in_at" => now
255
+ "last_sign_in_at" => now,
252
256
  },
253
257
  changes: {
254
- "name" => %w(bill bob)
255
- }
258
+ "name" => %w(bill bob),
259
+ },
260
+ journaled_enqueue_opts: {},
256
261
  )
257
262
  end
258
263
 
@@ -261,7 +266,7 @@ RSpec.describe Journaled::ChangeWriter do
261
266
  expect(JSON.parse(opts[:changes])).to eq(
262
267
  "name" => "bill",
263
268
  "rank" => "first lieutenant",
264
- "serial_number" => "foobar"
269
+ "serial_number" => "foobar",
265
270
  )
266
271
  journaled_change
267
272
  end