litejob 0.2.1 → 0.2.2

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: 9235b916ceb5620f30e307e23adb1c3baf256625a3d3cedde1c2851faa9ed490
4
- data.tar.gz: 553500fbb22d4ef729a6059277cb56738c87b671e4009ac9c3b7174293f7bfb8
3
+ metadata.gz: 7c4bdf49bc448e94756a084b9ccd2ada75a5a3b74b48d92a2e598a8eeba47961
4
+ data.tar.gz: 743856cc10d998e7f0e1be88eaadcf1d5f2a66759e3819b4dc733439da49178c
5
5
  SHA512:
6
- metadata.gz: 86125548df029a4a0035314ff34f3a429394079d56b88075e7b05ec72a4975a9b7ee32ed130bef939cfe4edd6a6cbc02b46458e011df847fd942efbbdbd36562
7
- data.tar.gz: 50f38790e97d1b19462a5926bd2a92fbcbc9485ccadf2c89a9c1f1effc4ccd566650bea57400793d3d11aec0390c647f81e04d2ead1963aa0889f9522918654a
6
+ metadata.gz: 88f7d30be4b531ddb717d51db662ffd7cd7473f6da5b48efc13fdd1b05ac95910b5168cbd60ba1aceac74c69b02794e76b27df2ade238ac3b4dbb45fc87e0f49
7
+ data.tar.gz: 7648f507ae5e5fc9d05adfb939d3210de6992f5cc99758921ae83ce6b210294147d4a84f9bc4fda733384e10699b68c38f4456f2b863282b5e777d35d51b85b4
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.2.2] - 2023-08-14
4
+
5
+ - Add logging
6
+
3
7
  ## [0.2.1] - 2023-08-13
4
8
 
5
9
  - Fix some bugs with Litejob::Server
data/Gemfile.lock CHANGED
@@ -1,8 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- litejob (0.2.1)
5
- litequeue (>= 0.2.0)
4
+ litejob (0.2.2)
5
+ litequeue (>= 0.2.1)
6
6
  litescheduler (>= 0.2.1)
7
7
 
8
8
  GEM
@@ -16,7 +16,7 @@ GEM
16
16
  litedb (0.2.1)
17
17
  litescheduler (>= 0.2.0)
18
18
  sqlite3 (>= 1.5.0)
19
- litequeue (0.2.0)
19
+ litequeue (0.2.1)
20
20
  litedb (>= 0.2.1)
21
21
  litescheduler (0.2.1)
22
22
  minitest (5.19.0)
data/README.md CHANGED
@@ -5,25 +5,69 @@
5
5
  ![Tests](https://github.com/litestack-ruby/litejob/actions/workflows/main.yml/badge.svg)
6
6
  ![Coverage](https://img.shields.io/badge/code_coverage-100%25-brightgreen)
7
7
 
8
- TODO: Delete this and the text below, and describe your gem
9
-
10
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/litejob`. To experiment with that code, run `bin/console` for an interactive prompt.
8
+ Litejob is a Ruby module that enables seamless integration of the Litequeue job queueing system into Ruby applications. By including the Litejob module in a class and implementing the `#perform` method, developers can easily enqueue and process jobs asynchronously.
11
9
 
12
10
  ## Installation
13
11
 
14
- TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
15
-
16
12
  Install the gem and add to the application's Gemfile by executing:
17
13
 
18
- $ bundle add UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG
14
+ $ bundle add litejob
19
15
 
20
16
  If bundler is not being used to manage dependencies, install the gem by executing:
21
17
 
22
- $ gem install UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG
18
+ $ gem install litejob
23
19
 
24
20
  ## Usage
25
21
 
26
- TODO: Write usage instructions here
22
+ When a job is enqueued, Litejob creates a new instance of the class and passes it any necessary arguments. The class's `#perform` method is then called asynchronously to process the job. This allows the application to continue running without waiting for the job to finish, improving overall performance and responsiveness.
23
+
24
+ One of the main benefits of using Litejob is its simplicity. Because it integrates directly with Litequeue, developers do not need to worry about managing job queues or processing logic themselves. Instead, they can focus on implementing the `#perform` method to handle the specific job tasks.
25
+
26
+ Litejob also provides a number of useful features, including the ability to set job priorities, retry failed jobs, and limit the number of retries. These features can be configured using simple configuration options in the class that includes the Litejob module.
27
+
28
+ Overall, Litejob is a powerful and flexible module that allows developers to easily integrate Litequeue job queueing into their Ruby applications. By enabling asynchronous job processing, Litejob can help improve application performance and scalability, while simplifying the development and management of background job processing logic.
29
+
30
+ ```ruby
31
+ class EasyJob
32
+ include ::Litejob
33
+
34
+ def perform(params)
35
+ # do stuff
36
+ end
37
+ end
38
+ ```
39
+
40
+ Then later you can perform a job asynchronously:
41
+
42
+ ```ruby
43
+ EasyJob.perform_async(params) # perform a job synchronously
44
+ ```
45
+
46
+ Or perform it at a specific time:
47
+
48
+ ```ruby
49
+ EasyJob.perform_at(time, params) # perform a job at a specific time
50
+ ```
51
+
52
+ Or perform it after a certain delay:
53
+
54
+ ```ruby
55
+ EasyJob.perform_in(delay, params) # perform a job after a certain delay
56
+ ```
57
+
58
+ You can also specify a specific queue to be used
59
+
60
+ ```ruby
61
+ class EasyJob
62
+ include ::Litejob
63
+
64
+ self.queue = :urgent
65
+
66
+ def perform(params)
67
+ # do stuff
68
+ end
69
+ end
70
+ ```
27
71
 
28
72
  ## Development
29
73
 
@@ -33,7 +77,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
33
77
 
34
78
  ## Contributing
35
79
 
36
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/litejob. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/litejob/blob/main/CODE_OF_CONDUCT.md).
80
+ Bug reports and pull requests are welcome on GitHub at https://github.com/litestack-ruby/litejob. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/litestack-ruby/litejob/blob/main/CODE_OF_CONDUCT.md).
37
81
 
38
82
  ## License
39
83
 
@@ -41,4 +85,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
41
85
 
42
86
  ## Code of Conduct
43
87
 
44
- Everyone interacting in the Litejob project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/litejob/blob/main/CODE_OF_CONDUCT.md).
88
+ Everyone interacting in the Litejob project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/litestack-ruby/litejob/blob/main/CODE_OF_CONDUCT.md).
@@ -15,11 +15,14 @@ module Litejob
15
15
  attempts = options[:attempts] || 5
16
16
  queue = options[:queue]
17
17
  payload = JSON.dump({class: jobclass, params: params, attempts: attempts, queue: queue})
18
- atomic_push(payload, delay, queue)
18
+ job_id, job_queue = atomic_push(payload, delay, queue)
19
+ Litejob.logger.info("[litejob]:[ENQ] queue=#{job_queue} class=#{jobclass} job=#{job_id}")
20
+ [job_id, job_queue]
19
21
  end
20
22
 
21
23
  def delete(id)
22
24
  payload = @queue.delete(id)
25
+ Litejob.logger.info("[litejob]:[DEL] job=#{id}")
23
26
  JSON.parse(payload)
24
27
  end
25
28
 
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "client"
4
+
5
+ module Litejob
6
+ # Litejob::Concern is responsible for providing an interface to job classes
7
+ module Concern
8
+ def perform_async(*params)
9
+ @litejob_options ||= {}
10
+ client.push(name, params, @litejob_options.merge(delay: 0, queue: queue_name))
11
+ end
12
+
13
+ def perform_at(time, *params)
14
+ @litejob_options ||= {}
15
+ delay = time.to_i - Time.now.to_i
16
+ client.push(name, params, @litejob_options.merge(delay: delay, queue: queue_name))
17
+ end
18
+
19
+ def perform_in(delay, *params)
20
+ @litejob_options ||= {}
21
+ client.push(name, params, @litejob_options.merge(delay: delay, queue: queue_name))
22
+ end
23
+ alias_method :perform_after, :perform_in
24
+
25
+ def delete(id)
26
+ client.delete(id)
27
+ end
28
+
29
+ def queue_as(queue_name)
30
+ @queue_name = queue_name.to_s
31
+ end
32
+
33
+ def litejob_options(options)
34
+ @litejob_options = options
35
+ end
36
+
37
+ private
38
+
39
+ def queue_name
40
+ @queue_name || "default"
41
+ end
42
+
43
+ def client
44
+ @client ||= Client.new
45
+ end
46
+ end
47
+ end
@@ -6,36 +6,67 @@ require "litequeue"
6
6
  module Litejob
7
7
  # Litejob::Processor is responsible for processing job payloads
8
8
  class Processor
9
- def initialize(payload)
10
- @payload = payload
11
- @queue = Litequeue.instance
9
+ def initialize(queue, id, serialized_job)
10
+ @queue = queue
11
+ @id = id
12
+ @serialized_job = serialized_job
13
+ @job_hash = JSON.parse(@serialized_job)
14
+ @litequeue = Litequeue.instance
15
+
16
+ set_log_context!(queue: @queue, class: @job_hash["class"], job: @id)
12
17
  end
13
18
 
14
19
  def repush(id, job, delay = 0, queue = nil)
15
- @queue.repush(id, JSON.dump(job), queue: queue, delay: delay)
20
+ @litequeue.repush(id, JSON.dump(job), queue: queue, delay: delay)
16
21
  end
17
22
 
18
23
  def process!
19
- id, serialized_job = @payload
20
- job_hash = JSON.parse(serialized_job)
21
- klass = Object.const_get(job_hash["class"])
24
+ log(:deq)
25
+ klass = Object.const_get(@job_hash["class"])
22
26
  instance = klass.new
23
27
 
24
28
  begin
25
- instance.perform(*job_hash["params"])
26
- rescue
27
- if job_hash["retries_left"] == 0
28
- repush(id, job_hash, 0, "_dead")
29
+ instance.perform(*@job_hash["params"])
30
+ log(:end)
31
+ rescue StandardError => e
32
+ if @job_hash["retries_left"] == 0
33
+ err(e, "retries exhausted, moving to _dead queue")
34
+ repush(@id, @job_hash, 0, "_dead")
29
35
  else
30
- job_hash["retries_left"] ||= job_hash["attempts"]
31
- job_hash["retries_left"] -= 1
32
- retry_delay = (job_hash["attempts"] - job_hash["retries_left"]) * 0.1
33
- repush(id, job_hash, retry_delay, job_hash["queue"])
36
+ @job_hash["retries_left"] ||= @job_hash["attempts"]
37
+ @job_hash["retries_left"] -= 1
38
+ retry_delay = (@job_hash["attempts"] - @job_hash["retries_left"]) * 0.1
39
+ err(e, "retrying in #{retry_delay} seconds")
40
+ repush(@id, @job_hash, retry_delay, @job_hash["queue"])
34
41
  end
35
42
  end
36
- rescue => exception # standard:disable Lint/UselessRescue
43
+ rescue StandardError => e
37
44
  # this is an error in the extraction of job info, retrying here will not be useful
38
- raise exception
45
+ err(e, "while processing job=#{@serialized_job}")
46
+ raise e
47
+ end
48
+
49
+ private
50
+
51
+ def set_log_context!(**attributes)
52
+ @log_context = attributes.map { |k, v| [k, v].join('=') }.join(' ')
53
+ end
54
+
55
+ def log(event, msg: nil)
56
+ prefix = "[litejob]:[#{event.to_s.upcase}]"
57
+
58
+ Litejob.logger.info [prefix, @log_context, msg].compact.join(" ")
59
+ end
60
+
61
+ def err(exception, msg = nil)
62
+ prefix = "[litejob]:[ERR]"
63
+ error_context = if exception.class.name == exception.message
64
+ "failed with #<#{exception.class.name}>"
65
+ else
66
+ "failed with #{exception.inspect}"
67
+ end
68
+
69
+ Litejob.logger.error [prefix, @log_context, error_context, msg].compact.join(" ")
39
70
  end
40
71
  end
41
72
  end
@@ -37,6 +37,7 @@ module Litejob
37
37
 
38
38
  def run!
39
39
  @scheduler.spawn do
40
+ Litejob.logger.info("[litejob]:[RUN] id=#{@scheduler.context.object_id}")
40
41
  worker_sleep_index = 0
41
42
  while @running
42
43
  processed = 0
@@ -47,7 +48,8 @@ module Litejob
47
48
  batched += 1
48
49
  processed += 1
49
50
 
50
- processor = Processor.new(payload)
51
+ id, serialized_job = payload
52
+ processor = Processor.new(queue, id, serialized_job)
51
53
  processor.process!
52
54
 
53
55
  # give other contexts a chance to run here
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Litejob
4
- VERSION = "0.2.1"
4
+ VERSION = "0.2.2"
5
5
  end
data/lib/litejob.rb CHANGED
@@ -1,53 +1,28 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "litejob/version"
4
- require_relative "litejob/client"
4
+ require_relative "litejob/concern"
5
5
  require_relative "litejob/server"
6
+ require "logger"
6
7
 
7
- # Litejob is responsible for providing an interface to job classes
8
8
  module Litejob
9
9
  def self.included(klass)
10
- klass.extend(ClassMethods)
10
+ klass.extend(Concern)
11
11
  end
12
-
13
- module ClassMethods
14
- def perform_async(*params)
15
- @litejob_options ||= {}
16
- client.push(name, params, @litejob_options.merge(delay: 0, queue: queue_name))
17
- end
18
-
19
- def perform_at(time, *params)
20
- @litejob_options ||= {}
21
- delay = time.to_i - Time.now.to_i
22
- client.push(name, params, @litejob_options.merge(delay: delay, queue: queue_name))
23
- end
24
-
25
- def perform_in(delay, *params)
26
- @litejob_options ||= {}
27
- client.push(name, params, @litejob_options.merge(delay: delay, queue: queue_name))
28
- end
29
- alias_method :perform_after, :perform_in
30
-
31
- def delete(id)
32
- client.delete(id)
33
- end
34
-
35
- def queue_as(queue_name)
36
- @queue_name = queue_name.to_s
37
- end
38
-
39
- def litejob_options(options)
40
- @litejob_options = options
41
- end
42
-
43
- private
44
-
45
- def queue_name
46
- @queue_name || "default"
47
- end
48
-
49
- def client
50
- @client ||= Client.new
51
- end
12
+
13
+ Configuration = Struct.new(:logger)
14
+
15
+ def self.configuration
16
+ @configuration ||= Configuration.new(
17
+ _logger = Logger.new($stdout),
18
+ )
19
+ end
20
+
21
+ def self.configure
22
+ yield(configuration)
23
+ end
24
+
25
+ def self.logger
26
+ configuration.logger
52
27
  end
53
28
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: litejob
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mohamed Hassan
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2023-08-13 00:00:00.000000000 Z
12
+ date: 2023-08-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: litescheduler
@@ -31,14 +31,14 @@ dependencies:
31
31
  requirements:
32
32
  - - ">="
33
33
  - !ruby/object:Gem::Version
34
- version: 0.2.0
34
+ version: 0.2.1
35
35
  type: :runtime
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
39
  - - ">="
40
40
  - !ruby/object:Gem::Version
41
- version: 0.2.0
41
+ version: 0.2.1
42
42
  - !ruby/object:Gem::Dependency
43
43
  name: simplecov
44
44
  requirement: !ruby/object:Gem::Requirement
@@ -71,6 +71,7 @@ files:
71
71
  - Rakefile
72
72
  - lib/litejob.rb
73
73
  - lib/litejob/client.rb
74
+ - lib/litejob/concern.rb
74
75
  - lib/litejob/processor.rb
75
76
  - lib/litejob/server.rb
76
77
  - lib/litejob/version.rb