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, accept_update_with_no_id: false) ⇒ 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.

  • accept_update_with_no_id (Boolean) (defaults to: false)

    temporary contingency This parameter has been added due to a bug on server side. An external_id is still required.



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/eco/api/session/batch/job.rb', line 40

def initialize(e, name:, type:, sets:, usecase: nil, accept_update_with_no_id: false)
  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)
  @accept_update_with_no_id = accept_update_with_no_id
  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:



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/eco/api/session/batch/job.rb', line 99

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



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

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



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

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:



135
136
137
# File 'lib/eco/api/session/batch/job.rb', line 135

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


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
196
197
198
199
# File 'lib/eco/api/session/batch/job.rb', line 169

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



89
90
91
# File 'lib/eco/api/session/batch/job.rb', line 89

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

#pending?Boolean

Returns has been this batch job launched?.

Returns:

  • (Boolean)

    has been this batch job launched?



116
117
118
# File 'lib/eco/api/session/batch/job.rb', line 116

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



142
143
144
# File 'lib/eco/api/session/batch/job.rb', line 142

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

#request_stats(requests = nil) ⇒ Object



129
130
131
# File 'lib/eco/api/session/batch/job.rb', line 129

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



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

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

#resetObject



56
57
58
59
60
61
62
# File 'lib/eco/api/session/batch/job.rb', line 56

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:



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

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



207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
# File 'lib/eco/api/session/batch/job.rb', line 207

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)



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

def usecase?
  !!usecase
end