postjob 0.5.5 → 0.5.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +5 -5
  2. data/lib/postjob/cli/cron.rb +16 -0
  3. data/lib/postjob/cli/enqueue.rb +14 -0
  4. data/lib/postjob/cli/job.rb +15 -19
  5. data/lib/postjob/cli/ps.rb +8 -2
  6. data/lib/postjob/host.rb +41 -0
  7. data/lib/postjob/job.rb +23 -23
  8. data/lib/postjob/migrations/006_enqueue.sql +48 -4
  9. data/lib/postjob/migrations/006a_processing.sql +5 -2
  10. data/lib/postjob/migrations/007_job_results.sql +6 -5
  11. data/lib/postjob/migrations/008a_childjobs.sql +33 -38
  12. data/lib/postjob/migrations/010_settings.sql +1 -1
  13. data/lib/postjob/migrations/{008_checkout_runnable.sql → 013a_checkout_runnable.sql} +11 -7
  14. data/lib/postjob/migrations/017_zombie_check.sql +11 -6
  15. data/lib/postjob/migrations/021_cron_jobs.sql +65 -0
  16. data/lib/postjob/migrations/023_sticky_jobs.sql +16 -0
  17. data/lib/postjob/migrations.rb +3 -1
  18. data/lib/postjob/queue.rb +23 -4
  19. data/lib/postjob/record.rb +4 -10
  20. data/lib/postjob/registry.rb +117 -20
  21. data/lib/postjob/runner.rb +169 -166
  22. data/lib/postjob/worker_session.rb +9 -25
  23. data/lib/postjob/workflow.rb +26 -50
  24. data/lib/postjob.rb +97 -23
  25. data/lib/tools/heartbeat.rb +2 -2
  26. data/lib/tools/history.rb +1 -1
  27. data/spec/postjob/enqueue_spec.rb +3 -0
  28. data/spec/postjob/events/heartbeat_event_spec.rb +5 -67
  29. data/spec/postjob/events/zombie_event_spec.rb +61 -0
  30. data/spec/postjob/worker_session_spec.rb +1 -24
  31. data/spec/spec_helper.rb +1 -1
  32. data/spec/support/configure_active_record.rb +7 -16
  33. data/spec/support/configure_database.rb +11 -0
  34. data/spec/support/configure_simple_sql.rb +0 -16
  35. metadata +10 -5
  36. data/lib/tools/atomic_store.rb +0 -17
data/lib/postjob/queue.rb CHANGED
@@ -2,10 +2,11 @@
2
2
  # rubocop:disable Metrics/MethodLength
3
3
  # rubocop:disable Metrics/ParameterLists
4
4
  # rubocop:disable Metrics/LineLength
5
+ # rubocop:disable Metrics/ModuleLength
5
6
 
6
7
  require "securerandom"
7
8
 
8
- # The Postjob::Queue manages enqueueing and fetching jobs from a job queue.
9
+ # The Postjob::Queue module manages enqueueing and fetching jobs from a job queue.
9
10
  module Postjob::Queue
10
11
  extend self
11
12
 
@@ -20,7 +21,7 @@ require_relative "queue/associations"
20
21
  require_relative "queue/settings"
21
22
 
22
23
  module Postjob::Queue
23
- Job = ::Postjob::Job
24
+ Job = ::Postjob::Job # :nodoc:
24
25
 
25
26
  # enqueues a new job with the given arguments
26
27
  #
@@ -41,7 +42,8 @@ module Postjob::Queue
41
42
  parent_id: [Integer, nil],
42
43
  tags: [Hash, nil],
43
44
  timeout: [Numeric, nil],
44
- max_attempts: [Integer, nil]
45
+ max_attempts: [Integer, nil],
46
+ sticky: [true, false, nil]
45
47
  }
46
48
 
47
49
  workflow, workflow_method = parse_workflow(workflow)
@@ -51,7 +53,7 @@ module Postjob::Queue
51
53
  # a) a limitation in Simple::SQL which would not be able to unpack a
52
54
  # "SELECT function()" usefully when the return value is a record;
53
55
  # b) and/or my inability to write better SQL functions;
54
- SQL.ask "SELECT * FROM #{SCHEMA_NAME}.enqueue($1::uuid, $2, $3, $4, $5, $6, $7, $8, $9, $10)",
56
+ SQL.ask "SELECT * FROM #{SCHEMA_NAME}.enqueue($1::uuid, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)",
55
57
  worker_session_id,
56
58
  options[:queue],
57
59
  workflow,
@@ -62,9 +64,26 @@ module Postjob::Queue
62
64
  Encoder.encode(options[:tags]),
63
65
  options[:max_attempts],
64
66
  options[:timeout],
67
+ options[:cron_interval],
68
+ options[:sticky],
65
69
  into: Job
66
70
  end
67
71
 
72
+ # Disable cron'ness for workflow + args combination
73
+ def disable_cron_jobs(workflow, args)
74
+ sql = <<~SQL
75
+ UPDATE postjob.postjobs
76
+ SET cron_interval = NULL
77
+ WHERE cron_interval IS NOT NULL
78
+ AND workflow=$1
79
+ AND args=$2
80
+ AND parent_id IS NULL
81
+ AND status NOT IN ('ok', 'failed', 'timeout')
82
+ SQL
83
+
84
+ Simple::SQL.ask sql, workflow, Encoder.encode(args)
85
+ end
86
+
68
87
  def set_job_result(worker_session_id, job, value, version:)
69
88
  value = Encoder.encode([value]) unless value.nil?
70
89
  SQL.ask "SELECT #{SCHEMA_NAME}.set_job_result($1::uuid, $2, $3, $4)", worker_session_id, job.id, value, version
@@ -1,17 +1,11 @@
1
- # rubocop:disable Style/EvalWithLocation
2
- # rubocop:disable Security/Eval
3
-
4
1
  #
5
2
  # A job class in-memory representation.
6
3
  #
7
- class Postjob::Record < Hash
4
+ class Postjob::Record < Hash # :nodoc:
8
5
  def initialize(hsh)
9
6
  replace hsh.dup
10
- end
11
-
12
- def self.attribute(sym)
13
- eval <<~RUBY
14
- define_method(:#{sym}) { self[:#{sym}] }
15
- RUBY
7
+ each do |key, value|
8
+ instance_variable_set "@#{key}", value
9
+ end
16
10
  end
17
11
  end
@@ -1,37 +1,134 @@
1
1
  # The registry holds a list of all available workflows
2
- module Postjob::Registry
3
- extend self
2
+ class Postjob::Registry
3
+ def self.instance
4
+ @instance ||= new
5
+ end
4
6
 
5
- def workflows
6
- instance.values.uniq
7
+ # Used for tests
8
+ def self.reset! # :nodoc:
9
+ @instance = nil
7
10
  end
8
11
 
9
- def workflows_with_versions
10
- @workflows_with_versions ||= []
12
+ def self.workflows
13
+ instance.workflows
11
14
  end
12
15
 
13
- # Used for tests
14
- def reset! # :nodoc:
15
- @instance = @workflows_with_versions = nil
16
+ def self.workflow_names
17
+ instance.workflows.keys.map(&:first).uniq
16
18
  end
17
19
 
18
- def register(workflow, _options = {})
19
- instance[[workflow.name, ""]] = workflow
20
- instance[[workflow.name, workflow.workflow_version]] = workflow
20
+ def self.runnable_workflows_with_versions
21
+ workflows
22
+ .select { |_, spec| spec.runnable? }
23
+ .inject([]) do |ary, (name_and_version, _spec)|
24
+ name, version = *name_and_version
25
+ ary << name << "#{name}#{version}"
26
+ end
27
+ end
21
28
 
22
- workflows_with_versions << workflow.name << "#{workflow.name}#{workflow.workflow_version}"
29
+ def self.workflows_with_versions
30
+ instance.workflows_with_versions
23
31
  end
24
32
 
25
- def lookup!(name:, version:)
26
- expect! name => String
27
- expect! version => String
33
+ def self.register(workflow, options = {})
34
+ instance.register(workflow, options)
35
+ end
36
+
37
+ class WorkflowSpec
38
+ class Options
39
+ DEFAULTS = {
40
+ version: "0.0",
41
+ max_attempts: 5,
42
+ timeout: 15 * 60,
43
+ sticky: false,
44
+ cron_interval: nil,
45
+ queue: "q"
46
+ }
47
+
48
+ attr_reader :version
49
+ attr_reader :max_attempts
50
+ attr_reader :timeout
51
+ attr_reader :sticky
52
+ attr_reader :cron_interval
53
+ attr_reader :queue
54
+
55
+ def initialize(options)
56
+ expect! options => {
57
+ version: [ nil, /^\d+(\.\d+)*/ ],
58
+ max_attempts: [ nil, Integer ],
59
+ timeout: [ nil, Integer ],
60
+ sticky: [ nil, true, false ],
61
+ cron_interval: [ nil, Integer ],
62
+ queue: [ nil, String ]
63
+ }
64
+
65
+ options = DEFAULTS.merge(options)
66
+
67
+ @version = options[:version]
68
+ @max_attempts = options[:max_attempts]
69
+ @timeout = options[:timeout]
70
+ @sticky = options[:sticky]
71
+ @cron_interval = options[:cron_interval]
72
+ @queue = options[:queue]
73
+ end
74
+ end
75
+
76
+ attr_reader :workflow
77
+ attr_reader :options
78
+
79
+ def runnable?
80
+ workflow.is_a?(Module)
81
+ end
28
82
 
29
- instance.fetch([name, version])
83
+ def name
84
+ case workflow
85
+ when Module then workflow.name
86
+ when String then workflow
87
+ end
88
+ end
89
+
90
+ def initialize(workflow, options)
91
+ expect! workflow => [ Module, String ]
92
+ @workflow = workflow
93
+ @options = Options.new(options)
94
+ end
95
+ end
96
+
97
+ # looks up a specific version of a specific workflow. Returns a WorkflowSpec
98
+ # object.
99
+ def self.lookup!(name:, version:)
100
+ instance.lookup! name: name, version: version
101
+ end
102
+
103
+ def self.[](name)
104
+ lookup! name: name, version: ""
105
+ rescue KeyError
106
+ nil
107
+ end
108
+
109
+ attr_reader :workflows
110
+ attr_reader :workflows_with_versions
111
+
112
+ def initialize
113
+ @workflows = {}
114
+ @workflows_with_versions = []
30
115
  end
31
116
 
32
- private
117
+ def register(workflow, options)
118
+ spec = WorkflowSpec.new(workflow, options)
119
+
120
+ @workflows_with_versions << spec.name << "#{spec.name}#{spec.options.version}"
121
+
122
+ @workflows[[spec.name, ""]] = spec
123
+ @workflows[[spec.name, spec.options.version]] = spec
124
+ end
125
+
126
+ # looks up a specific version of a specific workflow. Returns the workflow
127
+ # module itself
128
+ def lookup!(name:, version:)
129
+ expect! name => String
130
+ expect! version => String
33
131
 
34
- def instance
35
- @instance ||= {}
132
+ @workflows.fetch([name, version])
36
133
  end
37
134
  end
@@ -3,194 +3,197 @@
3
3
  # rubocop:disable Lint/RescueException
4
4
  # rubocop:disable Metrics/MethodLength
5
5
 
6
+ # Base implementations for Runners
7
+ #
8
+ # This module contains methods for runners.
6
9
  module Postjob::Runner
7
- extend self
10
+ class << self
11
+ extend Forwardable
12
+ delegate [:logger] => Postjob
13
+
14
+ Job = Postjob::Job
15
+
16
+ # returns the job that is currently running.
17
+ #
18
+ # This value is set by +process_job+ (via +with_current_job+), and
19
+ # currently only used from <tt>Postjob::Runner.async</tt>
20
+ def current_job
21
+ Thread.current[:current_job]
22
+ end
8
23
 
9
- extend Forwardable
10
- delegate [:logger] => Postjob
24
+ private
11
25
 
12
- Job = Postjob::Job
26
+ def with_current_job(job)
27
+ expect! current_job => nil
28
+ Thread.current[:current_job] = job
29
+ yield
30
+ ensure
31
+ Thread.current[:current_job] = nil
32
+ end
13
33
 
14
- # returns the job that is currently running.
15
- #
16
- # This value is set by +process_job+ (via +with_current_job+), and
17
- # currently only used from <tt>Postjob::Runner.async</tt>
18
- def current_job
19
- Thread.current[:current_job]
20
- end
34
+ public
35
+
36
+ # returns a subjob within the current job, for a +runner+
37
+ # description and +args+.
38
+ def async(workflow, *args, timeout: nil, max_attempts:)
39
+ worker_session_id = Postjob.current_worker_session.id
40
+
41
+ # if the workflow is a symbol, then we change it into "__manual__"
42
+ # - there should never be a workflow with that name - or into
43
+ # "CurrentWorkshop.#{workflow}", denoting the \a workflow method of the
44
+ # current workflow.
45
+ case workflow
46
+ when :manual then workflow = "__manual__"
47
+ when Symbol then workflow = "#{current_job.workflow}.#{workflow}"
48
+ when Module then workflow = workflow.name
49
+ when String then :nop
50
+ else
51
+ raise ArgumentError, "Unsupported workflow spec #{workflow.inspect}. Did you run await(fun(a, b)) instead of await(:fun, a, b)"
52
+ end
21
53
 
22
- private
54
+ ::Postjob::Queue.find_or_create_childjob(worker_session_id, self.current_job, workflow, args,
55
+ timeout: timeout,
56
+ max_attempts: max_attempts)
57
+ end
23
58
 
24
- def with_current_job(job)
25
- expect! current_job => nil
26
- Thread.current[:current_job] = job
27
- yield
28
- ensure
29
- Thread.current[:current_job] = nil
30
- end
59
+ # tries to resolve a job.
60
+ def await(job, *args, timeout: nil, max_attempts: nil)
61
+ case job
62
+ when :all
63
+ unresolved_childjobs = Postjob::Queue.unresolved_childjobs(current_job)
64
+ if unresolved_childjobs > 0
65
+ Postjob.logger.debug "await :all: Found #{unresolved_childjobs} unresolved childjobs"
66
+ throw :pending, :pending
67
+ else
68
+ childjobs = Postjob::Queue.childjobs(current_job)
69
+ childjobs.each(&:resolve).count
70
+ end
71
+ when Job
72
+ expect! args == []
73
+ expect! timeout => nil, max_attempts => nil
74
+ r = job.resolve
75
+ throw :pending, :pending if r == :pending
76
+ r
77
+ else
78
+ job = async(job, *args, timeout: timeout, max_attempts: max_attempts)
79
+ await(job)
80
+ end
81
+ end
31
82
 
32
- public
33
-
34
- # returns a subjob within the current job, for a +runner+
35
- # description and +args+.
36
- def async(workflow, *args, timeout: nil, max_attempts:)
37
- worker_session_id = Postjob.current_worker_session.id
38
-
39
- # if the workflow is a symbol, then we change it into "__manual__"
40
- # - there should never be a workflow with that name - or into
41
- # "CurrentWorkshop.#{workflow}", denoting the \a workflow method of the
42
- # current workflow.
43
- case workflow
44
- when :manual then workflow = "__manual__"
45
- when Symbol then workflow = "#{current_job.workflow}.#{workflow}"
46
- when Module then workflow = workflow.name
47
- when String then :nop
48
- else
49
- raise ArgumentError, "Unsupported workflow spec #{workflow.inspect}. Did you run await(fun(a, b)) instead of await(:fun, a, b)"
83
+ STATUSES = [ :sleep, :ok, :err, :failed ]
84
+
85
+ #
86
+ # runs a specific job
87
+ #
88
+ # returns a tuple [status, value], which follows the following pattern:
89
+ #
90
+ # - <tt>[ <runner-version>, :ok, value, nil ]</tt>: job completed successfully
91
+ # - <tt>[ <runner-version>, :sleep, nil, nil ]</tt>: job has to wait on a child job
92
+ # - <tt>[ <runner-version>, :err, <err>, nil ]</tt>: job errored with a recoverable error
93
+ # - <tt>[ <runner-version>, :failed, <err>, <shutdown> ]</tt>: job failed with a non-recoverable error
94
+ #
95
+ # <err> is a tuple [ error-class-name, error-message, stacktrace ].
96
+ # <shutdown> is either nil or :shutdown
97
+ #
98
+ def process_job(job)
99
+ expect! job => Job
100
+
101
+ spec = Postjob::Registry.lookup!(name: job.workflow, version: job.workflow_version)
102
+ expect! spec.runnable?
103
+
104
+ with_current_job(job) do
105
+ status, value, shutdown = invoke_workflow spec.workflow, job
106
+ log_result! job, status, value
107
+ # If the status is ok the job finished processing. In that case
108
+ # we'll wait for all child jobs to finish.
109
+ # if status == :ok
110
+ # await :all
111
+ # end
112
+ [ spec.options.version, status, value, shutdown ]
113
+ end
50
114
  end
51
115
 
52
- ::Postjob::Queue.find_or_create_childjob(worker_session_id, self.current_job, workflow, args,
53
- timeout: timeout,
54
- max_attempts: max_attempts)
55
- end
116
+ private
117
+
118
+ # runs a job. Returns a [ status, value, shutdown ] tuple.
119
+ #
120
+ # The shutdown value is used by a worker in run mode (i.e. process
121
+ # indefinetively) to determine whether or not it should cancel
122
+ # processing. It is usually nil; but if the worker received a
123
+ # SIGINT it will be :shutdown instead.
124
+ #
125
+ # We are catching SIGINT to allow the job status to be updated.
126
+ def invoke_workflow(workflow, job)
127
+ value = catch(:pending) {
128
+ expect! job.args => [Array, nil]
129
+
130
+ workflow_method = job.workflow_method
131
+ args = job.args
132
+
133
+ insp_args = args.map(&:inspect).join(", ")
134
+ logger.info "Running Postjob##{job.id}: #{job.workflow}.#{workflow_method}(#{insp_args})"
56
135
 
57
- # tries to resolve a job.
58
- def await(job, *args, timeout: nil, max_attempts: nil)
59
- case job
60
- when :all
61
- unresolved_childjobs = Postjob::Queue.unresolved_childjobs(current_job)
62
- if unresolved_childjobs > 0
63
- Postjob.logger.debug "await :all: Found #{unresolved_childjobs} unresolved childjobs"
64
- throw :pending, :pending
136
+ workflow.public_send workflow_method, *args
137
+ }
138
+
139
+ if value == :pending
140
+ [ :pending, nil, nil ]
65
141
  else
66
- childjobs = Postjob::Queue.childjobs(current_job)
67
- childjobs.each(&:resolve).count
142
+ # Check that we can encode the value. If we can't the job returned something invalid
143
+ # i.e. something we cannot encode as JSON. This will raise a Postjob::Queue::Encoder::Error.
144
+ #
145
+ # Usually this points to a non-UTF8 string.
146
+ # This is a fix for https://github.com/mediapeers/postjob/issues/35
147
+ Postjob::Queue::Encoder.check_encodable!([value])
148
+ [ :ok, value, nil ]
68
149
  end
69
- when Job
70
- expect! args == []
71
- expect! timeout => nil, max_attempts => nil
72
- r = job.resolve
73
- throw :pending, :pending if r == :pending
74
- r
75
- else
76
- job = async(job, *args, timeout: timeout, max_attempts: max_attempts)
77
- await(job)
78
- end
79
- end
80
-
81
- STATUSES = [ :sleep, :ok, :err, :failed ]
82
-
83
- #
84
- # runs a specific job
85
- #
86
- # returns a tuple [status, value], which follows the following pattern:
87
- #
88
- # - <tt>[ <runner-version>, :ok, value, nil ]</tt>: job completed successfully
89
- # - <tt>[ <runner-version>, :sleep, nil, nil ]</tt>: job has to wait on a child job
90
- # - <tt>[ <runner-version>, :err, <err>, nil ]</tt>: job errored with a recoverable error
91
- # - <tt>[ <runner-version>, :failed, <err>, <shutdown> ]</tt>: job failed
92
- # with a non-recoverable error
93
- #
94
- # <err> is a tuple [ error-class-name, error-message, stacktrace ].
95
- # <shutdown> is either nil or :shutdown
96
- #
97
- def process_job(job)
98
- expect! job => Job
99
-
100
- workflow = Postjob::Registry.lookup!(name: job.workflow, version: job.workflow_version)
101
-
102
- with_current_job(job) do
103
- status, value, shutdown = invoke_workflow workflow, job
104
- log_result! job, status, value
105
- # If the status is ok the job finished processing. In that case
106
- # we'll wait for all child jobs to finish.
107
- # if status == :ok
108
- # await :all
109
- # end
110
- [ workflow.workflow_version, status, value, shutdown ]
150
+ rescue ArgumentError, LocalJumpError, NameError, RegexpError, ScriptError, TypeError
151
+ Postjob.logger.error "#{$!}, from\n\t#{$!.backtrace[0, 10].join("\n\t")}"
152
+ return_exception :failed, $!
153
+ rescue Postjob::Error::Nonrecoverable
154
+ return_exception :failed, $!
155
+ rescue Exception
156
+ return_exception :err, $!
111
157
  end
112
- end
113
158
 
114
- private
115
-
116
- # runs a job. Returns a [ status, value, shutdown ] tuple.
117
- #
118
- # The shutdown value is used by a worker in run mode (i.e. process
119
- # indefinetively) to determine whether or not it should cancel
120
- # processing. It is usually nil; but if the worker received a
121
- # SIGINT it will be :shutdown instead.
122
- #
123
- # We are catching SIGINT to allow the job status to be updated.
124
- def invoke_workflow(workflow, job)
125
- value = catch(:pending) {
126
- expect! job.args => [Array, nil]
127
-
128
- workflow_method = job.workflow_method
129
- args = job.args
130
-
131
- insp_args = args.map(&:inspect).join(", ")
132
- logger.info "Running Postjob##{job.id}: #{job.workflow}.#{workflow_method}(#{insp_args})"
133
-
134
- workflow.public_send workflow_method, *args
135
- }
136
-
137
- if value == :pending
138
- [ :pending, nil, nil ]
139
- else
140
- # Check that we can encode the value. If we can't the job returned something invalid
141
- # i.e. something we cannot encode as JSON. This will raise a Postjob::Queue::Encoder::Error.
142
- #
143
- # Usually this points to a non-UTF8 string.
144
- # This is a fix for https://github.com/mediapeers/postjob/issues/35
145
- Postjob::Queue::Encoder.check_encodable!([value])
146
- [ :ok, value, nil ]
159
+ def should_shutdown?(exception)
160
+ exception.is_a?(Interrupt)
147
161
  end
148
- rescue ArgumentError, LocalJumpError, NameError, RegexpError, ScriptError, TypeError
149
- Postjob.logger.error "#{$!}, from\n\t#{$!.backtrace[0, 10].join("\n\t")}"
150
- return_exception :failed, $!
151
- rescue Postjob::Error::Nonrecoverable
152
- return_exception :failed, $!
153
- rescue Exception
154
- return_exception :err, $!
155
- end
156
162
 
157
- def should_shutdown?(exception)
158
- exception.is_a?(Interrupt)
159
- end
163
+ def return_exception(state, exception)
164
+ # get and shorten backtrace.
165
+ error_backtrace = exception.backtrace[0, 10]
160
166
 
161
- def return_exception(state, exception)
162
- # get and shorten backtrace.
163
- error_backtrace = exception.backtrace[0, 10]
167
+ curdir = "#{Dir.getwd}/"
168
+ error_backtrace = error_backtrace.map { |path| path.start_with?(curdir) ? path[curdir.length..-1] : path }
164
169
 
165
- curdir = "#{Dir.getwd}/"
166
- error_backtrace = error_backtrace.map { |path| path.start_with?(curdir) ? path[curdir.length..-1] : path }
170
+ shutdown = should_shutdown?(exception) ? :shutdown : nil
171
+ [ state, [exception.class.name, exception.message, error_backtrace], shutdown ]
172
+ end
167
173
 
168
- shutdown = should_shutdown?(exception) ? :shutdown : nil
169
- [ state, [exception.class.name, exception.message, error_backtrace], shutdown ]
170
- end
174
+ def log_result!(job, status, value)
175
+ case status
176
+ when :err
177
+ severity = job.parent_id ? :warn : :error
178
+ logger.send severity, error_message(job, status, value)
179
+ when :failed
180
+ logger.error error_message(job, status, value)
181
+ when :ok
182
+ runtime = Time.now.utc - job.created_at
183
+ runtime = "%.03f secs" % runtime
184
+ severity = job.parent_id ? :info : :warn
185
+ msg = "#{job} successful w/result #{value.inspect}: #{runtime}"
186
+ logger.send severity, msg
187
+ end
188
+ end
171
189
 
172
- def log_result!(job, status, value)
173
- case status
174
- when :err
175
- severity = job.parent_id ? :warn : :error
176
- logger.send severity, error_message(job, status, value)
177
- when :failed
178
- logger.error error_message(job, status, value)
179
- when :ok
190
+ def error_message(job, status, value)
180
191
  runtime = Time.now.utc - job.created_at
181
192
  runtime = "%.03f secs" % runtime
182
- severity = job.parent_id ? :info : :warn
183
- msg = "#{job} successful w/result #{value.inspect}: #{runtime}"
184
- logger.send severity, msg
185
- end
186
- end
187
-
188
- def error_message(job, status, value)
189
- runtime = Time.now.utc - job.created_at
190
- runtime = "%.03f secs" % runtime
191
- error_class, err_message, _error_backtrace = value
193
+ error_class, err_message, _error_backtrace = value
192
194
 
193
- "#{job} #{status} #{error_class} #{err_message.inspect}: #{runtime}"
194
- # + "\n backtrace information:\n #{error_backtrace.join("\n ")}"
195
+ "#{job} #{status} #{error_class} #{err_message.inspect}: #{runtime}"
196
+ # + "\n backtrace information:\n #{error_backtrace.join("\n ")}"
197
+ end
195
198
  end
196
199
  end
@@ -3,34 +3,18 @@
3
3
  require_relative "./record"
4
4
 
5
5
  require "tools/heartbeat"
6
- require "tools/atomic_store"
7
-
8
- class Postjob::Host < Postjob::Record
9
- def self.register(attributes = {})
10
- Postjob.logger.debug "registering host w/#{attributes.inspect}"
11
- ::Postjob::Queue.host_register(attributes)
12
- end
13
- end
14
6
 
15
7
  # A worker worker_session
16
8
  class Postjob::WorkerSession < Postjob::Record
17
- HOST_ID_PATH = ".postjob.host_id"
18
-
19
9
  class << self
20
10
  # Starts a worker session.
21
11
  def start!(workflows_with_versions)
22
- worker_session = nil
23
-
24
- AtomicStore.with(HOST_ID_PATH) do |host_id|
25
- host_id ||= ::Postjob::Host.register
26
- Postjob.logger.debug "Starting worker_session w/host_id #{host_id.inspect}"
27
- worker_session = ::Postjob::Queue.start_worker_session(workflows_with_versions, host_id: host_id)
28
- host_id
29
- end
12
+ host_id = ::Postjob.host_id
13
+ worker_session = ::Postjob::Queue.start_worker_session(workflows_with_versions, host_id: host_id)
30
14
 
31
15
  Postjob.logger.info "Starting worker_session #{worker_session.inspect}"
32
16
 
33
- start_heartbeat_monitor(worker_session.host_id)
17
+ start_heartbeat_monitor(host_id)
34
18
  worker_session
35
19
  end
36
20
 
@@ -58,12 +42,12 @@ class Postjob::WorkerSession < Postjob::Record
58
42
  end
59
43
  end
60
44
 
61
- attribute :id
62
- attribute :host_id
63
- attribute :client_socket
64
- attribute :workflows
65
- attribute :attributes
66
- attribute :created_at
45
+ attr_reader :id
46
+ attr_reader :host_id
47
+ attr_reader :client_socket
48
+ attr_reader :workflows
49
+ attr_reader :attributes
50
+ attr_reader :created_at
67
51
 
68
52
  def to_s
69
53
  "Session##{id}"