Class: Ecoportal::API::V1::Job::Awaiter

Inherits:
Object
  • Object
show all
Includes:
Common::Client::TimeOut
Defined in:
lib/ecoportal/api/v1/job/awaiter.rb

Constant Summary collapse

DELAY_STATUS_CHECK =
4
MIN_STATUS_CHECK =
2
TIMEOUT_APPROACH =

adaptative timeout

:conservative
TIMEOUT_FALLBACK =
:min

Constants included from Common::Client::TimeOut

Common::Client::TimeOut::MIN_SIZE, Common::Client::TimeOut::TIMEOUT_MARGIN

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(job, job_id:, total:) ⇒ Awaiter

Returns a new instance of Awaiter.



17
18
19
20
21
22
23
# File 'lib/ecoportal/api/v1/job/awaiter.rb', line 17

def initialize(job, job_id:, total:)
  @job     = job
  @job_id  = job_id
  @total   = total
  @checked = false
  self.timeout_approach = self.class::TIMEOUT_APPROACH
end

Instance Attribute Details

#jobObject (readonly)

Returns the value of attribute job.



14
15
16
# File 'lib/ecoportal/api/v1/job/awaiter.rb', line 14

def job
  @job
end

#job_idObject (readonly)

Returns the value of attribute job_id.



14
15
16
# File 'lib/ecoportal/api/v1/job/awaiter.rb', line 14

def job_id
  @job_id
end

#timeout_approachObject

Returns the value of attribute timeout_approach.



15
16
17
# File 'lib/ecoportal/api/v1/job/awaiter.rb', line 15

def timeout_approach
  @timeout_approach
end

#totalObject (readonly)

Returns the value of attribute total.



14
15
16
# File 'lib/ecoportal/api/v1/job/awaiter.rb', line 14

def total
  @total
end

Instance Method Details

#await_completion!Object

rubocop:disable Metrics/AbcSize



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/ecoportal/api/v1/job/awaiter.rb', line 32

def await_completion! # rubocop:disable Metrics/AbcSize

  max_timeout = timeout_for(total, approach: timeout_approach)

  # timeout library is evil. So we make poor-man timeout.

  # https://jvns.ca/blog/2015/11/27/why-rubys-timeout-is-dangerous-and-thread-dot-raise-is-terrifying/

  before = Time.now
  delay_status_check = nil

  loop do
    status  = job.status(job_id)
    waited  = Time.now - before

    adapted = waited
    adapted = waited - (delay_status_check / 2) if delay_status_check
    ratio   = throughput!(adapted, count: status.progress)

    break status if status.complete?(total)

    pending = status.pending(total)
    left    = max_timeout - waited

    timeout!(status, timeout: max_timeout) unless left.positive?

    delay_status_check = status_check_in(pending, timeout_in: left)

    msg  = " ... Awaiting #{delay_status_check} s. -- "
    msg << " TimeOut: #{left.round(2)} s. "
    msg << "(job '#{job_id}') "
    msg << "Done: #{status.progress} (est. #{ratio} rec/s) "
    msg << "     \r"

    print msg
    $stdout.flush

    sleep(delay_status_check)
  end
end

#new(**kargs) ⇒ Object

Allows to preserve the learned throughput



26
27
28
29
30
# File 'lib/ecoportal/api/v1/job/awaiter.rb', line 26

def new(**kargs)
  self.class.new(job, **kargs).tap do |out|
    out.throughput = throughput
  end
end