solid-jobs 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidJobs
4
+ module Utilities
5
+ module_function
6
+
7
+ def stringify_keys(value)
8
+ case value
9
+ when Hash
10
+ value.each_with_object({}) do |(key, nested), result|
11
+ result[key.to_s] = stringify_keys(nested)
12
+ end
13
+ when Array
14
+ value.map { |nested| stringify_keys(nested) }
15
+ else
16
+ value
17
+ end
18
+ end
19
+
20
+ def stringify_hash_keys(hash)
21
+ hash.each_with_object({}) { |(key, value), result| result[key.to_s] = value }
22
+ end
23
+
24
+ def shareable_copy(value)
25
+ return value if Ractor.shareable?(value)
26
+
27
+ copied = case value
28
+ when Hash
29
+ value.each_with_object({}) do |(key, nested), result|
30
+ result[shareable_copy(key)] = shareable_copy(nested)
31
+ end
32
+ when Array
33
+ value.map { |nested| shareable_copy(nested) }
34
+ when String
35
+ value.dup.freeze
36
+ when Symbol, Numeric, true, false, nil
37
+ value
38
+ else
39
+ value.frozen? ? value : value.dup.freeze
40
+ end
41
+ Ractor.make_shareable(copied)
42
+ end
43
+
44
+ def constantize(name)
45
+ name.split("::").reject(&:empty?).reduce(Object) { |scope, part| scope.const_get(part, false) }
46
+ end
47
+
48
+ def realtime_milliseconds
49
+ ::Process.clock_gettime(::Process::CLOCK_REALTIME, :millisecond)
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidJobs
4
+ VERSION = "0.1.0"
5
+ end
6
+
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+
5
+ module SolidJobs
6
+ class Worker
7
+ attr_reader :config
8
+
9
+ def initialize(redis_config:, config: nil)
10
+ @config = config || Config.new(redis: redis_config)
11
+ end
12
+
13
+ def perform(payload)
14
+ payload = JSON.parse(payload) if payload.is_a?(String)
15
+ raise InvalidJobError, "Job payload must be a Hash" unless payload.is_a?(Hash)
16
+
17
+ class_name = payload["class"] || payload["job_class"]
18
+ raise InvalidJobError, "Job must include a non-empty class" if class_name.nil? || class_name.empty?
19
+ raise InvalidJobError, "Job args must be an Array" unless payload["args"].is_a?(Array)
20
+ raise InvalidJobError, "Job queue must be present" if payload["queue"].nil? || payload["queue"].empty?
21
+
22
+ job_class = Utilities.constantize(class_name)
23
+ job = job_class.new
24
+ job.jid = payload["jid"] if job.respond_to?(:jid=)
25
+
26
+ if config.server_middleware.empty?
27
+ job.perform(*payload.fetch("args"))
28
+ else
29
+ config.server_middleware.invoke(job, payload, payload.fetch("queue")) do
30
+ job.perform(*payload.fetch("args"))
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
data/lib/solid_jobs.rb ADDED
@@ -0,0 +1,92 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "base_service"
4
+ require "callback_collection"
5
+ require "solid_redis"
6
+ require "solid_resp_ractor"
7
+
8
+ require_relative "solid_jobs/version"
9
+ require_relative "solid_jobs/errors"
10
+ require_relative "solid_jobs/utilities"
11
+ require_relative "solid_jobs/ractor_support"
12
+ require_relative "solid_jobs/startup_barrier"
13
+ require_relative "solid_jobs/middleware/chain"
14
+ require_relative "solid_jobs/config"
15
+ require_relative "solid_jobs/client"
16
+ require_relative "solid_jobs/testing"
17
+ require_relative "solid_jobs/job"
18
+ require_relative "solid_jobs/worker"
19
+ require_relative "solid_jobs/fetch"
20
+ require_relative "solid_jobs/retry_service"
21
+ require_relative "solid_jobs/scheduler"
22
+ require_relative "solid_jobs/processor"
23
+ require_relative "solid_jobs/heartbeat"
24
+ require_relative "solid_jobs/recovery"
25
+ require_relative "solid_jobs/integrity_check"
26
+ require_relative "solid_jobs/server"
27
+ require_relative "solid_jobs/api"
28
+ require_relative "solid_jobs/active_job" if defined?(::ActiveJob::Base)
29
+ require_relative "solid_jobs/rails" if defined?(::Rails::Railtie)
30
+
31
+ module SolidJobs
32
+ CONFIG_KEY = :solid_jobs_config
33
+
34
+ module_function
35
+
36
+ def config
37
+ Thread.current[CONFIG_KEY] ||= Config.new
38
+ end
39
+
40
+ def configure
41
+ yield config
42
+ config
43
+ end
44
+
45
+ def use_config(configuration)
46
+ Thread.current[CONFIG_KEY]&.close
47
+ Thread.current[CONFIG_KEY] = configuration
48
+ end
49
+
50
+ def reset!
51
+ Thread.current[CONFIG_KEY]&.close
52
+ Thread.current[CONFIG_KEY] = Config.new
53
+ end
54
+
55
+ def testing!(mode, &block)
56
+ Testing.testing!(mode, &block)
57
+ end
58
+
59
+ def enqueue(job_class, args, queue: "default", **options)
60
+ Client.push(
61
+ options.merge(
62
+ "class" => job_class,
63
+ "args" => args,
64
+ "queue" => queue,
65
+ ),
66
+ )
67
+ end
68
+
69
+ def enqueue_bulk(job_class, arguments, queue: "default", **options)
70
+ Client.push_bulk(
71
+ options.merge(
72
+ "class" => job_class,
73
+ "args" => arguments,
74
+ "queue" => queue,
75
+ ),
76
+ )
77
+ end
78
+
79
+ def redis(&block)
80
+ raise ArgumentError, "SolidJobs.redis requires a block" unless block
81
+
82
+ config.redis(&block)
83
+ end
84
+
85
+ def redis_pool
86
+ config.redis_pool
87
+ end
88
+
89
+ def recovery!
90
+ Recovery.call(config: config).result
91
+ end
92
+ end
metadata ADDED
@@ -0,0 +1,189 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: solid-jobs
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Nicolas Vandenbogaerde
8
+ bindir: exe
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: base-service
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '0.1'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '0.1'
26
+ - !ruby/object:Gem::Dependency
27
+ name: callback-collection
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: '0.2'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '0.2'
40
+ - !ruby/object:Gem::Dependency
41
+ name: logger
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '1.7'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '1.7'
54
+ - !ruby/object:Gem::Dependency
55
+ name: solid-redis
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '1.0'
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: 1.0.10
64
+ type: :runtime
65
+ prerelease: false
66
+ version_requirements: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - "~>"
69
+ - !ruby/object:Gem::Version
70
+ version: '1.0'
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: 1.0.10
74
+ - !ruby/object:Gem::Dependency
75
+ name: solid-resp-ractor
76
+ requirement: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - "~>"
79
+ - !ruby/object:Gem::Version
80
+ version: '0.1'
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: 0.1.3
84
+ type: :runtime
85
+ prerelease: false
86
+ version_requirements: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - "~>"
89
+ - !ruby/object:Gem::Version
90
+ version: '0.1'
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: 0.1.3
94
+ - !ruby/object:Gem::Dependency
95
+ name: minitest
96
+ requirement: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: '5'
101
+ - - "<"
102
+ - !ruby/object:Gem::Version
103
+ version: '7'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '5'
111
+ - - "<"
112
+ - !ruby/object:Gem::Version
113
+ version: '7'
114
+ - !ruby/object:Gem::Dependency
115
+ name: rake
116
+ requirement: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - "~>"
119
+ - !ruby/object:Gem::Version
120
+ version: '13.0'
121
+ type: :development
122
+ prerelease: false
123
+ version_requirements: !ruby/object:Gem::Requirement
124
+ requirements:
125
+ - - "~>"
126
+ - !ruby/object:Gem::Version
127
+ version: '13.0'
128
+ description: Ractor-local job clients and workers with Sidekiq-compatible Redis payloads,
129
+ queues, scheduling, and retries.
130
+ executables:
131
+ - solid-jobs
132
+ extensions: []
133
+ extra_rdoc_files: []
134
+ files:
135
+ - CHANGELOG.md
136
+ - LICENSE.txt
137
+ - README.md
138
+ - docs/reliability.md
139
+ - exe/solid-jobs
140
+ - lib/active_job/queue_adapters/solid_jobs_adapter.rb
141
+ - lib/solid_jobs.rb
142
+ - lib/solid_jobs/active_job.rb
143
+ - lib/solid_jobs/api.rb
144
+ - lib/solid_jobs/cli.rb
145
+ - lib/solid_jobs/client.rb
146
+ - lib/solid_jobs/config.rb
147
+ - lib/solid_jobs/errors.rb
148
+ - lib/solid_jobs/fetch.rb
149
+ - lib/solid_jobs/heartbeat.rb
150
+ - lib/solid_jobs/integrity_check.rb
151
+ - lib/solid_jobs/job.rb
152
+ - lib/solid_jobs/middleware/chain.rb
153
+ - lib/solid_jobs/processor.rb
154
+ - lib/solid_jobs/ractor_support.rb
155
+ - lib/solid_jobs/rails.rb
156
+ - lib/solid_jobs/recovery.rb
157
+ - lib/solid_jobs/retry_service.rb
158
+ - lib/solid_jobs/scheduler.rb
159
+ - lib/solid_jobs/server.rb
160
+ - lib/solid_jobs/startup_barrier.rb
161
+ - lib/solid_jobs/testing.rb
162
+ - lib/solid_jobs/utilities.rb
163
+ - lib/solid_jobs/version.rb
164
+ - lib/solid_jobs/worker.rb
165
+ homepage: https://github.com/nicolasva/solid-jobs
166
+ licenses:
167
+ - MIT
168
+ metadata:
169
+ rubygems_mfa_required: 'true'
170
+ source_code_uri: https://github.com/nicolasva/solid-jobs
171
+ changelog_uri: https://github.com/nicolasva/solid-jobs/blob/main/CHANGELOG.md
172
+ rdoc_options: []
173
+ require_paths:
174
+ - lib
175
+ required_ruby_version: !ruby/object:Gem::Requirement
176
+ requirements:
177
+ - - ">="
178
+ - !ruby/object:Gem::Version
179
+ version: '3.2'
180
+ required_rubygems_version: !ruby/object:Gem::Requirement
181
+ requirements:
182
+ - - ">="
183
+ - !ruby/object:Gem::Version
184
+ version: '0'
185
+ requirements: []
186
+ rubygems_version: 3.6.9
187
+ specification_version: 4
188
+ summary: A Ractor-oriented Redis background job system
189
+ test_files: []