lib/eco/api/session/batch.rb in eco-helpers-0.6.17 vs lib/eco/api/session/batch.rb in eco-helpers-0.7.1

- old
+ new

@@ -1,112 +1,162 @@ module Eco module API class Session - # important! the handler should probably only create logs and save the update with same timestamp class Batch < Common::Session::BaseSession DEFAULT_BATCH_BLOCK = 100 - VALID_METHODS = ['get', 'create', 'update', 'upsert', 'delete'] + VALID_METHODS = [:get, :create, :update, :upsert, :delete] - # people can be: empty, an api object, a people object, or an array with id's or persons - def get_people(people = nil, api: nil, params: {per_page: DEFAULT_BATCH_BLOCK}) - api = api || self.api - return batch_from(people, 'get', api, params: params) if people.is_a?(Array) - return batch_get(api, params: params) + class << self + # @return [Boolean] `true` if the method is supported, `false` otherwise. + def valid_method?(value) + VALID_METHODS.include?(value) + end end - def launch(people = nil, method:, api: nil, params: {per_page: DEFAULT_BATCH_BLOCK}) - fatal "Invalid batch method: #{method}." if !valid_method?(method) - return nil if !people || !people.is_a?(Array) - batch_from(people, method, api || self.api, params: params) + # Gets the _people_ of the organization according `params`. + # If `people` is not `nil`, scopes to only the people specified. + # @note + # - If `people` is given keys `page:` and `q` of `params:`. + # @param people [Nil, People, Enumerable<Person>, Enumerable<Hash>] target _People_ to launch the batch against. + # @param params [Hash] api request options. + # @option params [String] :page the page number `page` based on `:per_page`. + # @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: {}) + return launch(people, method: :get, params: params) if people.is_a?(Enumerable) + return get(params: params) end - def valid_method?(value) - VALID_METHODS.include?(value) + # launches a batch of `method` type using `people` and the specified `params` + # @raise Exception + # - if `people` is `nil` or is not an `Enumerable`. + # - if there's no `api` connection linked to the current `Batch`. + # @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 [BatchStatus] the `status` of this batch launch. + def launch(people, method:, params: {} , silent: false) + batch_from(people, method: method, params: params, silent: silent) end + def search(data, params: {}) + params = {per_page: DEFAULT_BATCH_BLOCK}.merge(params) + + launch(data, method: :get, params: params, silent: true).tap do |status| + status.type = :search + status.queue.each do |entry| + 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 + + people_matching = [] + email = email.to_s.strip.downcase + unless email.empty? + people_matching = get(params: params.merge(q: email), silent: true).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 + end + private def new_status(queue, method) BatchStatus.new(enviro, queue: queue, method: method) end - def batch_get(api, params: {}) + def get(params: {}, silent: false) 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) client = people_api.client - people = []; - if page = params[:page] - res, response = get(client, params: params) - people +=res - logger.info("page number: #{page}, got num people #{people.length}") - else - page = 1 - loop do - params = params.merge({page: page}) - people_res, response = get(client, params: params) - people += people_res - total_pages = response.body["total_pages"] - logger.info("page number: #{page}/#{total_pages}, got num people #{people_res.length}, with total #{people.length} people got") - break if page >= total_pages - page += 1 - end + looping = !params.key?(:page) + page = params[:page] || 1 + + people = []; total_pages = nil + loop do + people_res, response = client_get(client, params: params.merge(page: page), silent: silent) + people += people_res + + total_pages ||= response.body["total_pages"] + + msg = "page number: #{page}/#{total_pages}, got num people #{people_res.length}, with total #{people.length} people got" + logger.info(msg) unless silent + + break if page >= total_pages || !looping + page += 1 end + return people end - def get(client, params:) + def client_get(client, params:, silent: false) response = client.get("/people", params: params) unless response.success? msg = "Request failed - params: #{params}" msg += "\n Error message: - Status #{response.status}: #{response.body}" - fatal(msg) + fatal msg end people = [] response.body["results"].each do |person_hash| person = Ecoportal::API::Internal::Person.new(person_hash) yield person if block_given? people.push(person) end [people, response] end - def batch_from(people, method, api, params: {}) - return nil if !people || !people.is_a?(Array) + def batch_from(people, method:, params: {}, silent: false) + fatal "Invalid batch method: #{method}." if !self.class.valid_method?(method) + return nil if !people || !people.is_a?(Enumerable) fatal "cannot batch #{method} without api connnection, please provide a valid api connection!" unless people_api = api&.people # batch Status status = new_status(people, method) # param q does not make sense here, even for GET method - params = {per_page: DEFAULT_BATCH_BLOCK}.merge(params) - per_page = params.fetch(:per_page) + params = {per_page: DEFAULT_BATCH_BLOCK}.merge(params) + per_page = params[:per_page] || DEFAULT_BATCH_BLOCK iteration = 1; done = 0 iterations = (people.length.to_f / per_page).ceil people.each_slice(per_page) do |slice| msg = "starting batch '#{method}' iteration #{iteration}/#{iterations}, with #{slice.length} entries of #{people.length} -- #{done} done" - logger.info(msg) + logger.info(msg) unless silent people_api.batch do |batch| slice.each do |person| - # valid method checked before batch.public_send(method, person) do |response| + faltal("Request with no response") unless !!response status[person] = response - #status.print_error(person) - end # current person - end # next person + end + end end # next batch iteration += 1 done += slice.length end # next slice - status.print_errors - + status.print_errors unless silent return status end end end