lib/eco/api/session/batch.rb in eco-helpers-2.7.14 vs lib/eco/api/session/batch.rb in eco-helpers-2.7.15
- old
+ new
@@ -1,12 +1,11 @@
module Eco
module API
class Session
class Batch < Common::Session::BaseSession
-
DEFAULT_BATCH_BLOCK = 50
- VALID_METHODS = [:get, :create, :update, :upsert, :delete]
+ VALID_METHODS = %i[get create update upsert delete].freeze
class << self
# @return [Boolean] `true` if the method is supported, `false` otherwise.
def valid_method?(value)
VALID_METHODS.include?(value)
@@ -23,11 +22,12 @@
# @option params [String] :per_page the number of people included per each batch api request.
# @option params [String] :q some text to search. Omit this parameter to target all the people.
# @return [Array<People>] all the people based on `params`
def get_people(people = nil, params: {}, silent: false)
return launch(people, method: :get, params: params, silent: silent).people if people.is_a?(Enumerable)
- return get(params: params, silent: silent)
+
+ get(params: params, silent: silent)
end
# launches a batch of `method` type using `people` and the specified `params`
# @raise Exception
# - if `people` is `nil` or is not an `Enumerable`.
@@ -35,108 +35,127 @@
# @param people [People, Enumerable<Person>, Enumerable<Hash>] target _People_ to launch the batch against.
# @param method [Symbol] the method to launch the batch api request with.
# @param params [Hash] api request options.
# @option params [String] :per_page the number of people included per each batch api request.
# @return [Batch::Status] the `status` of this batch launch.
- def launch(people, method:, params: {} , silent: false)
+ def launch(people, method:, params: {}, silent: false)
batch_from(people, method: method, params: params, silent: silent)
end
- def search(data, silent: false, params: {})
+ def search(data, silent: false, params: {}) # rubocop:disable Metrics/AbcSize
params = {per_page: DEFAULT_BATCH_BLOCK}.merge(params)
launch(data, method: :get, params: params, silent: silent).tap do |status|
status.mode = :search
entries = status.queue
puts "\n"
entries.each_with_index do |entry, i|
- if (i % 10 == 0)
+ if (i % 10).zero?
percent = i * 100 / entries.length
print "Searching: #{percent.round}% (#{i}/#{entries.length} entries)\r"
$stdout.flush
end
- unless status.success?(entry)
- email = nil
- case
- when entry.respond_to?(:email)
- email = entry.email
- when entry.respond_to?(:to_h)
- email = entry.to_h["email"]
- end
+ next if status.success?(entry)
- people_matching = []
- email = email.to_s.strip.downcase
- unless email.empty?
- people_matching = get(params: params.merge(q: email), silent: silent).select do |person|
- person.email == email
- end
- end
+ email = nil
+ if entry.respond_to?(:email)
+ email = entry.email
+ elsif entry.respond_to?(:to_h)
+ email = entry.to_h["email"]
+ end
- case people_matching.length
- when 1
- status.set_person_match(entry, people_matching.first)
- when 2..Float::INFINITY
- status.set_people_match(entry, people_matching)
+ people_matching = []
+ email = email.to_s.strip.downcase
+ unless email.empty?
+ people_matching = get(params: params.merge(q: email), silent: silent).select do |person|
+ person.email == email
end
end
+
+ case people_matching.length
+ when 1
+ status.set_person_match(entry, people_matching.first)
+ when 2..Float::INFINITY
+ status.set_people_match(entry, people_matching)
+ end
end
end
end
private
def get(params: {}, silent: false)
- fatal "cannot batch get without api connnection, please provide a valid api connection!" unless people_api = api&.people
+ msg = "cannot batch get without api connnection, please provide a valid api connection!"
+ fatal msg unless (people_api = api&.people)
+
params = {per_page: DEFAULT_BATCH_BLOCK}.merge(params)
- return people_api.get_all(params: params, silent: silent)
+ people_api.get_all(params: params, silent: silent)
end
-
def batch_from(data, method:, params: {}, silent: false)
- fatal "Invalid batch method: #{method}." if !self.class.valid_method?(method)
+ fatal "Invalid batch method: #{method}." unless self.class.valid_method?(method)
return nil if !data || !data.is_a?(Enumerable)
- fatal "cannot batch #{method} without api connnection, please provide a valid api connection!" unless people_api = api&.people
+ msg = "cannot batch #{method} without api connnection, please provide a valid api connection!"
+ fatal msg unless (people_api = api&.people)
+
# param q does not make sense here, even for GET method
params = {per_page: DEFAULT_BATCH_BLOCK}.merge(params)
per_page = params[:per_page] || DEFAULT_BATCH_BLOCK
- launch_batch(data,
- method: method,
- per_page: per_page,
+ launch_batch(
+ data,
+ method: method,
+ per_page: per_page,
people_api: people_api,
- silent: silent
+ silent: silent
)
end
- def launch_batch(data, method:, status: nil, job_mode: true, per_page: DEFAULT_BATCH_BLOCK, people_api: api&.people, silent: false)
- iteration = 1; done = 0
+ def launch_batch( # rubocop:disable Metrics/AbcSize
+ data,
+ method:,
+ status: nil,
+ job_mode: true, # rubocop:disable Lint/UnusedMethodArgument
+ per_page: DEFAULT_BATCH_BLOCK,
+ people_api: api&.people,
+ silent: false
+ )
+ iteration = 1
+ done = 0
iterations = (data.length.to_f / per_page).ceil
- status ||= Eco::API::Session::Batch::Status.new(enviro, queue: data, method: method)
- status.tap do |status|
+ status ||= Eco::API::Session::Batch::Status.new(
+ enviro,
+ queue: data,
+ method: method
+ )
+
+ status.tap do
start_time = Time.now
- start_slice = Time.now; slice = []
- pending_for_server_error = data.to_a[0..-1]
+ start_slice = Time.now
+
+ pending_for_server_error = data.to_a[0..]
data.each_slice(per_page) do |slice|
msg = "starting batch '#{method}' iteration #{iteration}/#{iterations},"
- msg += " with #{slice.length} entries of #{data.length} -- #{done} done"
- msg += " (last: #{str_stats(start_slice, slice.length)}; total: #{str_stats(start_time, done)})"
+ msg << " with #{slice.length} entries of #{data.length} -- #{done} done"
+ msg << " (last: #{str_stats(start_slice, slice.length)}; total: #{str_stats(start_time, done)})"
logger.info(msg) unless silent
start_slice = Time.now
offer_retry_on(Ecoportal::API::Errors::TimeOut) do
people_api.batch(job_mode: false) do |batch|
slice.each do |person|
batch.public_send(method, person) do |response|
- faltal("Request with no response") unless !!response
- unless server_error?(response)
- pending_for_server_error.delete(person)
- status[person] = response
- end
+ faltal("Request with no response") unless response
+
+ next if server_error?(response)
+
+ pending_for_server_error.delete(person)
+ status[person] = response
end
end
end # end batch
end
@@ -146,44 +165,45 @@
# temporary working around (due to back-end problems with batch/jobs)
unless pending_for_server_error.empty?
msg = "Going to re-try #{pending_for_server_error.count} due to server errors"
logger.info(msg) unless silent
- launch_batch(pending_for_server_error,
- status: status,
- method: method,
- job_mode: false,
- per_page: per_page,
+
+ launch_batch(
+ pending_for_server_error,
+ status: status,
+ method: method,
+ job_mode: false,
+ per_page: per_page,
people_api: people_api,
- silent: silent
+ silent: silent
)
end
end
end
def server_error?(response)
res_status = response.status
server_error = !res_status || res_status.server_error?
other_error = !server_error && (!res_status.code || res_status.code < 100)
- no_body = !server_error && !other_error && !response.body
+ no_body = !server_error && !other_error && !response.body
server_error || other_error || no_body
end
def offer_retry_on(error_type, retries_left = 3, &block)
- begin
- block.call
- rescue error_type => e
- raise unless retries_left > 0
- explanation = "Batch TimeOut. You have #{retries_left} retries left."
- prompt_user(" Do you want to retry (y/N)?", default: "Y", explanation: explanation, timeout: 10) do |response|
- if response.upcase.start_with?("Y")
- puts "\nOkay... let's retry!"
- offer_retry_on(error_type, retries_left - 1, &block)
- else
- raise
- end
- end
+ block.call
+ rescue error_type
+ raise unless retries_left.positive?
+
+ explanation = "Batch TimeOut. You have #{retries_left} retries left."
+ question = " Do you want to retry (y/N)?"
+
+ prompt_user(question, default: "Y", explanation: explanation, timeout: 10) do |response|
+ raise unless response.upcase.start_with?("Y")
+
+ puts "\nOkay... let's retry!"
+ offer_retry_on(error_type, retries_left - 1, &block)
end
end
def str_stats(start, count)
now = Time.now
@@ -193,10 +213,9 @@
"#{secs}s -> #{per_sec} people/s"
else
" -- "
end
end
-
end
end
end
end