Class: Eco::API::Session::Batch::Job

Inherits:
Common::Session::BaseSession show all
Defined in:
lib/eco/api/session/batch/job.rb

Class Attribute Summary collapse

Instance Attribute Summary collapse

Attributes inherited from Common::Session::BaseSession

#api, #config, #environment, #file_manager, #logger, #session

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Common::Session::BaseSession

#enviro=, #fatal, #fm, #mailer, #mailer?, #s3uploader, #s3uploader?, #sftp, #sftp?

Constructor Details

#initialize(e, name:, type:, sets:, usecase: nil) ⇒ Job

Returns a new instance of Job.

Parameters:

  • e (Eco::API::Common::Session::Environment)

    requires a session environment, as any child of Eco::API::Common::Session::BaseSession.

  • name (String)

    the name of this batch job

  • type (Symbol)

    a valid batch operation.

  • usecase (Eco::API::UseCases::UseCase, nil) (defaults to: nil)

    when provided: usecase that generated this batch job. This is necessary to know the options used to run the usecase, which could modify the Batch::Job behviour.



37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/eco/api/session/batch/job.rb', line 37

def initialize(e, name:, type:, sets:, usecase: nil)
  raise "A name is required to refer a job. Given: #{name}" if !name
  raise "Type should be one of #{self.class.types}. Given: #{type}"    unless self.class.valid_type?(type)
  raise "Sets should be some of #{self.class.sets}. Given: #{sets}"    unless self.class.valid_sets?(sets)
  raise "usecase must be a Eco::API::UseCases::UseCase object. Given: #{usecase.class}" if usecase && !usecase.is_a?(Eco::API::UseCases::UseCase)
  super(e)

  @name     = name
  @type     = type
  @sets     = [sets].flatten.compact
  @usecase  = usecase
  @feedback = Eco::API::Session::Batch::Feedback.new(job: self)
  reset
end

Class Attribute Details

.setsObject (readonly)

Returns the value of attribute sets.



16
17
18
# File 'lib/eco/api/session/batch/job.rb', line 16

def sets
  @sets
end

.typesObject (readonly)

Returns the value of attribute types.



16
17
18
# File 'lib/eco/api/session/batch/job.rb', line 16

def types
  @types
end

Instance Attribute Details

#feedbackEco::API::Session::Batch::Feedback (readonly)

helper class for feedback and end-user decision making

Returns:



11
12
13
# File 'lib/eco/api/session/batch/job.rb', line 11

def feedback
  @feedback
end

#nameString (readonly)

the name of this batch job

Returns:

  • (String)

    the current value of name



11
12
13
# File 'lib/eco/api/session/batch/job.rb', line 11

def name
  @name
end

#setsArray<Symbol> (readonly)

the parts of the person model this batch is supposed to affect

Returns:

  • (Array<Symbol>)

    the current value of sets



11
12
13
# File 'lib/eco/api/session/batch/job.rb', line 11

def sets
  @sets
end

#statusEco::API::Session::Batch::Status (readonly)

if launched: the status of the batch

Returns:



11
12
13
# File 'lib/eco/api/session/batch/job.rb', line 11

def status
  @status
end

#typeSymbol (readonly)

a valid batch operation

Returns:

  • (Symbol)

    the current value of type



11
12
13
# File 'lib/eco/api/session/batch/job.rb', line 11

def type
  @type
end

#usecaseEco::API::UseCases::UseCase? (readonly)

when provided: usecase that generated this batch job

Returns:



11
12
13
# File 'lib/eco/api/session/batch/job.rb', line 11

def usecase
  @usecase
end

Class Method Details

.valid_sets?(value) ⇒ Boolean

Returns:

  • (Boolean)


22
23
24
25
# File 'lib/eco/api/session/batch/job.rb', line 22

def valid_sets?(value)
  sts = [value].flatten
  sts.all? { |s| sets.include?(s) }
end

.valid_type?(value) ⇒ Boolean

Returns:

  • (Boolean)


18
19
20
# File 'lib/eco/api/session/batch/job.rb', line 18

def valid_type?(value)
  types.include?(value)
end

Instance Method Details

#add(entry, unique: true) {|person| ... } ⇒ Eco::API::Session::Batch::Job

Adds an entry(ies) to the job queue.

Parameters:

  • entry (Ecoportal::API::V1::Person, Enumberable<Person>)

    the person(s) we want to update, carrying the changes to be done.

  • unique (Boolean) (defaults to: true)

    specifies if repeated entries should be avoided in the queue.

Yields:

  • (person)

    callback before launching the batch job request against the server.

Yield Parameters:

  • person (Person)

    current person object that that should be treated by the callback before launching the batch.

Returns:



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/eco/api/session/batch/job.rb', line 95

def add(entry, unique: true, &block)
  case entry
  when Enumerable
    entry.each {|e| add(e, unique: unique, &block)}
  else
    unless !entry
      unless unique && @queue_hash.key?(entry)
        @queue_hash[entry] = true
        @queue.push(entry)
        @callbacks[entry]  = Proc.new if block_given?
      end
    end
  end
  self
end

#dup(name = "ad-hoc:job-from:#{self.name}", usecase: self.usecase) ⇒ Eco::API::Session::Batch::Job

Note:
  • this job will not be linked to the Batch::Jobs model of the current session
  • mostly used for error_handlers

Creates an empty Batch::Job with same behaviour as the current one



65
66
67
# File 'lib/eco/api/session/batch/job.rb', line 65

def dup(name = "ad-hoc:job-from:#{self.name}", usecase: self.usecase)
  self.class.new(enviro, name: name, type: type, sets: sets, usecase: usecase)
end

#error_handler?Boolean

Returns true if the current batch job is a result of an error_handler.

Returns:

  • (Boolean)

    true if the current batch job is a result of an error_handler



75
76
77
# File 'lib/eco/api/session/batch/job.rb', line 75

def error_handler?
  usecase? && usecase.is_a?(Eco::API::Error::Handler)
end

#errors?Boolean

Returns true if there were Server errors, false otherwise.

Returns:

  • (Boolean)

    true if there were Server errors, false otherwise

See Also:



131
132
133
# File 'lib/eco/api/session/batch/job.rb', line 131

def errors?
  status && status.errors?
end

#launch(simulate: false) ⇒ Eco::API::Session::Batch::Status

Processes the queue and, unless simulate is true, launches against 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 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 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 (see 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 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


165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/eco/api/session/batch/job.rb', line 165

def launch(simulate: false)
  pqueue    = processed_queue
  @requests = as_update(pqueue)
  pre_checks(requests, simulate: simulate)

  if simulate
    if options.dig(:requests, :backup)
      req_backup = as_update(pqueue, add_feedback: false)
      backup_update(req_backup, simulate: simulate)
    end
  else
    if pqueue.length > 0
      req_backup = as_update(pqueue, add_feedback: false)
      backup_update(req_backup)
      logger.debug("Job ('#{name}':#{type}): going to launch batch against #{pqueue.count} entries")
      session.batch.launch(pqueue, method: type).tap do |job_status|
        @status     = job_status
        status.root = self
        status.errors.print
      end
    end
  end

  unless requests.empty? || !simulate
    logger.info("--- simulate mode (dry-run) --  job '#{name}' -- this would have launched #{type.to_s.upcase}")
  end

  post_launch(queue: pqueue, simulate: simulate)
  @pending = false
  return status
end

#optionsHash

Returns options the root usecase is run with.

Returns:

  • (Hash)

    options the root usecase is run with



85
86
87
# File 'lib/eco/api/session/batch/job.rb', line 85

def options
  usecase?? usecase.options : {}
end

#pending?Boolean

Returns has been this batch job launched?.

Returns:

  • (Boolean)

    has been this batch job launched?



112
113
114
# File 'lib/eco/api/session/batch/job.rb', line 112

def pending?
  @pending
end

#people(input = @queue) ⇒ Eco::API::Organization::People

Note:

if input is not provided, it will use queue

Helper/shortcut to obtain a people object out of input



138
139
140
# File 'lib/eco/api/session/batch/job.rb', line 138

def people(input = @queue)
  Eco::API::Organization::People.new(input)
end

#request_stats(requests = nil) ⇒ Object



125
126
127
# File 'lib/eco/api/session/batch/job.rb', line 125

def request_stats(requests = nil)
  feedback.request_stats(requests || self.requests)
end

#requestsEnumbrable<Hash>

Note:

it requires launch to be firstly invoked

Returns the last requests that the queue will generate.

Returns:

  • (Enumbrable<Hash>)

    the last requests that the queue will generate

Raises:

  • (Exception)

    if 'launch' has not firstly invoked



119
120
121
122
# File 'lib/eco/api/session/batch/job.rb', line 119

def requests
  raise "Method missuse. Firstly 'launch' should be invoked" unless instance_variable_defined?(:@requests)
  @requests
end

#resetObject



52
53
54
55
56
57
58
# File 'lib/eco/api/session/batch/job.rb', line 52

def reset
  @queue      = []
  @queue_hash = {}
  @callbacks  = {}
  @pending    = true
  @status     = nil
end

#subjobsEco::API::Session::Batch::Jobs

Returns group of subjobs of this Batch::Job.

Returns:



70
71
72
# File 'lib/eco/api/session/batch/job.rb', line 70

def subjobs
  @subjobs ||= Eco::API::Session::Batch::Jobs.new(enviro, name: "childs-of:#{self.name}")
end

#summaryString

Note:

if launch was not invoked, it specifies so

Provides a text summary of the current status including:

  1. stats of the changes introduced by the job in the different parts of the person model
  2. if the job is compliant with the batch policy
  3. error messages in case they were errors from the server

Returns:

  • (String)

    the summary



203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
# File 'lib/eco/api/session/batch/job.rb', line 203

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
      msg << subjobs_summary
    end
  end.join("\n")
end

#usecase?Boolean

Returns was this batch job generated by a usecase? (Eco::API::UseCases::UseCase).

Returns:

  • (Boolean)

    was this batch job generated by a usecase? (Eco::API::UseCases::UseCase)



80
81
82
# File 'lib/eco/api/session/batch/job.rb', line 80

def usecase?
  !!usecase
end