async-job-adapter-active_job 0.2.0 → 0.3.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a39dbb873ca265d9f750235a0be307e24110956aceb8a58e4c5fdebe53cd46ff
4
- data.tar.gz: aa5d024057874f46d90345f638d7355e0e7a5fd60dd9b16005ec3d489eb03b79
3
+ metadata.gz: 9963783ca059ac1a3572fdbcca27ecfb6b0e2512e8994603ba1e1191d77ece61
4
+ data.tar.gz: f4be3f33865cf8a1d5aeec993b518418c9f422090ed0de4c5ff16aef5a02a276
5
5
  SHA512:
6
- metadata.gz: 38b2b356333aee50cf84dbff824ef5da4dc3fe91068c6d94a1129e35975c59f4135f85ac4cb4bce5c08c2378138ece5270144737d18825f4bbe16e1c1e948360
7
- data.tar.gz: 62e653848d731ed01c794ec08e1d29938887e79632a49837557fe2307678126d29040b84d8b9220be3ca009d15c6454c7777088f138a2f86777597e552b5b153
6
+ metadata.gz: bc94ed3bad8be7871793b65a36cec6da478515df5cec6f0c733c842fd9af2f3024174314f7f2bab308d4bb7175dbec65b4c62934dae4578b9c9f97d7021108f7
7
+ data.tar.gz: c232453580b7ee21760449b7e31f69b06cc4f7ee862c885a7eb61e0bc90057fd9e27d9c38bd93e00c94af4e7ede932204fb8a3a3804850c61ae3e619bdb25e28
checksums.yaml.gz.sig CHANGED
Binary file
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2024, by Samuel Williams.
5
+
6
+ require_relative 'queue_adapter'
7
+ require_relative 'queue_handler'
8
+
9
+ module Async
10
+ module Job
11
+ module Adapter
12
+ module ActiveJob
13
+ class Builder
14
+ Pipeline = Struct.new(:adapter, :queue)
15
+
16
+ def initialize
17
+ @enqueue = []
18
+ @dequeue = []
19
+ @handler = QueueHandler::DEFAULT
20
+
21
+ @queue = nil
22
+ end
23
+
24
+ def enqueue(middleware)
25
+ @enqueue << middleware
26
+ end
27
+
28
+ def queue(queue, *arguments, **options)
29
+ # The handler is the output side of the queue, e.g. a QueueHandler or similar wrapper.
30
+ # The queue itself is instantiated with the handler.
31
+ @queue = ->(handler){queue.new(handler, *arguments, **options)}
32
+ end
33
+
34
+ def dequeue(middleware)
35
+ @dequeue << middleware
36
+ end
37
+
38
+ def handler(handler)
39
+ @handler = handler
40
+ end
41
+
42
+ def build
43
+ # To construct the queue, we need the handler.
44
+ handler = @handler
45
+
46
+ # We then wrap the handler with the middleware in reverse order:
47
+ @dequeue.reverse_each do |middleware|
48
+ handler = middleware.new(handler)
49
+ end
50
+
51
+ # We can now construct the queue with the handler:
52
+ queue = @queue.call(handler)
53
+
54
+ adapter = queue
55
+
56
+ # We now construct the queue adapter:
57
+ adapter = @enqueue.reverse_each do |middleware|
58
+ adapter = middleware.new(queue)
59
+ end
60
+
61
+ unless adapter.is_a?(QueueAdapter)
62
+ adapter = QueueAdapter.new(adapter)
63
+ end
64
+
65
+ # The adapter is the part we provide to ActiveJob, and the handler is the part that actually executes the job:
66
+ return Pipeline.new(adapter, queue)
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2024, by Samuel Williams.
5
+
6
+ require 'async/job'
7
+ require 'thread/local'
8
+
9
+ require_relative 'builder'
10
+
11
+ module Async
12
+ module Job
13
+ module Adapter
14
+ module ActiveJob
15
+ class Dispatcher
16
+ def initialize(backends, aliases = {})
17
+ @backends = backends
18
+ @aliases = aliases
19
+
20
+ @pipelines = {}
21
+ end
22
+
23
+ attr :backends
24
+
25
+ attr :aliases
26
+
27
+ def [](name)
28
+ @pipelines.fetch(name) do
29
+ backend = @backends.fetch(name)
30
+ @pipelines[name] = build(backend)
31
+ end
32
+ end
33
+
34
+ def enqueue(job)
35
+ name = @aliases.fetch(job.queue_name, job.queue_name)
36
+
37
+ self[name].adapter.enqueue(job)
38
+ end
39
+
40
+ def enqueue_at(job, timestamp)
41
+ name = @aliases.fetch(job.queue_name, job.queue_name)
42
+
43
+ self[name].adapter.enqueue_at(job, timestamp)
44
+ end
45
+
46
+ def start(name)
47
+ self[name].queue.start
48
+ end
49
+
50
+ private def build(backend)
51
+ builder = Builder.new
52
+
53
+ builder.instance_eval(&backend)
54
+
55
+ builder.build
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -22,17 +22,6 @@ module Async
22
22
  Console.info(self, "Enqueueing job at...", id: job.job_id, timestamp: timestamp)
23
23
  @server.schedule(@coder.dump(job.serialize), timestamp)
24
24
  end
25
-
26
- def start
27
- Async do
28
- @server.start
29
-
30
- @server.each do |id, data|
31
- job = @coder.parse(data)
32
- ::ActiveJob::Base.execute(job)
33
- end
34
- end
35
- end
36
25
  end
37
26
  end
38
27
  end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2024, by Samuel Williams.
5
+
6
+ require 'json'
7
+
8
+ module Async
9
+ module Job
10
+ module Adapter
11
+ module ActiveJob
12
+ class QueueHandler
13
+ def initialize(coder = JSON)
14
+ @coder = coder
15
+ end
16
+
17
+ def call(job)
18
+ job = @coder.load(job)
19
+ Console.info(self, "Calling job...", id: job[:job_id])
20
+ ::ActiveJob::Base.execute(job)
21
+ end
22
+
23
+ DEFAULT = self.new.freeze
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -3,38 +3,77 @@
3
3
  # Released under the MIT License.
4
4
  # Copyright, 2024, by Samuel Williams.
5
5
 
6
+ require 'async/job'
6
7
  require 'thread/local'
7
- require 'async/redis/client'
8
- require 'async/job/backend/redis/server'
8
+
9
+ require_relative 'dispatcher'
10
+
11
+ class Thread
12
+ attr_accessor :async_job_adapter_active_job_dispatcher
13
+ end
9
14
 
10
15
  module Async
11
16
  module Job
12
17
  module Adapter
13
18
  module ActiveJob
14
19
  class Railtie < ::Rails::Railtie
15
- config.async_job = ActiveSupport::OrderedOptions.new
20
+ DEFAULT_REDIS = proc do
21
+ queue Async::Job::Backend::Redis
22
+ end
23
+
24
+ def initialize
25
+ @backends = {default: DEFAULT_REDIS}
26
+ @aliases = {}
27
+ end
28
+
29
+ attr :backends
30
+
31
+ attr :aliases
32
+
33
+ def backend_for(name, *aliases, &block)
34
+ @backends[name] ||= block
35
+
36
+ if aliases.any?
37
+ alias_for(name, *aliases)
38
+ end
39
+ end
40
+
41
+ def alias_for(name, *aliases)
42
+ aliases.each do |alias_name|
43
+ @aliases[alias_name] = name
44
+ end
45
+ end
16
46
 
17
- module Dispatcher
18
- extend Thread::Local
47
+ # Used for dispatching jobs to a thread-local backend to avoid thread-safety issues.
48
+ class ThreadLocalDispatcher
49
+ def initialize(backends, aliases)
50
+ @backends = backends
51
+ @aliases = aliases
52
+ end
53
+
54
+ def dispatcher
55
+ Thread.current.async_job_adapter_active_job_dispatcher ||= Dispatcher.new(@backends)
56
+ end
19
57
 
20
- def self.local
21
- server = Async::Job::Backend.new(
22
- **Railtie.config.async_job
23
- )
24
-
25
- return QueueAdapter.new(server)
58
+ def enqueue_at(job, timestamp)
59
+ dispatcher.enqueue_at(job, timestamp)
26
60
  end
27
61
 
28
- def self.enqueue(job)
29
- self.instance.enqueue(job)
62
+ def enqueue(job)
63
+ dispatcher.enqueue(job)
30
64
  end
31
65
 
32
- def self.enqueue_at(job, timestamp)
33
- self.instance.enqueue_at(job, timestamp)
66
+ def start(name)
67
+ dispatcher.start(name)
34
68
  end
35
69
  end
36
70
 
37
- config.active_job.queue_adapter = Dispatcher
71
+ def start(name = :default)
72
+ config.active_job.queue_adapter.start(name)
73
+ end
74
+
75
+ config.async_job = self
76
+ config.active_job.queue_adapter = ThreadLocalDispatcher.new(self.backends, self.aliases)
38
77
  end
39
78
  end
40
79
  end
@@ -7,7 +7,7 @@ module Async
7
7
  module Job
8
8
  module Adapter
9
9
  module ActiveJob
10
- VERSION = "0.2.0"
10
+ VERSION = "0.3.0"
11
11
  end
12
12
  end
13
13
  end
@@ -5,5 +5,4 @@
5
5
 
6
6
  require_relative 'active_job/version'
7
7
  require_relative 'active_job/queue_adapter'
8
-
9
8
  require_relative "active_job/railtie" if defined?(Rails::Railtie)
data/readme.md CHANGED
@@ -30,6 +30,22 @@ Then run it:
30
30
  $ bundle exec ./job-server.rb
31
31
  ```
32
32
 
33
+ ### Configuration
34
+
35
+ ```ruby
36
+ Rails.application.configure do
37
+ config.async_job.backend_for :default, :critical do
38
+ queue Async::Job::Backend::Redis, endpoint: Async::IO::Endpoint.tcp('redis.local')
39
+ end
40
+
41
+ config.async_job.aliases_for :default, :email
42
+
43
+ config.async_job.backend_for :local do
44
+ queue Async::Job::Backend::Inline
45
+ end
46
+ end
47
+ ```
48
+
33
49
  ## Contributing
34
50
 
35
51
  We welcome contributions to this project.
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: async-job-adapter-active_job
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
@@ -37,7 +37,7 @@ cert_chain:
37
37
  Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
38
38
  voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
39
39
  -----END CERTIFICATE-----
40
- date: 2024-02-24 00:00:00.000000000 Z
40
+ date: 2024-02-25 00:00:00.000000000 Z
41
41
  dependencies:
42
42
  - !ruby/object:Gem::Dependency
43
43
  name: async-job
@@ -74,7 +74,10 @@ extensions: []
74
74
  extra_rdoc_files: []
75
75
  files:
76
76
  - lib/async/job/adapter/active_job.rb
77
+ - lib/async/job/adapter/active_job/builder.rb
78
+ - lib/async/job/adapter/active_job/dispatcher.rb
77
79
  - lib/async/job/adapter/active_job/queue_adapter.rb
80
+ - lib/async/job/adapter/active_job/queue_handler.rb
78
81
  - lib/async/job/adapter/active_job/railtie.rb
79
82
  - lib/async/job/adapter/active_job/service.rb
80
83
  - lib/async/job/adapter/active_job/version.rb
metadata.gz.sig CHANGED
Binary file