journaled 2.5.0 → 3.0.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: 895598e96b01aad6c51bd55355c5d7d0fab963b97326c2943bcb76450dd7cdb7
4
- data.tar.gz: 61073882361fbb34ca243d8cc4dbedb494f798bcaaf2bde124f820eb8e175439
3
+ metadata.gz: 358c3ced2b976724c62e951ca88b635709d1fb7da0276ed4538bdc44bc02f468
4
+ data.tar.gz: ca65a5b0531ba4540de1b79fd36d247c7c164f3aef8b397254ed7b34503ebf0f
5
5
  SHA512:
6
- metadata.gz: 4564bc7e637fc2d032ee00b1f2b9e21282d65a531ae758ac374f863b1964100c3ea755db1e558c43d3503a74b995ffc310bb6343f255591357bf4d7ffe556e54
7
- data.tar.gz: b456385727f88392465553ff9c63f313902536a9a13cae00fae011e40c7afb2490f3f5ff5fb1012346c18cedfb5cfabcbd20ed2dcaf1cd039dc27551d756647c
6
+ metadata.gz: 236c6169ef41b1af9043f2549248ae43fad665a91d43cdd2f579e891685788aa5a008cf4f1dc8aba13abcce5dccfa6513c82232fdaaf3ab4f42f8a7b1b222bf7
7
+ data.tar.gz: 9e325f6c1e41eb577f5e0d7320517f5435b9570d7b0274c5b6ad9c593abc2a4a66dc6b6eb10d668617e645e5731804ecd65d4b6403fda63005de129443ed9332
data/README.md CHANGED
@@ -1,16 +1,16 @@
1
1
  # Journaled
2
2
 
3
- A Rails engine to durably deliver schematized events to Amazon Kinesis via DelayedJob.
3
+ A Rails engine to durably deliver schematized events to Amazon Kinesis via ActiveJob.
4
4
 
5
5
  More specifically, `journaled` is composed of three opinionated pieces:
6
6
  schema definition/validation via JSON Schema, transactional enqueueing
7
- via Delayed::Job (specifically `delayed_job_active_record`), and event
7
+ via ActiveJob (specifically, via a DB-backed queue adapter), and event
8
8
  transmission via Amazon Kinesis. Our current use-cases include
9
9
  transmitting audit events for durable storage in S3 and/or analytical
10
10
  querying in Amazon Redshift.
11
11
 
12
12
  Journaled provides an at-least-once event delivery guarantee assuming
13
- Delayed::Job is configured not to delete jobs on failure.
13
+ ActiveJob's queue adapter is not configured to delete jobs on failure.
14
14
 
15
15
  Note: Do not use the journaled gem to build an event sourcing solution
16
16
  as it does not guarantee total ordering of events. It's possible we'll
@@ -20,9 +20,20 @@ durable, eventually consistent record that discrete events happened.
20
20
 
21
21
  ## Installation
22
22
 
23
- 1. [Install `delayed_job_active_record`](https://github.com/collectiveidea/delayed_job_active_record#installation)
24
- if you haven't already.
23
+ 1. If you haven't already,
24
+ [configure ActiveJob](https://guides.rubyonrails.org/active_job_basics.html)
25
+ to use one of the following queue adapters:
25
26
 
27
+ - `:delayed_job` (via `delayed_job_active_record`)
28
+ - `:que`
29
+ - `:good_job`
30
+ - `:delayed`
31
+
32
+ Ensure that your queue adapter is not configured to delete jobs on failure.
33
+
34
+ **If you launch your application in production mode and the gem detects that
35
+ `ActiveJob::Base.queue_adapter` is not in the above list, it will raise an exception
36
+ and prevent your application from performing unsafe journaling.**
26
37
 
27
38
  2. To integrate Journaled into your application, simply include the gem in your
28
39
  app's Gemfile.
@@ -85,9 +96,11 @@ Journaling provides a number of different configuation options that can be set i
85
96
 
86
97
  #### `Journaled.job_priority` (default: 20)
87
98
 
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.
99
+ This can be used to configure what `priority` the ActiveJobs are enqueued with. This will be applied to all the `Journaled::DeliveryJob`s that are created by this application.
89
100
  Ex: `Journaled.job_priority = 14`
90
101
 
102
+ _Note that job priority is only supported on Rails 6.0+. Prior Rails versions will ignore this parameter and enqueue jobs with the underlying ActiveJob adapter's default priority._
103
+
91
104
  #### `Journaled.http_idle_timeout` (default: 1 second)
92
105
 
93
106
  The number of seconds a persistent connection is allowed to sit idle before it should no longer be used.
@@ -100,9 +113,9 @@ Journaling provides a number of different configuation options that can be set i
100
113
 
101
114
  The number of seconds before the :http_handler should timeout while waiting for a HTTP response.
102
115
 
103
- #### DJ `enqueue` options
116
+ #### ActiveJob `set` options
104
117
 
105
- Both model-level directives accept additional options to be passed into DelayedJob's `enqueue` method:
118
+ Both model-level directives accept additional options to be passed into ActiveJob's `set` method:
106
119
 
107
120
  ```ruby
108
121
  # For change journaling:
data/Rakefile CHANGED
@@ -28,7 +28,13 @@ if %w(development test).include? Rails.env
28
28
  RuboCop::RakeTask.new
29
29
 
30
30
  task(:default).clear
31
- task default: %i(rubocop spec)
31
+ if ENV['APPRAISAL_INITIALIZED'] || ENV['CI']
32
+ task default: %i(rubocop spec)
33
+ else
34
+ require 'appraisal'
35
+ Appraisal::Task.new
36
+ task default: :appraisal
37
+ end
32
38
 
33
39
  task 'db:test:prepare' => 'db:setup'
34
40
  end
@@ -0,0 +1,4 @@
1
+ module Journaled
2
+ class ApplicationJob < Journaled.job_base_class_name.constantize
3
+ end
4
+ end
@@ -0,0 +1,96 @@
1
+ module Journaled
2
+ class DeliveryJob < ApplicationJob
3
+ DEFAULT_REGION = 'us-east-1'.freeze
4
+
5
+ rescue_from(Aws::Kinesis::Errors::InternalFailure, Aws::Kinesis::Errors::ServiceUnavailable, Aws::Kinesis::Errors::Http503Error) do |e|
6
+ Rails.logger.error "Kinesis Error - Server Error occurred - #{e.class}"
7
+ raise KinesisTemporaryFailure
8
+ end
9
+
10
+ rescue_from(Seahorse::Client::NetworkingError) do |e|
11
+ Rails.logger.error "Kinesis Error - Networking Error occurred - #{e.class}"
12
+ raise KinesisTemporaryFailure
13
+ end
14
+
15
+ def perform(serialized_event:, partition_key:, app_name:)
16
+ @serialized_event = serialized_event
17
+ @partition_key = partition_key
18
+ @app_name = app_name
19
+
20
+ journal!
21
+ end
22
+
23
+ def self.stream_name(app_name:)
24
+ env_var_name = [app_name&.upcase, 'JOURNALED_STREAM_NAME'].compact.join('_')
25
+ ENV.fetch(env_var_name)
26
+ end
27
+
28
+ def kinesis_client_config
29
+ {
30
+ region: ENV.fetch('AWS_DEFAULT_REGION', DEFAULT_REGION),
31
+ retry_limit: 0,
32
+ http_idle_timeout: Journaled.http_idle_timeout,
33
+ http_open_timeout: Journaled.http_open_timeout,
34
+ http_read_timeout: Journaled.http_read_timeout,
35
+ }.merge(credentials)
36
+ end
37
+
38
+ private
39
+
40
+ attr_reader :serialized_event, :partition_key, :app_name
41
+
42
+ def journal!
43
+ kinesis_client.put_record record if Journaled.enabled?
44
+ end
45
+
46
+ def record
47
+ {
48
+ stream_name: self.class.stream_name(app_name: app_name),
49
+ data: serialized_event,
50
+ partition_key: partition_key,
51
+ }
52
+ end
53
+
54
+ def kinesis_client
55
+ Aws::Kinesis::Client.new(kinesis_client_config)
56
+ end
57
+
58
+ def credentials
59
+ if ENV.key?('JOURNALED_IAM_ROLE_ARN')
60
+ {
61
+ credentials: iam_assume_role_credentials,
62
+ }
63
+ else
64
+ legacy_credentials_hash_if_present
65
+ end
66
+ end
67
+
68
+ def legacy_credentials_hash_if_present
69
+ if ENV.key?('RUBY_AWS_ACCESS_KEY_ID')
70
+ {
71
+ access_key_id: ENV.fetch('RUBY_AWS_ACCESS_KEY_ID'),
72
+ secret_access_key: ENV.fetch('RUBY_AWS_SECRET_ACCESS_KEY'),
73
+ }
74
+ else
75
+ {}
76
+ end
77
+ end
78
+
79
+ def sts_client
80
+ Aws::STS::Client.new({
81
+ region: ENV.fetch('AWS_DEFAULT_REGION', DEFAULT_REGION),
82
+ }.merge(legacy_credentials_hash_if_present))
83
+ end
84
+
85
+ def iam_assume_role_credentials
86
+ @iam_assume_role_credentials ||= Aws::AssumeRoleCredentials.new(
87
+ client: sts_client,
88
+ role_arn: ENV.fetch('JOURNALED_IAM_ROLE_ARN'),
89
+ role_session_name: "JournaledAssumeRoleAccess",
90
+ )
91
+ end
92
+
93
+ class KinesisTemporaryFailure < NotTrulyExceptionalError
94
+ end
95
+ end
96
+ end
@@ -83,6 +83,6 @@ class Journaled::Delivery # rubocop:disable Betterment/ActiveJobPerformable
83
83
  )
84
84
  end
85
85
 
86
- class KinesisTemporaryFailure < NotTrulyExceptionalError
86
+ class KinesisTemporaryFailure < ::Journaled::NotTrulyExceptionalError
87
87
  end
88
88
  end
@@ -27,7 +27,9 @@ class Journaled::Writer
27
27
  def journal!
28
28
  base_event_json_schema_validator.validate! serialized_event
29
29
  json_schema_validator.validate! serialized_event
30
- Journaled.enqueue!(journaled_delivery, journaled_enqueue_opts)
30
+ Journaled::DeliveryJob
31
+ .set(journaled_enqueue_opts.reverse_merge(priority: Journaled.job_priority))
32
+ .perform_later(delivery_perform_args)
31
33
  end
32
34
 
33
35
  private
@@ -35,12 +37,12 @@ class Journaled::Writer
35
37
  attr_reader :journaled_event
36
38
  delegate(*EVENT_METHOD_NAMES, to: :journaled_event)
37
39
 
38
- def journaled_delivery
39
- @journaled_delivery ||= Journaled::Delivery.new(
40
+ def delivery_perform_args
41
+ {
40
42
  serialized_event: serialized_event,
41
43
  partition_key: journaled_partition_key,
42
44
  app_name: journaled_app_name,
43
- )
45
+ }
44
46
  end
45
47
 
46
48
  def serialized_event
data/lib/journaled.rb CHANGED
@@ -1,17 +1,19 @@
1
1
  require "aws-sdk-kinesis"
2
- require "delayed_job"
2
+ require "active_job"
3
3
  require "json-schema"
4
4
  require "request_store"
5
5
 
6
6
  require "journaled/engine"
7
- require 'journaled/enqueue'
8
7
 
9
8
  module Journaled
9
+ SUPPORTED_QUEUE_ADAPTERS = %w(delayed delayed_job good_job que).freeze
10
+
10
11
  mattr_accessor :default_app_name
11
12
  mattr_accessor(:job_priority) { 20 }
12
13
  mattr_accessor(:http_idle_timeout) { 5 }
13
14
  mattr_accessor(:http_open_timeout) { 2 }
14
15
  mattr_accessor(:http_read_timeout) { 60 }
16
+ mattr_accessor(:job_base_class_name) { 'ActiveJob::Base' }
15
17
 
16
18
  def development_or_test?
17
19
  %w(development test).include?(Rails.env)
@@ -33,5 +35,21 @@ module Journaled
33
35
  Journaled::ActorUriProvider.instance.actor_uri
34
36
  end
35
37
 
36
- module_function :development_or_test?, :enabled?, :schema_providers, :commit_hash, :actor_uri
38
+ def detect_queue_adapter!
39
+ adapter = job_base_class_name.constantize.queue_adapter.class.name.split('::').last.underscore.gsub("_adapter", "")
40
+ unless SUPPORTED_QUEUE_ADAPTERS.include?(adapter)
41
+ raise <<~MSG
42
+ Journaled has detected an unsupported ActiveJob queue adapter: `:#{adapter}`
43
+
44
+ Journaled jobs must be enqueued transactionally to your primary database.
45
+
46
+ Please install the appropriate gems and set `queue_adapter` to one of the following:
47
+ #{SUPPORTED_QUEUE_ADAPTERS.map { |a| "- `:#{a}`" }.join("\n")}
48
+
49
+ Read more at https://github.com/Betterment/journaled
50
+ MSG
51
+ end
52
+ end
53
+
54
+ module_function :development_or_test?, :enabled?, :schema_providers, :commit_hash, :actor_uri, :detect_queue_adapter!
37
55
  end
@@ -1,4 +1,9 @@
1
1
  module Journaled
2
2
  class Engine < ::Rails::Engine
3
+ config.after_initialize do
4
+ ActiveSupport.on_load(:active_job) do
5
+ Journaled.detect_queue_adapter! unless Journaled.development_or_test?
6
+ end
7
+ end
3
8
  end
4
9
  end
@@ -1,3 +1,3 @@
1
1
  module Journaled
2
- VERSION = "2.5.0".freeze
2
+ VERSION = "3.0.0".freeze
3
3
  end
@@ -1,10 +1,9 @@
1
1
  require File.expand_path('boot', __dir__)
2
2
 
3
3
  require "active_record/railtie"
4
+ require "active_job/railtie"
4
5
  require "active_model/railtie"
5
6
  require "action_controller/railtie"
6
- require "action_mailer/railtie"
7
- require "sprockets/railtie"
8
7
 
9
8
  Bundler.require(*Rails.groups)
10
9
  require "journaled"
@@ -1,21 +1,6 @@
1
- default: &default
2
- pool: 5
3
- encoding: unicode
4
-
5
- postgresql:
6
- default: &postgres_default
7
- adapter: postgresql
8
- url: <%= ENV['DATABASE_URL'] %>
9
- test: &postgres_test
10
- <<: *postgres_default
11
- url: <%= ENV['DATABASE_URL'] || "postgresql://localhost:#{ENV.fetch('PGPORT', 5432)}/journaled_test" %>
12
- database: journaled_test
13
- development: &postgres_development
14
- <<: *postgres_default
15
- url: <%= ENV['DATABASE_URL'] || "postgresql://localhost:#{ENV.fetch('PGPORT', 5432)}/journaled_development" %>
16
- database: journaled_development
17
-
18
1
  development:
19
- <<: *postgres_development
2
+ adapter: sqlite3
3
+ database: ":memory:"
20
4
  test:
21
- <<: *postgres_test
5
+ adapter: sqlite3
6
+ database: ":memory:"
@@ -13,25 +13,12 @@ Rails.application.configure do
13
13
  config.consider_all_requests_local = true
14
14
  config.action_controller.perform_caching = false
15
15
 
16
- # Don't care if the mailer can't send.
17
- config.action_mailer.raise_delivery_errors = false
18
-
19
16
  # Print deprecation notices to the Rails logger.
20
17
  config.active_support.deprecation = :log
21
18
 
22
19
  # Raise an error on page load if there are pending migrations.
23
20
  config.active_record.migration_error = :page_load
24
21
 
25
- # Debug mode disables concatenation and preprocessing of assets.
26
- # This option may cause significant delays in view rendering with a large
27
- # number of complex assets.
28
- config.assets.debug = true
29
-
30
- # Adds additional error checking when serving assets at runtime.
31
- # Checks for improperly declared sprockets dependencies.
32
- # Raises helpful error messages.
33
- config.assets.raise_runtime_errors = true
34
-
35
22
  # Raises error for missing translations
36
23
  # config.action_view.raise_on_missing_translations = true
37
24
  end
@@ -26,14 +26,12 @@ Rails.application.configure do
26
26
  # Disable request forgery protection in test environment.
27
27
  config.action_controller.allow_forgery_protection = false
28
28
 
29
- # Tell Action Mailer not to deliver emails to the real world.
30
- # The :test delivery method accumulates sent emails in the
31
- # ActionMailer::Base.deliveries array.
32
- config.action_mailer.delivery_method = :test
33
-
34
29
  # Print deprecation notices to the stderr.
35
30
  config.active_support.deprecation = :stderr
36
31
 
37
32
  # Raises error for missing translations
38
33
  # config.action_view.raise_on_missing_translations = true
34
+
35
+ # Use ActiveJob test adapter
36
+ config.active_job.queue_adapter = :test
39
37
  end
@@ -11,21 +11,8 @@
11
11
  # It's strongly recommended that you check this file into your version control system.
12
12
 
13
13
  ActiveRecord::Schema.define(version: 20180606205114) do
14
- # These are extensions that must be enabled in order to support this database
15
- enable_extension "plpgsql"
16
-
17
- create_table "delayed_jobs", force: :cascade do |t|
18
- t.integer "priority", default: 0, null: false
19
- t.integer "attempts", default: 0, null: false
20
- t.text "handler", null: false
21
- t.text "last_error"
22
- t.datetime "run_at"
23
- t.datetime "locked_at"
24
- t.datetime "failed_at"
25
- t.string "locked_by"
26
- t.string "queue"
27
- t.datetime "created_at"
28
- t.datetime "updated_at"
29
- t.index ["priority", "run_at"], name: "delayed_jobs_priority"
14
+ create_table "widgets", force: :cascade do |t|
15
+ t.string "name"
16
+ t.string "other_column"
30
17
  end
31
18
  end
@@ -0,0 +1,221 @@
1
+ require 'rails_helper'
2
+
3
+ RSpec.describe Journaled::DeliveryJob do
4
+ let(:stream_name) { 'test_events' }
5
+ let(:partition_key) { 'fake_partition_key' }
6
+ let(:serialized_event) { '{"foo":"bar"}' }
7
+ let(:kinesis_client) { Aws::Kinesis::Client.new(stub_responses: true) }
8
+ let(:args) { { serialized_event: serialized_event, partition_key: partition_key, app_name: nil } }
9
+
10
+ around do |example|
11
+ with_env(JOURNALED_STREAM_NAME: stream_name) { example.run }
12
+ end
13
+
14
+ describe '#perform' do
15
+ let(:return_status_body) { { shard_id: '101', sequence_number: '101123' } }
16
+ let(:return_object) { instance_double Aws::Kinesis::Types::PutRecordOutput, return_status_body }
17
+
18
+ before do
19
+ allow(Aws::AssumeRoleCredentials).to receive(:new).and_call_original
20
+ allow(Aws::Kinesis::Client).to receive(:new).and_return kinesis_client
21
+ kinesis_client.stub_responses(:put_record, return_status_body)
22
+
23
+ allow(Journaled).to receive(:enabled?).and_return(true)
24
+ end
25
+
26
+ it 'makes requests to AWS to put the event on the Kinesis with the correct body' do
27
+ event = described_class.perform_now(args)
28
+
29
+ expect(event.shard_id).to eq '101'
30
+ expect(event.sequence_number).to eq '101123'
31
+ end
32
+
33
+ context 'when JOURNALED_IAM_ROLE_ARN is defined' do
34
+ let(:aws_sts_client) { Aws::STS::Client.new(stub_responses: true) }
35
+
36
+ around do |example|
37
+ with_env(JOURNALED_IAM_ROLE_ARN: 'iam-role-arn-for-assuming-kinesis-access') { example.run }
38
+ end
39
+
40
+ before do
41
+ allow(Aws::STS::Client).to receive(:new).and_return aws_sts_client
42
+ aws_sts_client.stub_responses(:assume_role, assume_role_response)
43
+ end
44
+
45
+ let(:assume_role_response) do
46
+ {
47
+ assumed_role_user: {
48
+ arn: 'iam-role-arn-for-assuming-kinesis-access',
49
+ assumed_role_id: "ARO123EXAMPLE123:Bob",
50
+ },
51
+ credentials: {
52
+ access_key_id: "AKIAIOSFODNN7EXAMPLE",
53
+ secret_access_key: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYzEXAMPLEKEY",
54
+ session_token: "EXAMPLEtc764bNrC9SAPBSM22wDOk4x4HIZ8j4FZTwdQWLWsKWHGBuFqwAeMicRXmxfpSPfIeoIYRqTflfKD8YUuwthAx7mSEI",
55
+ expiration: Time.zone.parse("2011-07-15T23:28:33.359Z"),
56
+ },
57
+ }
58
+ end
59
+
60
+ it 'initializes a Kinesis client with assume role credentials' do
61
+ described_class.perform_now(args)
62
+
63
+ expect(Aws::AssumeRoleCredentials).to have_received(:new).with(
64
+ client: aws_sts_client,
65
+ role_arn: "iam-role-arn-for-assuming-kinesis-access",
66
+ role_session_name: "JournaledAssumeRoleAccess",
67
+ )
68
+ end
69
+ end
70
+
71
+ context 'when the stream name env var is NOT set' do
72
+ let(:stream_name) { nil }
73
+
74
+ it 'raises an KeyError error' do
75
+ expect { described_class.perform_now(args) }.to raise_error KeyError
76
+ end
77
+ end
78
+
79
+ context 'when Amazon responds with an InternalFailure' do
80
+ before do
81
+ kinesis_client.stub_responses(:put_record, 'InternalFailure')
82
+ end
83
+
84
+ it 'catches the error and re-raises a subclass of NotTrulyExceptionalError and logs about the failure' do
85
+ allow(Rails.logger).to receive(:error)
86
+ expect { described_class.perform_now(args) }.to raise_error described_class::KinesisTemporaryFailure
87
+ expect(Rails.logger).to have_received(:error).with(
88
+ "Kinesis Error - Server Error occurred - Aws::Kinesis::Errors::InternalFailure",
89
+ ).once
90
+ end
91
+ end
92
+
93
+ context 'when Amazon responds with a ServiceUnavailable' do
94
+ before do
95
+ kinesis_client.stub_responses(:put_record, 'ServiceUnavailable')
96
+ end
97
+
98
+ it 'catches the error and re-raises a subclass of NotTrulyExceptionalError and logs about the failure' do
99
+ allow(Rails.logger).to receive(:error)
100
+ expect { described_class.perform_now(args) }.to raise_error described_class::KinesisTemporaryFailure
101
+ expect(Rails.logger).to have_received(:error).with(/\AKinesis Error/).once
102
+ end
103
+ end
104
+
105
+ context 'when we receive a 504 Gateway timeout' do
106
+ before do
107
+ kinesis_client.stub_responses(:put_record, 'Aws::Kinesis::Errors::ServiceError')
108
+ end
109
+
110
+ it 'raises an error that subclasses Aws::Kinesis::Errors::ServiceError' do
111
+ expect { described_class.perform_now(args) }.to raise_error Aws::Kinesis::Errors::ServiceError
112
+ end
113
+ end
114
+
115
+ context 'when the IAM user does not have permission to put_record to the specified stream' do
116
+ before do
117
+ kinesis_client.stub_responses(:put_record, 'AccessDeniedException')
118
+ end
119
+
120
+ it 'raises an AccessDeniedException error' do
121
+ expect { described_class.perform_now(args) }.to raise_error Aws::Kinesis::Errors::AccessDeniedException
122
+ end
123
+ end
124
+
125
+ context 'when the request timesout' do
126
+ before do
127
+ kinesis_client.stub_responses(:put_record, Seahorse::Client::NetworkingError.new(Timeout::Error.new))
128
+ end
129
+
130
+ it 'catches the error and re-raises a subclass of NotTrulyExceptionalError and logs about the failure' do
131
+ allow(Rails.logger).to receive(:error)
132
+ expect { described_class.perform_now(args) }.to raise_error described_class::KinesisTemporaryFailure
133
+ expect(Rails.logger).to have_received(:error).with(
134
+ "Kinesis Error - Networking Error occurred - Seahorse::Client::NetworkingError",
135
+ ).once
136
+ end
137
+ end
138
+ end
139
+
140
+ describe ".stream_name" do
141
+ context "when app_name is unspecified" do
142
+ it "is fetched from a prefixed ENV var if specified" do
143
+ allow(ENV).to receive(:fetch).and_return("expected_stream_name")
144
+ expect(described_class.stream_name(app_name: nil)).to eq("expected_stream_name")
145
+ expect(ENV).to have_received(:fetch).with("JOURNALED_STREAM_NAME")
146
+ end
147
+ end
148
+
149
+ context "when app_name is specified" do
150
+ it "is fetched from a prefixed ENV var if specified" do
151
+ allow(ENV).to receive(:fetch).and_return("expected_stream_name")
152
+ expect(described_class.stream_name(app_name: "my_funky_app_name")).to eq("expected_stream_name")
153
+ expect(ENV).to have_received(:fetch).with("MY_FUNKY_APP_NAME_JOURNALED_STREAM_NAME")
154
+ end
155
+ end
156
+ end
157
+
158
+ describe "#kinesis_client_config" do
159
+ it "is in us-east-1 by default" do
160
+ with_env(AWS_DEFAULT_REGION: nil) do
161
+ expect(subject.kinesis_client_config).to include(region: 'us-east-1')
162
+ end
163
+ end
164
+
165
+ it "respects AWS_DEFAULT_REGION env var" do
166
+ with_env(AWS_DEFAULT_REGION: 'us-west-2') do
167
+ expect(subject.kinesis_client_config).to include(region: 'us-west-2')
168
+ end
169
+ end
170
+
171
+ it "doesn't limit retry" do
172
+ expect(subject.kinesis_client_config).to include(retry_limit: 0)
173
+ end
174
+
175
+ it "provides no AWS credentials by default" do
176
+ with_env(RUBY_AWS_ACCESS_KEY_ID: nil, RUBY_AWS_SECRET_ACCESS_KEY: nil) do
177
+ expect(subject.kinesis_client_config).not_to have_key(:access_key_id)
178
+ expect(subject.kinesis_client_config).not_to have_key(:secret_access_key)
179
+ end
180
+ end
181
+
182
+ it "will use legacy credentials if specified" do
183
+ with_env(RUBY_AWS_ACCESS_KEY_ID: 'key_id', RUBY_AWS_SECRET_ACCESS_KEY: 'secret') do
184
+ expect(subject.kinesis_client_config).to include(access_key_id: 'key_id', secret_access_key: 'secret')
185
+ end
186
+ end
187
+
188
+ it "will set http_idle_timeout by default" do
189
+ expect(subject.kinesis_client_config).to include(http_idle_timeout: 5)
190
+ end
191
+
192
+ it "will set http_open_timeout by default" do
193
+ expect(subject.kinesis_client_config).to include(http_open_timeout: 2)
194
+ end
195
+
196
+ it "will set http_read_timeout by default" do
197
+ expect(subject.kinesis_client_config).to include(http_read_timeout: 60)
198
+ end
199
+
200
+ context "when Journaled.http_idle_timeout is specified" do
201
+ it "will set http_idle_timeout by specified value" do
202
+ allow(Journaled).to receive(:http_idle_timeout).and_return(2)
203
+ expect(subject.kinesis_client_config).to include(http_idle_timeout: 2)
204
+ end
205
+ end
206
+
207
+ context "when Journaled.http_open_timeout is specified" do
208
+ it "will set http_open_timeout by specified value" do
209
+ allow(Journaled).to receive(:http_open_timeout).and_return(1)
210
+ expect(subject.kinesis_client_config).to include(http_open_timeout: 1)
211
+ end
212
+ end
213
+
214
+ context "when Journaled.http_read_timeout is specified" do
215
+ it "will set http_read_timeout by specified value" do
216
+ allow(Journaled).to receive(:http_read_timeout).and_return(2)
217
+ expect(subject.kinesis_client_config).to include(http_read_timeout: 2)
218
+ end
219
+ end
220
+ end
221
+ end
@@ -49,4 +49,43 @@ RSpec.describe Journaled do
49
49
  expect(described_class.actor_uri).to eq "my actor uri"
50
50
  end
51
51
  end
52
+
53
+ describe '.detect_queue_adapter!' do
54
+ it 'raises an error unless the queue adapter is DB-backed' do
55
+ expect { described_class.detect_queue_adapter! }.to raise_error <<~MSG
56
+ Journaled has detected an unsupported ActiveJob queue adapter: `:test`
57
+
58
+ Journaled jobs must be enqueued transactionally to your primary database.
59
+
60
+ Please install the appropriate gems and set `queue_adapter` to one of the following:
61
+ - `:delayed`
62
+ - `:delayed_job`
63
+ - `:good_job`
64
+ - `:que`
65
+
66
+ Read more at https://github.com/Betterment/journaled
67
+ MSG
68
+ end
69
+
70
+ context 'when the queue adapter is supported' do
71
+ before do
72
+ stub_const("ActiveJob::QueueAdapters::DelayedAdapter", Class.new)
73
+ ActiveJob::Base.disable_test_adapter
74
+ ActiveJob::Base.queue_adapter = :delayed
75
+ end
76
+
77
+ around do |example|
78
+ begin
79
+ example.run
80
+ ensure
81
+ ActiveJob::Base.queue_adapter = :test
82
+ ActiveJob::Base.enable_test_adapter(ActiveJob::QueueAdapters::TestAdapter.new)
83
+ end
84
+ end
85
+
86
+ it 'does not raise an error' do
87
+ expect { described_class.detect_queue_adapter! }.not_to raise_error
88
+ end
89
+ end
90
+ end
52
91
  end
@@ -4,38 +4,42 @@ if Rails::VERSION::MAJOR > 5 || (Rails::VERSION::MAJOR == 5 && Rails::VERSION::M
4
4
  # rubocop:disable Rails/SkipsModelValidations
5
5
  RSpec.describe "Raw database change protection" do
6
6
  let(:journaled_class) do
7
- Class.new(Delayed::Job) do
7
+ Class.new(ActiveRecord::Base) do
8
8
  include Journaled::Changes
9
9
 
10
- journal_changes_to :locked_at, as: :attempt
10
+ self.table_name = 'widgets'
11
+
12
+ journal_changes_to :name, as: :attempt
11
13
  end
12
14
  end
13
15
 
14
16
  let(:journaled_class_with_no_journaled_columns) do
15
- Class.new(Delayed::Job) do
17
+ Class.new(ActiveRecord::Base) do
16
18
  include Journaled::Changes
19
+
20
+ self.table_name = 'widgets'
17
21
  end
18
22
  end
19
23
 
20
24
  describe "the relation" do
21
25
  describe "#update_all" do
22
26
  it "refuses on journaled columns passed as hash" do
23
- expect { journaled_class.update_all(locked_at: nil) }.to raise_error(/aborted by Journaled/)
27
+ expect { journaled_class.update_all(name: nil) }.to raise_error(/aborted by Journaled/)
24
28
  end
25
29
 
26
30
  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
+ expect { journaled_class.update_all("\"name\" = NULL") }.to raise_error(/aborted by Journaled/)
32
+ expect { journaled_class.update_all("name = null") }.to raise_error(/aborted by Journaled/)
33
+ expect { journaled_class.update_all("widgets.name = null") }.to raise_error(/aborted by Journaled/)
34
+ expect { journaled_class.update_all("other_column = 'name'") }.not_to raise_error
31
35
  end
32
36
 
33
37
  it "succeeds on unjournaled columns" do
34
- expect { journaled_class.update_all(handler: "") }.not_to raise_error
38
+ expect { journaled_class.update_all(other_column: "") }.not_to raise_error
35
39
  end
36
40
 
37
41
  it "succeeds when forced on journaled columns" do
38
- expect { journaled_class.update_all({ locked_at: nil }, force: true) }.not_to raise_error
42
+ expect { journaled_class.update_all({ name: nil }, force: true) }.not_to raise_error
39
43
  end
40
44
  end
41
45
 
@@ -69,29 +73,19 @@ if Rails::VERSION::MAJOR > 5 || (Rails::VERSION::MAJOR == 5 && Rails::VERSION::M
69
73
  end
70
74
 
71
75
  describe "an instance" do
72
- let(:job) do
73
- module TestJob
74
- def perform
75
- "foo"
76
- end
77
-
78
- module_function :perform
79
- end
80
- end
81
-
82
- subject { journaled_class.enqueue(job) }
76
+ subject { journaled_class.create!(name: 'foo') }
83
77
 
84
78
  describe "#update_columns" do
85
79
  it "refuses on journaled columns" do
86
- expect { subject.update_columns(locked_at: nil) }.to raise_error(/aborted by Journaled/)
80
+ expect { subject.update_columns(name: nil) }.to raise_error(/aborted by Journaled/)
87
81
  end
88
82
 
89
83
  it "succeeds on unjournaled columns" do
90
- expect { subject.update_columns(handler: "") }.not_to raise_error
84
+ expect { subject.update_columns(other_column: "") }.not_to raise_error
91
85
  end
92
86
 
93
87
  it "succeeds when forced on journaled columns" do
94
- expect { subject.update_columns({ locked_at: nil }, force: true) }.not_to raise_error
88
+ expect { subject.update_columns({ name: nil }, force: true) }.not_to raise_error
95
89
  end
96
90
  end
97
91
 
@@ -101,7 +95,7 @@ if Rails::VERSION::MAJOR > 5 || (Rails::VERSION::MAJOR == 5 && Rails::VERSION::M
101
95
  end
102
96
 
103
97
  it "succeeds if no journaled columns exist" do
104
- instance = journaled_class_with_no_journaled_columns.enqueue(job)
98
+ instance = journaled_class_with_no_journaled_columns.create!
105
99
  expect { instance.delete }.not_to raise_error
106
100
  end
107
101
 
@@ -80,16 +80,12 @@ RSpec.describe Journaled::Writer do
80
80
  )
81
81
  end
82
82
 
83
- around do |example|
84
- with_jobs_delayed { example.run }
85
- end
86
-
87
83
  context 'when the journaled event does NOT comply with the base_event schema' do
88
84
  let(:journaled_event_attributes) { { foo: 1 } }
89
85
 
90
86
  it 'raises an error and does not enqueue anything' do
91
87
  expect { subject.journal! }.to raise_error JSON::Schema::ValidationError
92
- expect(Delayed::Job.where('handler like ?', '%Journaled::Delivery%').count).to eq 0
88
+ expect(enqueued_jobs.count).to eq 0
93
89
  end
94
90
  end
95
91
 
@@ -99,7 +95,7 @@ RSpec.describe Journaled::Writer do
99
95
 
100
96
  it 'raises an error and does not enqueue anything' do
101
97
  expect { subject.journal! }.to raise_error JSON::Schema::ValidationError
102
- expect(Delayed::Job.where('handler like ?', '%Journaled::Delivery%').count).to eq 0
98
+ expect(enqueued_jobs.count).to eq 0
103
99
  end
104
100
  end
105
101
 
@@ -107,9 +103,8 @@ RSpec.describe Journaled::Writer do
107
103
  let(:journaled_event_attributes) { { id: 'FAKE_UUID', event_type: 'fake_event', created_at: Time.zone.now, foo: :bar } }
108
104
 
109
105
  it 'creates a delivery with the app name passed through' do
110
- allow(Journaled::Delivery).to receive(:new).and_call_original
111
- subject.journal!
112
- expect(Journaled::Delivery).to have_received(:new).with(hash_including(app_name: 'my_app'))
106
+ expect { subject.journal! }.to change { enqueued_jobs.count }.from(0).to(1)
107
+ expect(enqueued_jobs.first[:args].first).to include('app_name' => 'my_app')
113
108
  end
114
109
 
115
110
  context 'when there is no job priority specified in the enqueue opts' do
@@ -122,7 +117,11 @@ RSpec.describe Journaled::Writer do
122
117
 
123
118
  it 'defaults to the global default' do
124
119
  expect { subject.journal! }.to change {
125
- Delayed::Job.where('handler like ?', '%Journaled::Delivery%').where(priority: 999).count
120
+ if Rails::VERSION::MAJOR < 6
121
+ enqueued_jobs.select { |j| j[:job] == Journaled::DeliveryJob }.count
122
+ else
123
+ enqueued_jobs.select { |j| j['job_class'] == 'Journaled::DeliveryJob' && j['priority'] == 999 }.count
124
+ end
126
125
  }.from(0).to(1)
127
126
  end
128
127
  end
@@ -130,9 +129,13 @@ RSpec.describe Journaled::Writer do
130
129
  context 'when there is a job priority specified in the enqueue opts' do
131
130
  let(:journaled_enqueue_opts) { { priority: 13 } }
132
131
 
133
- it 'enqueues a Journaled::Delivery object with the given priority' do
132
+ it 'enqueues a Journaled::DeliveryJob with the given priority' do
134
133
  expect { subject.journal! }.to change {
135
- Delayed::Job.where('handler like ?', '%Journaled::Delivery%').where(priority: 13).count
134
+ if Rails::VERSION::MAJOR < 6
135
+ enqueued_jobs.select { |j| j[:job] == Journaled::DeliveryJob }.count
136
+ else
137
+ enqueued_jobs.select { |j| j['job_class'] == 'Journaled::DeliveryJob' && j['priority'] == 13 }.count
138
+ end
136
139
  }.from(0).to(1)
137
140
  end
138
141
  end
data/spec/rails_helper.rb CHANGED
@@ -6,7 +6,6 @@ require 'rspec/rails'
6
6
  require 'timecop'
7
7
  require 'webmock/rspec'
8
8
  require 'journaled/rspec'
9
- require 'pry-rails'
10
9
 
11
10
  Dir[Rails.root.join('..', 'support', '**', '*.rb')].each { |f| require f }
12
11
 
@@ -15,6 +14,6 @@ RSpec.configure do |config|
15
14
 
16
15
  config.infer_spec_type_from_file_location!
17
16
 
18
- config.include DelayedJobSpecHelper
17
+ config.include ActiveJob::TestHelper
19
18
  config.include EnvironmentSpecHelper
20
19
  end
data/spec/spec_helper.rb CHANGED
@@ -1,9 +1,7 @@
1
- require 'delayed_job_active_record'
2
1
  rails_env = ENV['RAILS_ENV'] ||= 'test'
3
- db_adapter = ENV['DB_ADAPTER'] ||= 'postgresql'
4
2
  require File.expand_path('dummy/config/environment.rb', __dir__)
5
3
 
6
- Rails.configuration.database_configuration[db_adapter][rails_env].tap do |c|
4
+ Rails.configuration.database_configuration[rails_env].tap do |c|
7
5
  ActiveRecord::Tasks::DatabaseTasks.create(c)
8
6
  ActiveRecord::Base.establish_connection(c)
9
7
  load File.expand_path('dummy/db/schema.rb', __dir__)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: journaled
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.5.0
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jake Lipson
@@ -11,24 +11,24 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2021-02-02 00:00:00.000000000 Z
14
+ date: 2021-05-18 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
- name: aws-sdk-kinesis
17
+ name: activejob
18
18
  requirement: !ruby/object:Gem::Requirement
19
19
  requirements:
20
- - - "<"
20
+ - - ">="
21
21
  - !ruby/object:Gem::Version
22
- version: '2'
22
+ version: '0'
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
- - - "<"
27
+ - - ">="
28
28
  - !ruby/object:Gem::Version
29
- version: '2'
29
+ version: '0'
30
30
  - !ruby/object:Gem::Dependency
31
- name: delayed_job
31
+ name: activerecord
32
32
  requirement: !ruby/object:Gem::Requirement
33
33
  requirements:
34
34
  - - ">="
@@ -41,6 +41,20 @@ dependencies:
41
41
  - - ">="
42
42
  - !ruby/object:Gem::Version
43
43
  version: '0'
44
+ - !ruby/object:Gem::Dependency
45
+ name: aws-sdk-kinesis
46
+ requirement: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - "<"
49
+ - !ruby/object:Gem::Version
50
+ version: '2'
51
+ type: :runtime
52
+ prerelease: false
53
+ version_requirements: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - "<"
56
+ - !ruby/object:Gem::Version
57
+ version: '2'
44
58
  - !ruby/object:Gem::Dependency
45
59
  name: json-schema
46
60
  requirement: !ruby/object:Gem::Requirement
@@ -56,7 +70,7 @@ dependencies:
56
70
  - !ruby/object:Gem::Version
57
71
  version: '0'
58
72
  - !ruby/object:Gem::Dependency
59
- name: rails
73
+ name: railties
60
74
  requirement: !ruby/object:Gem::Requirement
61
75
  requirements:
62
76
  - - ">="
@@ -103,48 +117,6 @@ dependencies:
103
117
  - - "~>"
104
118
  - !ruby/object:Gem::Version
105
119
  version: 2.2.0
106
- - !ruby/object:Gem::Dependency
107
- name: delayed_job_active_record
108
- requirement: !ruby/object:Gem::Requirement
109
- requirements:
110
- - - ">="
111
- - !ruby/object:Gem::Version
112
- version: '0'
113
- type: :development
114
- prerelease: false
115
- version_requirements: !ruby/object:Gem::Requirement
116
- requirements:
117
- - - ">="
118
- - !ruby/object:Gem::Version
119
- version: '0'
120
- - !ruby/object:Gem::Dependency
121
- name: pg
122
- requirement: !ruby/object:Gem::Requirement
123
- requirements:
124
- - - ">="
125
- - !ruby/object:Gem::Version
126
- version: '0'
127
- type: :development
128
- prerelease: false
129
- version_requirements: !ruby/object:Gem::Requirement
130
- requirements:
131
- - - ">="
132
- - !ruby/object:Gem::Version
133
- version: '0'
134
- - !ruby/object:Gem::Dependency
135
- name: pry-rails
136
- requirement: !ruby/object:Gem::Requirement
137
- requirements:
138
- - - ">="
139
- - !ruby/object:Gem::Version
140
- version: '0'
141
- type: :development
142
- prerelease: false
143
- version_requirements: !ruby/object:Gem::Requirement
144
- requirements:
145
- - - ">="
146
- - !ruby/object:Gem::Version
147
- version: '0'
148
120
  - !ruby/object:Gem::Dependency
149
121
  name: rspec-rails
150
122
  requirement: !ruby/object:Gem::Requirement
@@ -216,19 +188,19 @@ dependencies:
216
188
  - !ruby/object:Gem::Version
217
189
  version: '0'
218
190
  - !ruby/object:Gem::Dependency
219
- name: sprockets
191
+ name: sqlite3
220
192
  requirement: !ruby/object:Gem::Requirement
221
193
  requirements:
222
- - - "<"
194
+ - - ">="
223
195
  - !ruby/object:Gem::Version
224
- version: '4.0'
196
+ version: '0'
225
197
  type: :development
226
198
  prerelease: false
227
199
  version_requirements: !ruby/object:Gem::Requirement
228
200
  requirements:
229
- - - "<"
201
+ - - ">="
230
202
  - !ruby/object:Gem::Version
231
- version: '4.0'
203
+ version: '0'
232
204
  - !ruby/object:Gem::Dependency
233
205
  name: timecop
234
206
  requirement: !ruby/object:Gem::Requirement
@@ -272,6 +244,8 @@ files:
272
244
  - README.md
273
245
  - Rakefile
274
246
  - app/controllers/concerns/journaled/actor.rb
247
+ - app/jobs/journaled/application_job.rb
248
+ - app/jobs/journaled/delivery_job.rb
275
249
  - app/models/concerns/journaled/changes.rb
276
250
  - app/models/journaled/actor_uri_provider.rb
277
251
  - app/models/journaled/change.rb
@@ -283,13 +257,11 @@ files:
283
257
  - app/models/journaled/not_truly_exceptional_error.rb
284
258
  - app/models/journaled/writer.rb
285
259
  - config/initializers/change_protection.rb
286
- - config/routes.rb
287
260
  - config/spring.rb
288
261
  - journaled_schemas/base_event.json
289
262
  - journaled_schemas/journaled/change.json
290
263
  - lib/journaled.rb
291
264
  - lib/journaled/engine.rb
292
- - lib/journaled/enqueue.rb
293
265
  - lib/journaled/relation_change_protection.rb
294
266
  - lib/journaled/rspec.rb
295
267
  - lib/journaled/version.rb
@@ -304,9 +276,7 @@ files:
304
276
  - spec/dummy/config/database.yml
305
277
  - spec/dummy/config/environment.rb
306
278
  - spec/dummy/config/environments/development.rb
307
- - spec/dummy/config/environments/production.rb
308
279
  - spec/dummy/config/environments/test.rb
309
- - spec/dummy/config/initializers/assets.rb
310
280
  - spec/dummy/config/initializers/backtrace_silencers.rb
311
281
  - spec/dummy/config/initializers/cookies_serializer.rb
312
282
  - spec/dummy/config/initializers/filter_parameter_logging.rb
@@ -317,12 +287,12 @@ files:
317
287
  - spec/dummy/config/locales/en.yml
318
288
  - spec/dummy/config/routes.rb
319
289
  - spec/dummy/config/secrets.yml
320
- - spec/dummy/db/migrate/20180606205114_create_delayed_jobs.rb
321
290
  - spec/dummy/db/schema.rb
322
291
  - spec/dummy/public/404.html
323
292
  - spec/dummy/public/422.html
324
293
  - spec/dummy/public/500.html
325
294
  - spec/dummy/public/favicon.ico
295
+ - spec/jobs/journaled/delivery_job_spec.rb
326
296
  - spec/lib/journaled_spec.rb
327
297
  - spec/models/concerns/journaled/actor_spec.rb
328
298
  - spec/models/concerns/journaled/changes_spec.rb
@@ -335,7 +305,6 @@ files:
335
305
  - spec/models/journaled/writer_spec.rb
336
306
  - spec/rails_helper.rb
337
307
  - spec/spec_helper.rb
338
- - spec/support/delayed_job_spec_helper.rb
339
308
  - spec/support/environment_spec_helper.rb
340
309
  homepage: http://github.com/Betterment/journaled
341
310
  licenses:
@@ -368,7 +337,6 @@ test_files:
368
337
  - spec/dummy/config/secrets.yml
369
338
  - spec/dummy/config/routes.rb
370
339
  - spec/dummy/config/locales/en.yml
371
- - spec/dummy/config/environments/production.rb
372
340
  - spec/dummy/config/environments/development.rb
373
341
  - spec/dummy/config/environments/test.rb
374
342
  - spec/dummy/config/environment.rb
@@ -380,7 +348,6 @@ test_files:
380
348
  - spec/dummy/config/initializers/filter_parameter_logging.rb
381
349
  - spec/dummy/config/initializers/session_store.rb
382
350
  - spec/dummy/config/initializers/wrap_parameters.rb
383
- - spec/dummy/config/initializers/assets.rb
384
351
  - spec/dummy/config/initializers/cookies_serializer.rb
385
352
  - spec/dummy/config/initializers/inflections.rb
386
353
  - spec/dummy/config.ru
@@ -390,7 +357,6 @@ test_files:
390
357
  - spec/dummy/public/500.html
391
358
  - spec/dummy/public/404.html
392
359
  - spec/dummy/db/schema.rb
393
- - spec/dummy/db/migrate/20180606205114_create_delayed_jobs.rb
394
360
  - spec/dummy/README.rdoc
395
361
  - spec/models/journaled/json_schema_model/validator_spec.rb
396
362
  - spec/models/journaled/actor_uri_provider_spec.rb
@@ -401,7 +367,7 @@ test_files:
401
367
  - spec/models/database_change_protection_spec.rb
402
368
  - spec/models/concerns/journaled/changes_spec.rb
403
369
  - spec/models/concerns/journaled/actor_spec.rb
404
- - spec/support/delayed_job_spec_helper.rb
405
370
  - spec/support/environment_spec_helper.rb
406
371
  - spec/lib/journaled_spec.rb
372
+ - spec/jobs/journaled/delivery_job_spec.rb
407
373
  - spec/rails_helper.rb
data/config/routes.rb DELETED
@@ -1,2 +0,0 @@
1
- Rails.application.routes.draw do
2
- end
@@ -1,13 +0,0 @@
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,78 +0,0 @@
1
- Rails.application.configure do
2
- # Settings specified here will take precedence over those in config/application.rb.
3
-
4
- # Code is not reloaded between requests.
5
- config.cache_classes = true
6
-
7
- # Eager load code on boot. This eager loads most of Rails and
8
- # your application in memory, allowing both threaded web servers
9
- # and those relying on copy on write to perform better.
10
- # Rake tasks automatically ignore this option for performance.
11
- config.eager_load = true
12
-
13
- # Full error reports are disabled and caching is turned on.
14
- config.consider_all_requests_local = false
15
- config.action_controller.perform_caching = true
16
-
17
- # Enable Rack::Cache to put a simple HTTP cache in front of your application
18
- # Add `rack-cache` to your Gemfile before enabling this.
19
- # For large-scale production use, consider using a caching reverse proxy like nginx, varnish or squid.
20
- # config.action_dispatch.rack_cache = true
21
-
22
- # Disable Rails's static asset server (Apache or nginx will already do this).
23
- config.serve_static_assets = false
24
-
25
- # Compress JavaScripts and CSS.
26
- config.assets.js_compressor = :uglifier
27
- # config.assets.css_compressor = :sass
28
-
29
- # Do not fallback to assets pipeline if a precompiled asset is missed.
30
- config.assets.compile = false
31
-
32
- # Generate digests for assets URLs.
33
- config.assets.digest = true
34
-
35
- # `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb
36
-
37
- # Specifies the header that your server uses for sending files.
38
- # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache
39
- # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx
40
-
41
- # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
42
- # config.force_ssl = true
43
-
44
- # Set to :debug to see everything in the log.
45
- config.log_level = :info
46
-
47
- # Prepend all log lines with the following tags.
48
- # config.log_tags = [ :subdomain, :uuid ]
49
-
50
- # Use a different logger for distributed setups.
51
- # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
52
-
53
- # Use a different cache store in production.
54
- # config.cache_store = :mem_cache_store
55
-
56
- # Enable serving of images, stylesheets, and JavaScripts from an asset server.
57
- # config.action_controller.asset_host = "http://assets.example.com"
58
-
59
- # Ignore bad email addresses and do not raise email delivery errors.
60
- # Set this to true and configure the email server for immediate delivery to raise delivery errors.
61
- # config.action_mailer.raise_delivery_errors = false
62
-
63
- # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
64
- # the I18n.default_locale when a translation cannot be found).
65
- config.i18n.fallbacks = true
66
-
67
- # Send deprecation notices to registered listeners.
68
- config.active_support.deprecation = :notify
69
-
70
- # Disable automatic flushing of the log to improve performance.
71
- # config.autoflush_log = false
72
-
73
- # Use default logging formatter so that PID and timestamp are not suppressed.
74
- config.log_formatter = ::Logger::Formatter.new
75
-
76
- # Do not dump schema after migrations.
77
- config.active_record.dump_schema_after_migration = false
78
- end
@@ -1,8 +0,0 @@
1
- # Be sure to restart your server when you modify this file.
2
-
3
- # Version of your assets, change this if you want to expire all your assets.
4
- Rails.application.config.assets.version = '1.0'
5
-
6
- # Precompile additional assets.
7
- # application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
8
- # Rails.application.config.assets.precompile += %w( search.js )
@@ -1,18 +0,0 @@
1
- class CreateDelayedJobs < ActiveRecord::Migration[5.1]
2
- def change
3
- create_table :delayed_jobs do |t|
4
- t.integer :priority, default: 0, null: false # Allows some jobs to jump to the front of the queue
5
- t.integer :attempts, default: 0, null: false # Provides for retries, but still fail eventually.
6
- t.text :handler, null: false # YAML-encoded string of the object that will do work
7
- t.text :last_error # reason for last failure (See Note below)
8
- t.datetime :run_at # When to run. Could be Time.zone.now for immediately, or sometime in the future.
9
- t.datetime :locked_at # Set when a client is working on this object
10
- t.datetime :failed_at # Set when all retries have failed (actually, by default, the record is deleted instead)
11
- t.string :locked_by # Who is working on this object (if locked)
12
- t.string :queue # The name of the queue this job is in
13
- t.timestamps null: true
14
- end
15
-
16
- add_index :delayed_jobs, [:priority, :run_at], name: "delayed_jobs_priority"
17
- end
18
- end
@@ -1,11 +0,0 @@
1
- module DelayedJobSpecHelper
2
- def with_jobs_delayed(opts = {})
3
- work_off = opts.fetch(:work_off, true)
4
- original = Delayed::Worker.delay_jobs
5
- Delayed::Worker.delay_jobs = true
6
- yield
7
- ensure
8
- Delayed::Worker.delay_jobs = original
9
- Delayed::Worker.new.work_off if work_off
10
- end
11
- end