Skip to content

Commit

Permalink
refactoring classes AsyncBatchDestroyJob and AsyncBatchUpdateJob
Browse files Browse the repository at this point in the history
refactoring classes according to the interface ActiveJob
  • Loading branch information
Ivanov-Anton committed Jul 1, 2020
1 parent 4d0aad6 commit 90c96da
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 34 deletions.
17 changes: 7 additions & 10 deletions app/jobs/async_batch_destroy_job.rb
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
# frozen_string_literal: true

class AsyncBatchDestroyJob
class AsyncBatchDestroyJob < ApplicationJob
include BatchJobsLog
BATCH_SIZE = 1000
queue_as 'batch_actions'

attr_reader :model_class, :sql_query, :who_is
attr_reader :model_class, :who_is

def initialize(model_class, sql_query, who_is)
@model_class = model_class
@sql_query = sql_query
def perform(model_class, sql_query, who_is)
@model_class = model_class.constantize
@who_is = who_is
end

def perform
set_audit_log_data
begin
scoped_records = model_class.constantize.find_by_sql(sql_query + " LIMIT #{BATCH_SIZE}")
model_class.constantize.transaction do
scoped_records = @model_class.find_by_sql(sql_query + " LIMIT #{BATCH_SIZE}")
@model_class.transaction do
scoped_records.each(&:destroy!)
end
end until scoped_records.empty?
Expand Down
19 changes: 8 additions & 11 deletions app/jobs/async_batch_update_job.rb
Original file line number Diff line number Diff line change
@@ -1,26 +1,23 @@
# frozen_string_literal: true

class AsyncBatchUpdateJob
class AsyncBatchUpdateJob < ApplicationJob
include BatchJobsLog
BATCH_SIZE = 1000
queue_as 'batch_actions'

attr_reader :model_class, :sql_query, :changes, :who_is
attr_reader :model_class, :sql_query, :who_is

def initialize(model_class, sql_query, changes, who_is)
@model_class = model_class
def perform(model_class, sql_query, changes, who_is)
@model_class = model_class.constantize
@sql_query = sql_query
@changes = changes
@who_is = who_is
end

def perform
set_audit_log_data
model_class.constantize.transaction do
total_count = model_class.constantize.count_by_sql count_sql_query
@model_class.transaction do
total_count = @model_class.count_by_sql count_sql_query

(total_count.to_f / BATCH_SIZE).ceil.times do |batch_number|
offset = batch_number * BATCH_SIZE
scoped_records = model_class.constantize.find_by_sql(order_by_id_sql + " OFFSET #{offset} LIMIT #{BATCH_SIZE}")
scoped_records = @model_class.find_by_sql(order_by_id_sql + " OFFSET #{offset} LIMIT #{BATCH_SIZE}")
scoped_records.each { |record| record.update!(changes) }
end
end
Expand Down
29 changes: 24 additions & 5 deletions lib/batch_jobs_log.rb
Original file line number Diff line number Diff line change
@@ -1,20 +1,39 @@
# frozen_string_literal: true

module BatchJobsLog
def success(job)
extend ActiveSupport::Concern

included do
attr_reader :delayed_job_record_id

around_perform do |_job, block|
block.call
success
rescue StandardError => error
failure error
end
end

def deserialize(job_data)
@delayed_job_record_id = Delayed::Job.where("handler LIKE '%#{job_data['job_id']}%'").take.id
super
end

def success
LogicLog.create!(
source: "#{self.class} #{job.id}",
source: "#{self.class} #{delayed_job_record_id}",
level: 0,
msg: 'Success'
)
end

def failure(job)
def failure(error)
LogicLog.create!(
source: "#{self.class} #{job.id}",
source: "#{self.class} #{delayed_job_record_id}",
level: 0,
msg: job.last_error
msg: "Error: #{error.message}\nchanges: #{arguments[2]}\nclass: #{arguments[0]}\nqueue: #{queue_name}\nsql: #{arguments[1]}"
)
raise error
end

def set_audit_log_data
Expand Down
5 changes: 2 additions & 3 deletions lib/resource_dsl/acts_as_async_destroy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,9 @@ def acts_as_async_destroy(model_class)
scoped_collection_action :async_destroy,
title: 'Delete batch',
if: proc { authorized?(:batch_destroy, resource_klass) } do
Delayed::Job.enqueue AsyncBatchDestroyJob.new(model_class,
AsyncBatchDestroyJob.perform_later(model_class,
scoped_collection_records.except(:eager_load).to_sql,
@paper_trail_info),
queue: 'batch_actions'
@paper_trail_info)
flash[:notice] = I18n.t('flash.actions.batch_actions.batch_destroy.job_scheduled')
head :ok
end
Expand Down
5 changes: 2 additions & 3 deletions lib/resource_dsl/acts_as_async_update.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,10 @@ def acts_as_async_update(model_class, attrs_to_update)
class: 'scoped_collection_action_button ui',
form: attrs_to_update,
if: proc { authorized?(:batch_destroy, resource_klass) } do
Delayed::Job.enqueue AsyncBatchUpdateJob.new(model_class,
AsyncBatchUpdateJob.perform_later(model_class,
scoped_collection_records.except(:eager_load).to_sql,
params[:changes].permit!,
@paper_trail_info),
queue: 'batch_actions'
@paper_trail_info)
flash[:notice] = I18n.t('flash.actions.batch_actions.batch_update.job_scheduled')
head :ok
end
Expand Down
27 changes: 26 additions & 1 deletion spec/jobs/async_batch_destroy_job_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
include_context :init_destination, id: 2, initial_rate: 0.5
include_context :init_destination, id: 3, initial_rate: 0.7

subject { described_class.new(model_class, sql_query, who_is).perform }
subject { described_class.perform_now(model_class, sql_query, who_is) }

before :each do
stub_const('AsyncBatchDestroyJob::BATCH_SIZE', 2)
Expand Down Expand Up @@ -44,6 +44,31 @@
it { expect { subject }.to change(Routing::Destination, :count).by(-1) }
it { expect { subject }.to change(Routing::Destination.where(id: 1), :count).by(-1) }
end

context 'test LogicLog class' do
let!(:contractor) { create :vendor }
let!(:contractor_alone) { create :vendor }
let!(:gateway_group) { create :gateway_group, vendor: contractor }
let(:model_class) { 'Contractor' }

context 'should write record about' do
let(:sql_query) { Contractor.where(id: contractor_alone.id).to_sql }
it 'success performed job' do
expect { subject }.to change(LogicLog, :count).by 1
expect(LogicLog.last.msg).to start_with 'Success'
end
end

context do
let(:sql_query) { Contractor.all.to_sql }
it 'error performed job' do
expect do
expect { subject }.to raise_error(ActiveRecord::RecordNotDestroyed)
end.to change(LogicLog, :count).by 1
expect(LogicLog.last.msg).to start_with 'Error'
end
end
end
end
end
end
24 changes: 23 additions & 1 deletion spec/jobs/async_batch_update_job_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
include_context :init_destination, id: 2, initial_rate: 0.5
include_context :init_destination, id: 3, initial_rate: 0.7

subject { described_class.new(model_class, sql_query, changes, who_is).perform }
subject { described_class.perform_now(model_class, sql_query, changes, who_is) }

before :each do
stub_const('AsyncBatchUpdateJob::BATCH_SIZE', 2)
Expand Down Expand Up @@ -69,6 +69,28 @@
it { expect { subject }.to change(Routing::Destination.where(id: 1, prefix: 300), :count).by(1) }
end
end

context 'test LogicLog class' do
let(:sql_query) { Routing::Destination.all.to_sql }

context 'should write record about' do
let(:changes) { { next_interval: 4 } }
it 'success performed job' do
expect { subject }.to change(LogicLog, :count).by 1
expect(LogicLog.last.msg).to start_with 'Success'
end
end

context do
let(:changes) { { next_interval: 'string' } }
it 'error performed job' do
expect do
expect { subject }.to raise_error(ActiveRecord::RecordInvalid)
end.to change(LogicLog, :count).by 1
expect(LogicLog.last.msg).to start_with 'Error'
end
end
end
end
end
end

0 comments on commit 90c96da

Please sign in to comment.