lib/eco/api/session/batch/job.rb in eco-helpers-1.1.2 vs lib/eco/api/session/batch/job.rb in eco-helpers-1.1.3

- old
+ new

@@ -64,20 +64,10 @@ # @return [Hash] options the root `usecase` is run with def options usecase?? usecase.options : {} end - def match?(type:, sets:) - sets = [sets].flatten - type == self.type && (sets.order == self.sets.order) - end - - # @return [Boolean] has been this `batch job` launched? - def pending? - @pending - end - # Adds an entry(ies) to the job queue. # @param entry [Person, Enumberable<Person>] the person(s) we want to update, carrying the changes to be done. # @param unique [Boolean] specifies if repeated entries should be avoided in the queue. # @yield [person] callback before launching the batch job request against the server. # @yeldparam param [Person] current person object that that should be treated by the callback before launching the batch. @@ -95,50 +85,114 @@ end end end end + #def match?(type:, sets:) + # sets = [sets].flatten + # type == self.type && (sets.order == self.sets.order) + #end + + # @return [Boolean] has been this `batch job` launched? + def pending? + @pending + end + + # @note it requires launch to be firstly invoked + # @raise [Exception] if 'launch' has not firstly invoked + # @return [Enumbrable<Hash>] the last requests that the queue will generate + def requests + raise "Method missuse. Firstly 'launch' should be invoked" unless instance_variable_defined?(:@requests) + @requests + end + + # @see Eco::API::Session::Batch::Feedback#request_stats + def request_stats(requests = nil) + feedback.request_stats(requests || self.requests) + end + + # @see Eco::API::Session::Batch::Status#errors? + # @return [Boolean] `true` if there were Server errors, `false` otherwise + def errors? + status && status.errors? + end + # Helper/shortcut to obtain a people object out of `input` # @note if `input` is not provided, it will use `queue` # @return [Eco::API::Organization::People] def people(input = @queue) Eco::API::Organization::People.new(input) end # Processes the `queue` and, unless `simulate` is `true`, launches against the server: - # 1. if the entries of `queue` got pending _callbacks_ (delayed changes), it processes them - # 2. unless type == `:create`: if there's a defined `api_excluded` _callback_ it calls it (see `Eco::API::Session::Config::People#api_excluded`) - # 3. transforms the result to a `Eco::API::Organization::People` object - # 4. if there are `api policies` defined, it passes the entries through them in order (see `Eco::API::Session::Config#policies`) - # 5. at this point all the transformations have taken place... - # 6. only include the entries that, after all above, still hold pending changes (`!as_update.empty?`) to be launched as update - # 7. if we are **not** in `dry-run` (or `simulate`), launch the batch request against the server (see `Eco::API::Session::Batch#launch`) - # 8. next, it links the resulting batch `status` to this `Batch::Job` (see `Eco::API::Session::Batch::Status`) - # 9. the post launch kicks in, and for success requests, it consolidates the associated entries (see `Ecoportal::API::V1::Person#consolidate!`) - # 10. launches specific error handlers, if there were **errors** from the Server as a result of the `batch.launch`, and there are `Error::Handlers` defined - # 11. if we are **not** in `dry-run` (or `simulate`), it backs up the raw queries launched to the Server + # 1. pre_processes the queue obtaining the `requests`: + # - if the entries of `queue` got pending _callbacks_ (delayed changes), it processes them + # - unless type == `:create`: if there's a defined `api_excluded` _callback_ it calls it (see `Eco::API::Session::Config::People#api_excluded`) + # - transforms the result to a `Eco::API::Organization::People` object + # - if there are `api policies` defined, it passes the entries through them in order (see `Eco::API::Session::Config#policies`) + # - this step is **skipped** if the option `-skip-api-policies` was used in the command line + # - at this point all the transformations have taken place... + # - only include the entries that, after all above, still hold pending changes (`!as_update.empty?`) to be launched as update + # 2. pre launch checks against the `requests`: + # - it generates `stats` (`Eco::API::Session::Batch::RequestStats`) out of the requests + # - if there is a batch policy declared for the current job `type`, it checks compliance against `stats` (`Eco::API::Session::Batch::Policies`), + # - a non-compliant batch will stop the current session by raising an `Exception` + # - this setp is **skipped** if the option `-skip-batch-policy` was used in the command line + # 3. if we are **not** in `dry-run` (or `simulate`), it: + # - backs up the raw queries (`requests`) launched to the Server, if we are **not** in `dry-run` (or `simulate`) + # - **launches the batch** request against the _Server_ (see `Eco::API::Session::Batch#launch`) + # - links the resulting batch `status` to this `Batch::Job` (see `Eco::API::Session::Batch::Status`) + # - prints any `errors` replied by the _Server_ + # 4. the post launch kicks in, and: + # - for success requests, it consolidates the associated entries (see `Ecoportal::API::V1::Person#consolidate!`) + # - launches specific error handlers, if there were **errors** from the Server as a result of the `batch.launch`, and there are `Error::Handlers` defined + # @return [Eco::API::Session::Batch::Status] def launch(simulate: false) - pqueue = processed_queue - requests = pqueue.map {|e| as_update(e)} + pqueue = processed_queue + @requests = pqueue.map {|e| as_update(e)} pre_checks(requests, simulate: simulate) - if !simulate + unless simulate if pqueue.length > 0 backup_update(requests) - @status = session.batch.launch(pqueue, method: type) - @status.root = self + session.batch.launch(pqueue, method: type).tap do |job_status| + @status = job_status + status.root = self + status.errors.print + end end end - post_launch(queue: pqueue, simulate: simulate) + unless requests.empty? + logger.info("--- simulate mode (dry-run) -- job '#{name}' -- this would have launched #{type.to_s.upcase}") if simulate + end - logger.info("Simulate: this would have launched: '#{type}'") if simulate + post_launch(queue: pqueue, simulate: simulate) @pending = false - return @status + return status end + # Provides a text summary of the current status + # @note if `launch` was not invoked, it specifies so + # @return [String] the summary + def summary + [].tap do |msg| + if pending? + msg << "PENDING - Batch #{type.to_s.upcase} - job '#{name}' - length: #{@queue.length}" + else + msg << feedback.generate(requests, only_stats: true) + if batch_policy && !batch_policy.compliant?(request_stats) + msg << "Batch Policy Uncompliance:" + msg << batch_policy.uncompliance(request_stats) + end + + msg << status.errors.message unless !status + end + end.join("\n") + end + private def as_update(*args) feedback.as_update(*args) end @@ -176,31 +230,32 @@ only_stats = options.dig(:feedback, :only_stats) max_chars = simulate ? 2500 : 800 msg = feedback.generate(requests, max_chars: max_chars, only_stats: only_stats) logger.info(msg) - @request_stats = feedback.request_stats(requests) - if simulate && batch_policy && !batch_policy.compliant?(@request_stats) + # batch_policy + stats = request_stats(requests) + if simulate && batch_policy && !batch_policy.compliant?(stats) logger.warn("Batch Policy Uncompliance: this and next batches will be aborted!") - logger.warn(batch_policy.uncompliance(@request_stats)) + logger.warn(batch_policy.uncompliance(stats)) elsif batch_policy # will throw an Exception if the policy request_stats is not compliant - batch_policy.validate!(@request_stats) + batch_policy.validate!(stats) end end def post_launch(queue: [], simulate: false) - if !simulate && @status - @status.queue.map do |entry| - if @status.success?(entry) + if !simulate && status + status.queue.map do |entry| + if status.success?(entry) entry.consolidate! if entry.respond_to?(:consolidate!) #else # do not entry.reset! (keep track on changes still) end end # launch_error handlers handlers = session.config.error_handlers - if @status.errors.any? && !handlers.empty? - err_types = @status.errors.by_type + if status.errors.any? && !handlers.empty? + err_types = status.errors.by_type handlers.each do |handler| if entries = err_types[handler.name] handler.launch(people: people(entries), session: session, options: options) end end