litestack 0.1.6 → 0.1.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 01c10017cec21bcabea357aecb8746779060718bb2e6b6e36f250c37d80656f1
4
- data.tar.gz: 863b319c7a658f2a19410c614035068f8a2dec72b189698a5a081f595ecf5853
3
+ metadata.gz: d08724a0b9293f55ebed24ba6d738b103795b69563a210c4454322fc382e174e
4
+ data.tar.gz: 01401bfca727b4ef9452a9efafba846c886845dd43c1d8f5f5ce84cee22ab61f
5
5
  SHA512:
6
- metadata.gz: 7bb0fd84ee582eddfe32e48b0373a7545cad8581217ba56d7ac6c984b60b137b86d5196e1bc37486b88d21c28bc5ff62da573a1ba6ce6b49d66ba744ddbcabc6
7
- data.tar.gz: 38da99eae6a37222a8689577900504ea1b131f0ec56f67531dff00f5ae4f4c62a29baca21ba2a102435cc334773f8ef4709a361dff6f28de988471eac0937e08
6
+ metadata.gz: 729320670e62261596eabbfd8f8d931117507317127e9fd9e5a796928e7031418455ca351dd2de815d4860edc2e688c0bbdb79560d3907cb3545deb75a1b4fae
7
+ data.tar.gz: d75cc4f23694c726a361b0bc474f561b8ffc4db074ef275839917d4c82461aca7a1c4a0b0e939cd749a7e7afbb58de86f3de254a6adadfc7f6d91ea9021218f3
data/BENCHMARKS.md CHANGED
@@ -67,7 +67,7 @@ For testing the cache we attempted to try writing and reading different payload
67
67
 
68
68
  ### Write
69
69
 
70
- |Payload Size (bytes)|Redis|litecahce|
70
+ |Payload Size (bytes)|Redis|litecache|
71
71
  |-:|-:|-:|
72
72
  |10|4.2K q/s|11.0K q/s|
73
73
  |100|4.7K q/s|11.6K q/s|
data/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.1.8] - 2022-03-08
4
+
5
+ - More code cleanups, more test coverage
6
+ - Retry support for jobs in Litejob
7
+ - Job storage and garbage collection for failed jobs
8
+ - Initial graceful shutdown support for Litejob (incomplete)
9
+ - More configuration options for Litejob
10
+
11
+ ## [0.1.7] - 2022-03-05
12
+
13
+ - Code cleanup, removal of references to older name
14
+ - Fix for the litedb rake tasks (thanks: netmute)
15
+ - More fixes for the new concurrency model
16
+ - Introduced a logger for the Litejobqueue (doesn't work with Polyphony, fix should come soon)
17
+
3
18
  ## [0.1.6] - 2022-03-03
4
19
 
5
20
  - Revamped the locking model, more robust, minimal performance hit
data/README.md CHANGED
@@ -1,9 +1,9 @@
1
1
  ![litestack](https://github.com/oldmoe/litestack/blob/master/assets/litestack_logo_teal_large.png?raw=true)
2
2
 
3
3
 
4
- litestack is a revolutionary gem for Ruby and Ruby on Rails that provides an all-in-one solution for web application development. It exploits the power and embeddedness of SQLite to include a full-fledged SQL database, a fast cache, a robust job queue, and a simple yet performant full-text search all in a single package.
4
+ litestack is a revolutionary gem for Ruby and Ruby on Rails that provides an all-in-one solution for web application development. It exploits the power and embeddedness of SQLite to include a full-fledged SQL database, a fast cache and a robust job queue all in a single package.
5
5
 
6
- Compared to conventional approaches that require separate servers and databases, LiteStack offers superior performance, efficiency, ease of use, and cost savings. Its embedded database and cache reduce memory and CPU usage, while its simple interface streamlines the development process. Overall, LiteStack sets a new standard for web application development and is an excellent choice for those who demand speed, efficiency, and simplicity.
6
+ Compared to conventional approaches that require separate servers and databases, Litestack offers superior performance, efficiency, ease of use, and cost savings. Its embedded database and cache reduce memory and CPU usage, while its simple interface streamlines the development process. Overall, LiteStack sets a new standard for web application development and is an excellent choice for those who demand speed, efficiency, and simplicity.
7
7
 
8
8
  You can read more about why litestack can be a good choice for your next web application **[here](WHYLITESTACK.md)**, you might also be interested in litestack **[benchmarks](BENCHMARKS.md)**.
9
9
 
@@ -83,7 +83,7 @@ adapter: litedb
83
83
  litedb offers integration with the Sequel database toolkit and can be configured as follows
84
84
 
85
85
  ```ruby
86
- DB = Sequel.conncet("litedb://path_to_db_file")
86
+ DB = Sequel.connect("litedb://path_to_db_file")
87
87
  ```
88
88
 
89
89
 
@@ -120,7 +120,7 @@ litejob is a fast and very efficient job queue processor for Ruby applications.
120
120
  require 'litestack'
121
121
  # define your job class
122
122
  class MyJob
123
- include ::litejob
123
+ include ::Litejob
124
124
 
125
125
  queue = :default
126
126
 
data/bench/bench.rb CHANGED
@@ -2,8 +2,8 @@ require 'sqlite3'
2
2
 
3
3
  def bench(msg, iterations=1000)
4
4
  GC.start
5
- GC.compact
6
- print "Starting #{iterations} iterations of #{msg} ... "
5
+ #GC.compact
6
+ STDERR.puts "Starting #{iterations} iterations of #{msg} ... "
7
7
  t1 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
8
8
  iterations.times do |i|
9
9
  yield i
@@ -12,7 +12,7 @@ def bench(msg, iterations=1000)
12
12
  time = ((t2 - t1)*1000).to_i.to_f / 1000 rescue 0
13
13
  ips = ((iterations/(t2-t1))*100).to_i.to_f / 100 rescue "infinity?"
14
14
  #{m: msg, t: time, ips: iteratinos/time, i: iterations}
15
- puts "finished in #{time} seconds (#{ips} ips)"
15
+ STDERR.puts " .. finished in #{time} seconds (#{ips} ips)"
16
16
  end
17
17
 
18
18
  @db = SQLite3::Database.new(":memory:") # sqlite database for fast random string generation
@@ -16,15 +16,18 @@ redis = Redis.new # default settings
16
16
 
17
17
  values = []
18
18
  keys = []
19
- count = 1000
19
+ count = 5
20
20
  count.times { keys << random_str(10) }
21
21
 
22
- [10, 100, 1000, 10000].each do |size|
22
+ [10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000].each do |size|
23
23
  count.times do
24
24
  values << random_str(size)
25
25
  end
26
26
 
27
27
  random_keys = keys.shuffle
28
+
29
+ GC.compact
30
+
28
31
  puts "Benchmarks for values of size #{size} bytes"
29
32
  puts "=========================================================="
30
33
  puts "== Writes =="
@@ -33,7 +36,7 @@ count.times { keys << random_str(10) }
33
36
  end
34
37
 
35
38
  bench("Redis writes", count) do |i|
36
- redis.set(keys[i], values[i])
39
+ #redis.set(keys[i], values[i])
37
40
  end
38
41
 
39
42
  puts "== Reads =="
@@ -42,11 +45,13 @@ count.times { keys << random_str(10) }
42
45
  end
43
46
 
44
47
  bench("Redis reads", count) do |i|
45
- redis.get(random_keys[i])
48
+ #redis.get(random_keys[i])
46
49
  end
47
50
  puts "=========================================================="
48
51
 
49
52
  values = []
53
+
54
+
50
55
  end
51
56
 
52
57
 
@@ -64,5 +69,5 @@ end
64
69
  cache.clear
65
70
  redis.flushdb
66
71
 
67
- sleep
72
+ #sleep
68
73
 
@@ -1,22 +1,14 @@
1
1
  require './bench'
2
- require 'async/scheduler'
3
-
4
- #ActiveJob::Base.logger = Logger.new(IO::NULL)
5
2
 
3
+ count = ARGV[0].to_i rescue 1000
4
+ env = ARGV[1] || "t"
5
+ delay = ARGV[2].to_f rescue 0
6
6
 
7
- Fiber.set_scheduler Async::Scheduler.new
8
7
 
9
- require_relative '../lib/active_job/queue_adapters/litejob_adapter'
10
-
11
- ActiveSupport::IsolatedExecutionState.isolation_level = :fiber
8
+ #ActiveJob::Base.logger = Logger.new(IO::NULL)
12
9
 
13
10
  require './rails_job.rb'
14
11
 
15
-
16
- puts Litesupport.environment
17
-
18
- count = 1000
19
-
20
12
  RailsJob.queue_adapter = :sidekiq
21
13
  t = Time.now.to_f
22
14
  puts "Make sure sidekiq is started with -c ./rails_job.rb"
@@ -26,13 +18,27 @@ end
26
18
 
27
19
  puts "Don't forget to check the sidekiq log for processing time conclusion"
28
20
 
21
+
22
+ # Litejob bench
23
+ ###############
24
+
25
+ if env == "a" # threaded
26
+ require 'async/scheduler'
27
+ Fiber.set_scheduler Async::Scheduler.new
28
+ ActiveSupport::IsolatedExecutionState.isolation_level = :fiber
29
+ end
30
+
31
+ require_relative '../lib/active_job/queue_adapters/litejob_adapter'
32
+ puts Litesupport.environment
33
+
29
34
  RailsJob.queue_adapter = :litejob
30
35
  t = Time.now.to_f
31
36
  bench("enqueuing litejobs", count) do
32
37
  RailsJob.perform_later(count, t)
33
38
  end
34
39
 
35
- Fiber.scheduler.run
36
-
40
+ if env == "a" # threaded
41
+ Fiber.scheduler.run
42
+ end
37
43
 
38
44
  sleep
@@ -1,29 +1,43 @@
1
- #require 'polyphony'
2
- require 'async/scheduler'
3
1
  require './bench'
4
2
 
5
- Fiber.set_scheduler Async::Scheduler.new
3
+ count = ARGV[0].to_i rescue 1000
4
+ env = ARGV[1] || "t"
5
+ delay = ARGV[2].to_f rescue 0
6
6
 
7
- count = 10000
7
+ # Sidekiq bench
8
+ ###############
8
9
  require './skjob.rb'
9
- require './uljob.rb'
10
-
11
- puts Litesupport.environment
12
10
 
13
- t = Time.now.to_f
11
+ t = Process.clock_gettime(Process::CLOCK_MONOTONIC)
14
12
  puts "make sure sidekiq is started with skjob.rb as the job"
15
13
  bench("enqueuing sidekiq jobs", count) do |i|
16
- SidekiqJob.perform_async(count, t)
14
+ SidekiqJob.perform_async(count, t, delay)
17
15
  end
18
16
 
19
17
  puts "Don't forget to check the sidekiq log for processing time conclusion"
20
18
 
21
- t = Time.now.to_f
19
+ # Litejob bench
20
+ ###############
21
+
22
+ if env == "t" # threaded
23
+ # do nothing
24
+ elsif env == "a" # async
25
+ require 'async/scheduler'
26
+ Fiber.set_scheduler Async::Scheduler.new
27
+ end
28
+
29
+ require './uljob.rb'
30
+
31
+ STDERR.puts "litejob started in #{Litesupport.environment} environmnet"
32
+
33
+ t = Process.clock_gettime(Process::CLOCK_MONOTONIC)
22
34
  bench("enqueuing litejobs", count) do |i|
23
- MyJob.perform_async(count, t)
35
+ MyJob.perform_async(count, t, delay)
24
36
  end
25
37
 
26
- Fiber.scheduler.run
38
+ puts "Please wait for the benchmark to finish .."
39
+
40
+ Fiber.scheduler.run if env == "a"
27
41
 
28
42
  sleep
29
43
 
data/bench/skjob.rb CHANGED
@@ -3,11 +3,13 @@ require 'sidekiq'
3
3
  class SidekiqJob
4
4
  include Sidekiq::Job
5
5
  @@count = 0
6
- def perform(count, time)
7
- sleep 0.1
6
+ def perform(count, time, sleep_interval = nil)
7
+ sleep sleep_interval if sleep_interval
8
8
  @@count += 1
9
9
  if @@count == count
10
- puts "finished in #{Time.now.to_f - time} seconds (#{count / (Time.now.to_f - time)} jps)"
10
+ now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
11
+ STDERR.puts "Sidekiq finished in #{now - time} seconds (#{count / (now - time)} jps)"
12
+ @@count = 0
11
13
  end
12
14
  end
13
15
  end
data/bench/uljob.rb CHANGED
@@ -4,12 +4,13 @@ require '../lib/litestack'
4
4
  class MyJob
5
5
  include Litejob
6
6
  @@count = 0
7
- # self.queue = :normal
8
- def perform(count, time)
9
- #sleep 0.1
7
+ #self.queue = :default
8
+ def perform(count, time, sleep_interval = nil)
9
+ sleep sleep_interval if sleep_interval
10
10
  @@count += 1
11
11
  if @@count == count
12
- puts "UL finished in #{Time.now.to_f - time} seconds (#{count / (Time.now.to_f - time)} jps)"
12
+ now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
13
+ STDERR.puts "Litejob finished in #{now - time} seconds (#{count / (now - time)} jps)"
13
14
  end
14
15
  end
15
16
  end
@@ -16,12 +16,16 @@ module ActiveJob
16
16
  DEFAULT_OPTIONS = {
17
17
  config_path: "./config/litejob.yml",
18
18
  path: "../db/queue.db",
19
- queues: [["default", 1, "spawn"]],
20
- workers: 1
19
+ queues: [["default", 1]],
20
+ logger: nil, # Rails performs its logging already
21
+ retries: 5, # It is recommended to stop retries at the Rails level
22
+ workers: 5
21
23
  }
22
24
 
23
25
  def initialize(options={})
24
- Job.options = DEFAULT_OPTIONS.merge(options)
26
+ # we currently don't honour individual options per job class
27
+ # possible in the future?
28
+ # Job.options = DEFAULT_OPTIONS.merge(options)
25
29
  end
26
30
 
27
31
  def enqueue(job) # :nodoc:
@@ -95,7 +95,7 @@ module ActiveRecord
95
95
  end
96
96
 
97
97
  module DatabaseTasks
98
- register_task(/ultralite/, "ActiveRecord::Tasks::LitedbDatabaseTasks")
98
+ register_task(/litedb/, "ActiveRecord::Tasks::LitedbDatabaseTasks")
99
99
 
100
100
  end
101
101
  end
@@ -43,7 +43,7 @@ module Litejob
43
43
  private
44
44
  def self.included(klass)
45
45
  klass.extend(ClassMethods)
46
- klass.get_jobqueue
46
+ #klass.get_jobqueue
47
47
  end
48
48
 
49
49
  module ClassMethods
@@ -52,32 +52,37 @@ module Litejob
52
52
  end
53
53
 
54
54
  def perform_at(time, *params)
55
- delay = time - Time.now.to_i
55
+ delay = time.to_i - Time.now.to_i
56
56
  get_jobqueue.push(self.name, params, delay, queue)
57
57
  end
58
58
 
59
- def perfrom_in(delay, *params)
59
+ def perform_in(delay, *params)
60
60
  get_jobqueue.push(self.name, params, delay, queue)
61
61
  end
62
-
63
- def options
64
- @@options ||= {}
62
+
63
+ def perform_after(delay, *params)
64
+ perform_in(delay, *params)
65
65
  end
66
-
67
- def options=(options)
68
- @@options = options
66
+
67
+ def process_jobs
68
+ get_jobqueue
69
69
  end
70
-
70
+
71
+ def delete(id, queue_name=nil)
72
+ queue_name ||= queue
73
+ get_jobqueue.delete(id, queue)
74
+ end
75
+
71
76
  def queue
72
- @@queue_name ||= "default"
77
+ @@queue ||= "default"
73
78
  end
74
79
 
75
80
  def queue=(queue_name)
76
- @@queue_name = queue_name.to_s
81
+ @@queue = queue_name.to_s
77
82
  end
78
83
 
79
84
  def get_jobqueue
80
- Litejobqueue.jobqueue(options)
85
+ Litejobqueue.jobqueue
81
86
  end
82
87
  end
83
88
 
@@ -1,5 +1,5 @@
1
1
  # frozen_stringe_literal: true
2
-
2
+ require 'logger'
3
3
  require 'oj'
4
4
  require 'yaml'
5
5
  require_relative './litequeue'
@@ -32,13 +32,21 @@ class Litejobqueue
32
32
  DEFAULT_OPTIONS = {
33
33
  config_path: "./litejob.yml",
34
34
  path: "./queue.db",
35
- queues: [["default", 5]],
36
- workers: 1,
37
- sleep_intervals: [0.001, 0.005, 0.025, 0.125, 0.625, 3.125]
35
+ queues: [["default", 1]],
36
+ workers: 5,
37
+ retries: 5,
38
+ retry_delay: 60,
39
+ retry_delay_multiplier: 10,
40
+ dead_job_retention: 10 * 24 * 3600,
41
+ gc_sleep_interval: 7200,
42
+ logger: 'STDOUT',
43
+ sleep_intervals: [0.001, 0.005, 0.025, 0.125, 0.625, 1.0, 2.0]
38
44
  }
39
45
 
40
46
  @@queue = nil
41
47
 
48
+ attr_reader :running
49
+
42
50
  # a method that returns a single instance of the job queue
43
51
  # for use by Litejob
44
52
  def self.jobqueue(options = {})
@@ -57,14 +65,30 @@ class Litejobqueue
57
65
  #
58
66
  def initialize(options = {})
59
67
  @options = DEFAULT_OPTIONS.merge(options)
60
- @worker_sleep_index = 0
61
68
  config = YAML.load_file(@options[:config_path]) rescue {} # an empty hash won't hurt
62
69
  config.keys.each do |k| # symbolize keys
63
70
  config[k.to_sym] = config[k]
64
71
  config.delete k
65
72
  end
66
73
  @options.merge!(config)
74
+ @options.merge!(options) # make sure options passed to initialize trump everything else
75
+
67
76
  @queue = Litequeue.new(@options) # create a new queue object
77
+
78
+ # create logger
79
+ if @options[:logger].respond_to? :info
80
+ @logger = @options[:logger]
81
+ elsif @options[:logger] == 'STDOUT'
82
+ @logger = Logger.new(STDOUT)
83
+ elsif @options[:logger] == 'STDERR'
84
+ @logger = Logger.new(STDERR)
85
+ elsif @options[:logger].nil?
86
+ @logger = Logger.new(IO::NULL)
87
+ elsif @options[:logger].is_a? String
88
+ @logger = Logger.new(@options[:logger])
89
+ else
90
+ @logger = Logger.new(IO::NULL)
91
+ end
68
92
  # group and order queues according to their priority
69
93
  pgroups = {}
70
94
  @options[:queues].each do |q|
@@ -72,7 +96,25 @@ class Litejobqueue
72
96
  pgroups[q[1]] << [q[0], q[2] == "spawn"]
73
97
  end
74
98
  @queues = pgroups.keys.sort.reverse.collect{|p| [p, pgroups[p]]}
75
- @workers = @options[:workers].times.collect{create_worker}
99
+ @running = true
100
+ @workers = @options[:workers].times.collect{ create_worker }
101
+
102
+ @gc = create_garbage_collector
103
+ @jobs_in_flight = 0
104
+ @mutex = Litesupport::Mutex.new
105
+
106
+ at_exit do
107
+ @running = false
108
+ puts "--- Litejob detected an exit attempt, cleaning up"
109
+ index = 0
110
+ while @jobs_in_flight > 0 and index < 5
111
+ puts "--- Waiting for #{@jobs_in_flight} jobs to finish"
112
+ sleep 1
113
+ index += 1
114
+ end
115
+ puts " --- Exiting with #{@jobs_in_flight} jobs in flight"
116
+ end
117
+
76
118
  end
77
119
 
78
120
  # push a job to the queue
@@ -84,8 +126,10 @@ class Litejobqueue
84
126
  # jobqueue = Litejobqueue.new
85
127
  # jobqueue.push(EasyJob, params) # the job will be performed asynchronously
86
128
  def push(jobclass, params, delay=0, queue=nil)
87
- payload = Oj.dump([jobclass, params])
88
- @queue.push(payload, delay, queue)
129
+ payload = Oj.dump({klass: jobclass, params: params, retries: @options[:retries], queue: queue})
130
+ res = @queue.push(payload, delay, queue)
131
+ @logger.info("[litejob]:[ENQ] id: #{res} job: #{jobclass}")
132
+ res
89
133
  end
90
134
 
91
135
  # delete a job from the job queue
@@ -96,14 +140,42 @@ class Litejobqueue
96
140
  # end
97
141
  # jobqueue = Litejobqueue.new
98
142
  # id = jobqueue.push(EasyJob, params, 10) # queue for processing in 10 seconds
99
- # jobqueue.delete(id)
100
- def delete(id)
101
- job = @queue.delete(id)
102
- Oj.load(job) if job
143
+ # jobqueue.delete(id, 'default')
144
+ def delete(id, queue=nil)
145
+ job = @queue.delete(id, queue)
146
+ @logger.info("[litejob]:[DEL] job: #{job}")
147
+ job = Oj.load(job[0]) if job
148
+ job
149
+ end
150
+
151
+ # delete all jobs in a certain named queue
152
+ # or delete all jobs if the queue name is nil
153
+ def clear(queue=nil)
154
+ @queue.clear(queue)
155
+ end
156
+
157
+ # stop the queue object (does not delete the jobs in the queue)
158
+ # specifically useful for testing
159
+ def stop
160
+ @running = false
161
+ @@queue = nil
162
+ end
163
+
164
+
165
+ def count(queue=nil)
166
+ @queue.count(queue)
103
167
  end
104
168
 
105
169
  private
106
170
 
171
+ def job_started
172
+ Litesupport.synchronize(@mutex){@jobs_in_flight += 1}
173
+ end
174
+
175
+ def job_finished
176
+ Litesupport.synchronize(@mutex){@jobs_in_flight -= 1}
177
+ end
178
+
107
179
  # optionally run a job in its own context
108
180
  def schedule(spawn = false, &block)
109
181
  if spawn
@@ -111,50 +183,81 @@ class Litejobqueue
111
183
  else
112
184
  yield
113
185
  end
114
- end
115
-
186
+ end
187
+
116
188
  # create a worker according to environment
117
189
  def create_worker
118
190
  Litesupport.spawn do
119
- loop do
191
+ worker_sleep_index = 0
192
+ while @running do
120
193
  processed = 0
121
194
  @queues.each do |level| # iterate through the levels
122
195
  level[1].each do |q| # iterate through the queues in the level
123
196
  index = 0
124
197
  max = level[0]
125
- while index < max && payload = @queue.pop(q[0]) # fearlessly use the same queue object
198
+ while index < max && payload = @queue.pop(q[0], 1) # fearlessly use the same queue object
126
199
  processed += 1
127
200
  index += 1
128
201
  begin
129
202
  id, job = payload[0], payload[1]
130
203
  job = Oj.load(job)
131
- klass = eval(job[0])
204
+ # first capture the original job id
205
+ job[:id] = id if job[:retries].to_i == @options[:retries].to_i
206
+ @logger.info "[litejob]:[DEQ] job:#{job}"
207
+ klass = eval(job[:klass])
132
208
  schedule(q[1]) do # run the job in a new context
209
+ job_started #(Litesupport.current_context)
133
210
  begin
134
- klass.new.perform(*job[1])
211
+ klass.new.perform(*job[:params])
212
+ @logger.info "[litejob]:[END] job:#{job}"
135
213
  rescue Exception => e
136
- puts e
137
- puts e.message
138
- puts e.backtrace
214
+ # we can retry the failed job now
215
+ if job[:retries] == 0
216
+ @logger.error "[litejob]:[ERR] job: #{job} failed with #{e}:#{e.message}, retries exhausted, moved to _dead queue"
217
+ @queue.push(Oj.dump(job), @options[:dead_job_retention], '_dead')
218
+ else
219
+ retry_delay = @options[:retry_delay_multiplier].pow(@options[:retries] - job[:retries]) * @options[:retry_delay]
220
+ job[:retries] -= 1
221
+ @logger.error "[litejob]:[ERR] job: #{job} failed with #{e}:#{e.message}, retrying in #{retry_delay}"
222
+ @queue.push(Oj.dump(job), retry_delay, q[0])
223
+ @logger.info "[litejob]:[ENQ] job: #{job} enqueued"
224
+ end
139
225
  end
226
+ job_finished #(Litesupport.current_context)
140
227
  end
141
228
  rescue Exception => e
142
- puts e
143
- puts e.message
144
- puts e.backtrace
229
+ # this is an error in the extraction of job info
230
+ # retrying here will not be useful
231
+ @logger.error "[litejob]:[ERR] failed to extract job info for: #{payload} with #{e}:#{e.message}"
145
232
  end
146
- Litesupport.switch #give other context a chance to run here
233
+ Litesupport.switch #give other contexts a chance to run here
147
234
  end
148
235
  end
149
236
  end
150
237
  if processed == 0
151
- sleep @options[:sleep_intervals][@worker_sleep_index]
152
- @worker_sleep_index += 1 if @worker_sleep_index < @options[:sleep_intervals].length - 1
238
+ sleep @options[:sleep_intervals][worker_sleep_index]
239
+ worker_sleep_index += 1 if worker_sleep_index < @options[:sleep_intervals].length - 1
153
240
  else
154
- @worker_sleep_index = 0 # reset the index
241
+ worker_sleep_index = 0 # reset the index
155
242
  end
156
243
  end
157
244
  end
158
- end
245
+ end
246
+
247
+ # create a gc for dead jobs
248
+ def create_garbage_collector
249
+ Litesupport.spawn do
250
+ while @running do
251
+ while jobs = @queue.pop('_dead', 100)
252
+ if jobs[0].is_a? Array
253
+ @logger.info "[litejob]:[DEL] garbage collector deleted #{jobs.length} dead jobs"
254
+ else
255
+ @logger.info "[litejob]:[DEL] garbage collector deleted 1 dead job"
256
+ end
257
+ end
258
+ sleep @options[:gc_sleep_interval]
259
+ end
260
+ end
261
+ end
159
262
 
160
263
  end