lib/eco/api/session/batch.rb in eco-helpers-2.0.42 vs lib/eco/api/session/batch.rb in eco-helpers-2.0.43

- old
+ new

@@ -90,46 +90,83 @@ fatal "cannot batch get without api connnection, please provide a valid api connection!" unless people_api = api&.people params = {per_page: DEFAULT_BATCH_BLOCK}.merge(params) return 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) 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 # 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, + people_api: people_api, + 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 iterations = (data.length.to_f / per_page).ceil - Eco::API::Session::Batch::Status.new(enviro, queue: data, method: method).tap do |status| + status ||= Eco::API::Session::Batch::Status.new(enviro, queue: data, method: method) + status.tap do |status| start_time = Time.now start_slice = Time.now; slice = [] + pending_for_server_error = data.to_a[0..-1] 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)})" logger.info(msg) unless silent start_slice = Time.now offer_retry_on(Ecoportal::API::Errors::TimeOut) do - people_api.batch do |batch| + 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 - status[person] = response + unless server_error?(response) + pending_for_server_error.delete(person) + status[person] = response + end end end end # end batch end iteration += 1 done += slice.length end # next slice + + # 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, + people_api: people_api, + 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 + server_error || other_error || no_body end def offer_retry_on(error_type, retries_left = 3, &block) begin block.call