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



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

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 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| ... } ⇒ Void

Adds an entry(ies) to the job queue.

Parameters:

  • entry (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.

Returns:

  • (Void)


89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/eco/api/session/batch/job.rb', line 89

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
end

#dup(name = "ad-hoc:job-from:#{self.name}", usecase: nil) ⇒ 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



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

def dup(name = "ad-hoc:job-from:#{self.name}", usecase: nil)
  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



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

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:



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

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 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


163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'lib/eco/api/session/batch/job.rb', line 163

def launch(simulate: false)
  pqueue    = processed_queue
  @requests = pqueue.map {|e| as_update(e)}

  pre_checks(requests, simulate: simulate)

  unless simulate
    if pqueue.length > 0
      backup_update(requests)
      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?
    logger.info("--- simulate mode (dry-run) --  job '#{name}' -- this would have launched #{type.to_s.upcase}") if simulate
  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



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

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

#pending?Boolean

Returns has been this batch job launched?.

Returns:

  • (Boolean)

    has been this batch job launched?



110
111
112
# File 'lib/eco/api/session/batch/job.rb', line 110

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



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

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

#request_stats(requests = nil) ⇒ Object



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

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



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

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

#resetObject



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

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

#summaryString

Note:

if launch was not invoked, it specifies so

Provides a text summary of the current status

Returns:

  • (String)

    the summary



192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
# File 'lib/eco/api/session/batch/job.rb', line 192

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

#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)



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

def usecase?
  !!usecase
end