module Eco module API class Session class BatchJob < API::Common::Session::BaseSession TYPES = [:create, :update, :delete, :get] SETS = [:core, :details, :account] attr_reader :name, :status def initialize(name, type:, sets:, root:) raise "A name is required to refer a job. Given: #{name}" if !name raise "Type should be one of #{TYPES}. Given: #{type}" if !BatchJob.valid_type?(type) raise "Sets should be some of #{SETS}. Given: #{sets}" if !BatchJob.valid_sets?(sets) super(root.enviro) @name = name @type = type @sets = [sets].flatten @root = root reset end def reset @queue = [] @callbacks = {} @status = nil end def signature "job \"#{@name}\" ['#{@type.to_s.upcase}': #{sets_title}]" end def match?(type:, sets:) sets = [sets].flatten type == @type && (sets.order == @sets.order) end def pending? @queue.length > 0 end def add(entry) unless !entry @queue.push(entry) @callbacks[entry] = Proc.new if block_given? end end def people Eco::API::Organization::People.new(@queue) end def processed_queue @queue.map do |entry| callback = @callbacks[entry] e = entry e = callback.call(entry) if callback e = nil if as_update(e).empty? && @type!=:delete e end.compact end def launch(simulate: false) queue = processed_queue launch_feedback(queue, simulate ? 2500 : 800) if !simulate && queue.length > 0 backup_update(queue) @status = batch.launch(queue, method: @type.to_s) @status.root = self end logger.info("Simulate: this would have launched: '#{@type.to_s}'") if simulate return @status end def core? sets.include?(:core) end def details? sets.include?(:dettails) end def account? sets.include?(:account) end def self.valid_type?(value) TYPES.include?(value) end def self.valid_sets?(value) sets = [value].flatten sets.all? { |s| SETS.include?(s) } end private def as_update(update) hash = update if update.is_a?(Hash) if @type == :delete hash = update.as_json.slice("id", "external_id") else hash = update.as_update if update.is_a?(Ecoportal::API::V1::Person) fields = hash&.dig('details', 'fields') fields&.map! { |fld| fld&.slice("id", "alt_id", "value") } end hash || {} end def sets_title "#{@sets.map {|s| s.to_s}.join(", ")}" end def launch_feedback(data, max_chars = 800) if !data || !data.is_a?(Array) || data.empty? logger.warn("#{"*" * 20} Nothing for #{signature} so far :) #{"*" * 20}") return end header = ("*" * 20) + " #{signature} - Feedback Sample " + ("*" * 20) logger.info(header) sample_length = 1 sample = data.slice(0, 20).map do |entry| update = as_update(entry) max_chars -= update.pretty_inspect.length sample_length += 1 if max_chars > 0 update end logger.info("#{sample.slice(0, sample_length).pretty_inspect}") logger.info("#{@type.to_s.upcase} length: #{data.length}") logger.info("*" * header.length) end def backup_update(data) data_body = data.map { |u| as_update(u) } dir = config.people.requests_folder file = File.join(dir, "#{@type.to_s}_data.json") file_manager.save_json(data_body, file, :timestamp) end def session @root.session end def batch session.batch end end end end end