-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #18 from onemedical/update_to_use_import
Adding support for mysql upsert via AR import
- Loading branch information
Showing
14 changed files
with
328 additions
and
179 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,3 @@ | ||
Gemfile.lock | ||
|
||
.idea/* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
require 'acts_as_scrubbable/import_processor' | ||
require 'acts_as_scrubbable/update_processor' | ||
require 'term/ansicolor' | ||
|
||
module ActsAsScrubbable | ||
class ArClassProcessor | ||
|
||
attr_reader :ar_class, :query_processor | ||
|
||
def initialize(ar_class) | ||
@ar_class = ar_class | ||
|
||
if ActsAsScrubbable.use_upsert | ||
ActsAsScrubbable.logger.info Term::ANSIColor.white("Using Upsert") | ||
@query_processor = ImportProcessor.new(ar_class) | ||
else | ||
ActsAsScrubbable.logger.info Term::ANSIColor.white("Using Update") | ||
@query_processor = UpdateProcessor.new(ar_class) | ||
end | ||
end | ||
|
||
def process(num_of_batches) | ||
ActsAsScrubbable.logger.info Term::ANSIColor.green("Scrubbing #{ar_class} ...") | ||
|
||
num_of_batches = Integer(ENV.fetch("SCRUB_BATCHES", "256")) if num_of_batches.nil? | ||
scrubbed_count = ActsAsScrubbable::ParallelTableScrubber.new(ar_class, num_of_batches).each_query do |query| | ||
query_processor.scrub_query(query) | ||
end | ||
|
||
ActsAsScrubbable.logger.info Term::ANSIColor.blue("#{scrubbed_count} #{ar_class} objects scrubbed") | ||
ActiveRecord::Base.connection.verify! | ||
|
||
ActsAsScrubbable.logger.info Term::ANSIColor.white("Scrub Complete!") | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
module ActsAsScrubbable | ||
module BaseProcessor | ||
attr_reader :ar_class | ||
private :ar_class | ||
|
||
def initialize(ar_class) | ||
@ar_class = ar_class | ||
end | ||
|
||
def scrub_query(query = nil) | ||
scrubbed_count = 0 | ||
ActiveRecord::Base.connection_pool.with_connection do | ||
if ar_class.respond_to?(:scrubbable_scope) | ||
relation = ar_class.send(:scrubbable_scope) | ||
else | ||
relation = ar_class.all | ||
end | ||
|
||
relation.where(query).find_in_batches(batch_size: 1000) do |batch| | ||
ActiveRecord::Base.transaction do | ||
scrubbed_count += handle_batch(batch) | ||
end | ||
end | ||
end | ||
scrubbed_count | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
require 'acts_as_scrubbable/base_processor' | ||
|
||
module ActsAsScrubbable | ||
class ImportProcessor | ||
include BaseProcessor | ||
|
||
private | ||
def handle_batch(batch) | ||
scrubbed_count = 0 | ||
batch.each do |obj| | ||
_updates = obj.scrubbed_values | ||
obj.assign_attributes(_updates) | ||
scrubbed_count += 1 | ||
end | ||
ar_class.import( | ||
batch, | ||
on_duplicate_key_update: ar_class.scrubbable_fields.keys.map { |x| "#{x} = values(#{x})" }.join(" , "), | ||
validate: false, | ||
timestamps: false | ||
) | ||
scrubbed_count | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
require 'acts_as_scrubbable/parallel_table_scrubber' | ||
require 'highline/import' | ||
require 'acts_as_scrubbable/ar_class_processor' | ||
require 'term/ansicolor' | ||
|
||
module ActsAsScrubbable | ||
class TaskRunner | ||
attr_reader :ar_classes | ||
private :ar_classes | ||
|
||
def initialize | ||
@ar_classes = [] | ||
end | ||
|
||
def prompt_db_configuration | ||
db_host = ActiveRecord::Base.connection_config[:host] | ||
db_name = ActiveRecord::Base.connection_config[:database] | ||
|
||
ActsAsScrubbable.logger.warn Term::ANSIColor.red("Please verify the information below to continue") | ||
ActsAsScrubbable.logger.warn Term::ANSIColor.red("Host: ") + Term::ANSIColor.white(" #{db_host}") | ||
ActsAsScrubbable.logger.warn Term::ANSIColor.red("Database: ") + Term::ANSIColor.white("#{db_name}") | ||
end | ||
|
||
def confirmed_configuration? | ||
db_host = ActiveRecord::Base.connection_config[:host] | ||
|
||
unless ENV["SKIP_CONFIRM"] == "true" | ||
answer = ask("Type '#{db_host}' to continue. \n".red + '-> '.white) | ||
unless answer == db_host | ||
ActsAsScrubbable.logger.error Term::ANSIColor.red("exiting ...") | ||
return false | ||
end | ||
end | ||
true | ||
end | ||
|
||
def extract_ar_classes | ||
Rails.application.eager_load! # make sure all the classes are loaded | ||
@ar_classes = ActiveRecord::Base.descendants.select { |d| d.scrubbable? }.sort_by { |d| d.to_s } | ||
|
||
if ENV["SCRUB_CLASSES"].present? | ||
class_list = ENV["SCRUB_CLASSES"].split(",") | ||
class_list = class_list.map { |_class_str| _class_str.constantize } | ||
@ar_classes = ar_classes & class_list | ||
end | ||
end | ||
|
||
def set_ar_class(ar_class) | ||
ar_classes << ar_class | ||
end | ||
|
||
def scrub(num_of_batches: nil) | ||
Parallel.each(ar_classes) do |ar_class| | ||
ActsAsScrubbable::ArClassProcessor.new(ar_class).process(num_of_batches) | ||
end | ||
ActiveRecord::Base.connection.verify! | ||
end | ||
|
||
def after_hooks | ||
if ENV["SKIP_AFTERHOOK"].blank? | ||
ActsAsScrubbable.logger.info Term::ANSIColor.red("Running after hook") | ||
ActsAsScrubbable.execute_after_hook | ||
end | ||
end | ||
end | ||
end |
Oops, something went wrong.