esse-async_indexing 0.0.2 → 0.1.0.rc2

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.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +10 -0
  3. data/Gemfile +2 -1
  4. data/Gemfile.lock +18 -12
  5. data/README.md +50 -41
  6. data/lib/esse/async_indexing/actions/{batch_delete.rb → bulk_delete.rb} +2 -2
  7. data/lib/esse/async_indexing/actions/{batch_import.rb → bulk_import.rb} +1 -1
  8. data/lib/esse/async_indexing/actions/{batch_import_all.rb → bulk_import_all.rb} +1 -1
  9. data/lib/esse/async_indexing/actions/{batch_update.rb → bulk_update.rb} +6 -4
  10. data/lib/esse/async_indexing/actions/bulk_update_lazy_attribute.rb +19 -0
  11. data/lib/esse/async_indexing/actions/delete_document.rb +1 -1
  12. data/lib/esse/async_indexing/actions/index_document.rb +1 -1
  13. data/lib/esse/async_indexing/actions/update_document.rb +1 -1
  14. data/lib/esse/async_indexing/actions/upsert_document.rb +1 -2
  15. data/lib/esse/async_indexing/actions.rb +5 -7
  16. data/lib/esse/async_indexing/active_record_callbacks/lazy_update_attribute.rb +8 -5
  17. data/lib/esse/async_indexing/cli/async_import.rb +27 -18
  18. data/lib/esse/async_indexing/cli/async_update_lazy_attributes.rb +78 -0
  19. data/lib/esse/async_indexing/cli.rb +23 -9
  20. data/lib/esse/async_indexing/config.rb +0 -3
  21. data/lib/esse/async_indexing/configuration.rb +54 -18
  22. data/lib/esse/async_indexing/jobs/bulk_update_lazy_attribute_job.rb +7 -0
  23. data/lib/esse/async_indexing/jobs/import_all_job.rb +1 -1
  24. data/lib/esse/async_indexing/jobs/import_ids_job.rb +42 -0
  25. data/lib/esse/async_indexing/{workers.rb → jobs.rb} +7 -24
  26. data/lib/esse/async_indexing/tasks.rb +82 -0
  27. data/lib/esse/async_indexing/version.rb +1 -1
  28. data/lib/esse/async_indexing.rb +15 -20
  29. data/lib/esse/plugins/async_indexing.rb +18 -59
  30. metadata +19 -32
  31. data/lib/esse/async_indexing/actions/bulk_update_lazy_document_attribute.rb +0 -20
  32. data/lib/esse/async_indexing/actions/import_batch_id.rb +0 -21
  33. data/lib/esse/async_indexing/actions/update_lazy_document_attribute.rb +0 -14
  34. data/lib/esse/async_indexing/adapters/adapter.rb +0 -29
  35. data/lib/esse/async_indexing/adapters/faktory.rb +0 -114
  36. data/lib/esse/async_indexing/adapters/sidekiq.rb +0 -94
  37. data/lib/esse/async_indexing/adapters.rb +0 -12
  38. data/lib/esse/async_indexing/configuration/base.rb +0 -65
  39. data/lib/esse/async_indexing/configuration/faktory.rb +0 -6
  40. data/lib/esse/async_indexing/configuration/sidekiq.rb +0 -12
  41. data/lib/esse/async_indexing/jobs/bulk_update_lazy_document_attribute_job.rb +0 -7
  42. data/lib/esse/async_indexing/jobs/import_batch_id_job.rb +0 -34
  43. data/lib/esse/async_indexing/jobs/update_lazy_document_attribute_job.rb +0 -7
  44. data/lib/esse/async_indexing/testing.rb +0 -79
  45. data/lib/esse/async_indexing/worker.rb +0 -85
  46. data/lib/esse/async_indexing/workers/faktory.rb +0 -28
  47. data/lib/esse/async_indexing/workers/shared_class_methods.rb +0 -26
  48. data/lib/esse/async_indexing/workers/sidekiq.rb +0 -28
@@ -1,20 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Esse::AsyncIndexing::Actions
4
- class BulkUpdateLazyDocumentAttribute
5
- def self.call(index_class_name, repo_name, attr_name, batch_id, options = {})
6
- _index_class, repo_class = CoerceIndexRepository.call(index_class_name, repo_name)
7
- queue = Esse::RedisStorage::Queue.for(repo: repo_class, attribute_name: attr_name)
8
-
9
- kwargs = Esse::HashUtils.deep_transform_keys(options, &:to_sym)
10
-
11
- attr_name = repo_class.lazy_document_attributes.keys.find { |key| key.to_s == attr_name.to_s }
12
- updated_ids = []
13
- queue.fetch(batch_id) do |ids|
14
- updated_ids = ids
15
- repo_class.update_documents_attribute(attr_name, ids, **kwargs)
16
- end
17
- updated_ids
18
- end
19
- end
20
- end
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Esse::AsyncIndexing::Actions
4
- class ImportBatchId
5
- def self.call(index_class_name, repo_name, batch_id, options = {})
6
- _index_class, repo_class = CoerceIndexRepository.call(index_class_name, repo_name)
7
- queue = Esse::RedisStorage::Queue.for(repo: repo_class)
8
-
9
- kwargs = Esse::HashUtils.deep_transform_keys(options, &:to_sym)
10
- kwargs[:context] ||= {}
11
- result = 0
12
- ids_from_batch = []
13
- queue.fetch(batch_id) do |ids|
14
- ids_from_batch = ids
15
- kwargs[:context][:id] = ids
16
- result = repo_class.import(**kwargs)
17
- end
18
- [result, ids_from_batch]
19
- end
20
- end
21
- end
@@ -1,14 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Esse::AsyncIndexing::Actions
4
- class UpdateLazyDocumentAttribute
5
- def self.call(index_class_name, repo_name, attr_name, ids, options = {})
6
- _index_class, repo_class = CoerceIndexRepository.call(index_class_name, repo_name)
7
- kwargs = Esse::HashUtils.deep_transform_keys(options, &:to_sym)
8
-
9
- attr_name = repo_class.lazy_document_attributes.keys.find { |key| key.to_s == attr_name.to_s }
10
- repo_class.update_documents_attribute(attr_name, ids, **kwargs)
11
- ids
12
- end
13
- end
14
- end
@@ -1,29 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Esse::AsyncIndexing
4
- module Adapters
5
- class Adapter
6
- # Push the worker job to the service
7
- # @param _worker [Esse::AsyncIndexing::Worker] An instance of background worker
8
- # @abstract Child classes should override this method
9
- def self.push(_worker)
10
- raise NotImplemented
11
- end
12
-
13
- # Coerces the raw payload into an instance of Worker
14
- # @param payload [Object] the object that should be coerced to a Worker
15
- # @options options [Hash] list of options that will be passed along to the Worker instance
16
- # @return [Esse::AsyncIndexing::Worker] and instance of Esse::AsyncIndexing::Worker
17
- # @abstract Child classes should override this method
18
- def self.coerce_to_worker(payload, **options)
19
- raise NotImplemented
20
- end
21
-
22
- protected
23
-
24
- def normalize_before_push
25
- # noop
26
- end
27
- end
28
- end
29
- end
@@ -1,114 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Esse::AsyncIndexing
4
- module Adapters
5
- # This is a Faktory adapter that converts Esse::AsyncIndexing::Worker object into a faktory readable format
6
- # and then push the jobs into the service.
7
- class Faktory < Adapter
8
- attr_reader :worker, :queue
9
-
10
- def initialize(worker)
11
- @worker = worker
12
- @queue = worker.options.fetch(:queue, "default")
13
-
14
- @payload = worker.payload.merge(
15
- "jobtype" => worker.worker_class,
16
- "queue" => @queue,
17
- "retry" => parse_retry(worker.options[:retry])
18
- )
19
- @payload["created_at"] ||= Time.now.to_f
20
- end
21
-
22
- # Coerces the raw payload into an instance of Worker
23
- # @param payload [Hash] The job as json from redis
24
- # @options options [Hash] list of options that will be passed along to the Worker instance
25
- # @return [Esse::AsyncIndexing::Worker] and instance of Esse::AsyncIndexing::Worker
26
- def self.coerce_to_worker(payload, **options)
27
- raise(Error, "invalid payload") unless payload.is_a?(Hash)
28
- raise(Error, "invalid payload") unless payload["jobtype"].is_a?(String)
29
-
30
- options[:retry] ||= payload["retry"] if payload.key?("retry")
31
- options[:queue] ||= payload["queue"] if payload.key?("queue")
32
-
33
- Esse::AsyncIndexing.worker(payload["jobtype"], **options, service: :faktory).tap do |worker|
34
- worker.with_args(*Array(payload["args"])) if payload.key?("args")
35
- worker.with_job_jid(payload["jid"]) if payload.key?("jid")
36
- worker.created_at(payload["created_at"]) if payload.key?("created_at")
37
- worker.enqueued_at(payload["enqueued_at"]) if payload.key?("enqueued_at")
38
- worker.at(payload["at"]) if payload.key?("at")
39
- end
40
- end
41
-
42
- # Initializes adapter and push job into the faktory service
43
- #
44
- # @param worker [Esse::AsyncIndexing::Worker] An instance of Esse::AsyncIndexing::Worker
45
- # @return [Hash] Job payload
46
- # @see push method for more details
47
- def self.push(worker)
48
- new(worker).push
49
- end
50
-
51
- # Push job to Faktory
52
- # * If job has the 'at' key. Then schedule it
53
- # * Otherwise enqueue for immediate execution
54
- #
55
- # @raise [Esse::AsyncIndexing::Error] raise and error when faktory dependency is not loaded
56
- # @return [Hash] Payload that was sent to server
57
- def push
58
- unless Object.const_defined?(:Faktory)
59
- raise Esse::AsyncIndexing::Error, <<~ERR
60
- Faktory client for ruby is not loaded. You must install and require https://github.com/contribsys/faktory_worker_ruby.
61
- ERR
62
- end
63
- normalize_before_push
64
-
65
- pool = Thread.current[:faktory_via_pool] || ::Faktory.server_pool
66
- ::Faktory.client_middleware.invoke(@payload, pool) do
67
- pool.with do |c|
68
- c.push(@payload)
69
- end
70
- end
71
- @payload
72
- end
73
-
74
- protected
75
-
76
- # Convert worker retry value acording to the Go struct datatype.
77
- #
78
- # * 25 is the default.
79
- # * 0 means the job is completely ephemeral. No matter if it fails or succeeds, it will be discarded.
80
- # * -1 means the job will go straight to the Dead set if it fails, no retries.
81
- def parse_retry(value)
82
- case value
83
- when Numeric then value.to_i
84
- when false then -1
85
- else
86
- 25
87
- end
88
- end
89
-
90
- def parse_time(value)
91
- case value
92
- when Numeric then Time.at(value).to_datetime.rfc3339(9)
93
- when Time then value.to_datetime.rfc3339(9)
94
- when DateTime then value.rfc3339(9)
95
- end
96
- end
97
-
98
- def to_json(value)
99
- MultiJson.dump(value, mode: :compat)
100
- end
101
-
102
- def normalize_before_push
103
- @payload["enqueued_at"] ||= Time.now.to_f
104
- {"created_at" => false, "enqueued_at" => false, "at" => true}.each do |field, past_remove|
105
- # Optimization to enqueue something now that is scheduled to go out now or in the past
106
- if (time = @payload.delete(field)) &&
107
- (!past_remove || (past_remove && time > Time.now.to_f))
108
- @payload[field] = parse_time(time)
109
- end
110
- end
111
- end
112
- end
113
- end
114
- end
@@ -1,94 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Esse::AsyncIndexing
4
- module Adapters
5
- # This is a Sidekiq adapter that converts Esse::AsyncIndexing::Worker object into a sidekiq readable format
6
- # and then push the jobs into the service.
7
- class Sidekiq < Adapter
8
- attr_reader :worker, :queue
9
-
10
- def initialize(worker)
11
- @worker = worker
12
- @queue = worker.options.fetch(:queue, "default")
13
-
14
- @payload = worker.payload.merge(
15
- "class" => worker.worker_class,
16
- "retry" => worker.options.fetch(:retry, true),
17
- "queue" => @queue
18
- )
19
- @payload["created_at"] ||= Time.now.to_f
20
- end
21
-
22
- # Coerces the raw payload into an instance of Worker
23
- # @param payload [Hash] The job as json from redis
24
- # @options options [Hash] list of options that will be passed along to the Worker instance
25
- # @return [Esse::AsyncIndexing::Worker] and instance of Esse::AsyncIndexing::Worker
26
- def self.coerce_to_worker(payload, **options)
27
- raise(Error, "invalid payload") unless payload.is_a?(Hash)
28
- raise(Error, "invalid payload") unless payload["class"].is_a?(String)
29
-
30
- options[:retry] ||= payload["retry"] if payload.key?("retry")
31
- options[:queue] ||= payload["queue"] if payload.key?("queue")
32
-
33
- Esse::AsyncIndexing.worker(payload["class"], **options, service: :sidekiq).tap do |worker|
34
- worker.with_args(*Array(payload["args"])) if payload.key?("args")
35
- worker.with_job_jid(payload["jid"]) if payload.key?("jid")
36
- worker.created_at(payload["created_at"]) if payload.key?("created_at")
37
- worker.enqueued_at(payload["enqueued_at"]) if payload.key?("enqueued_at")
38
- worker.at(payload["at"]) if payload.key?("at")
39
- end
40
- end
41
-
42
- # Initializes adapter and push job into the sidekiq service
43
- #
44
- # @param worker [Esse::AsyncIndexing::Worker] An instance of Esse::AsyncIndexing::Worker
45
- # @return [Hash] Job payload
46
- # @see push method for more details
47
- def self.push(worker)
48
- new(worker).push
49
- end
50
-
51
- # Push sidekiq to the Sidekiq(Redis actually).
52
- # * If job has the 'at' key. Then schedule it
53
- # * Otherwise enqueue for immediate execution
54
- #
55
- # @return [Hash] Payload that was sent to redis
56
- def push
57
- normalize_before_push
58
- # Optimization to enqueue something now that is scheduled to go out now or in the past
59
- if (timestamp = @payload.delete("at")) && (timestamp > Time.now.to_f)
60
- Esse.config.async_indexing.sidekiq.redis_pool.with do |redis|
61
- redis.zadd(scheduled_queue_name, timestamp.to_f.to_s, to_json(@payload))
62
- end
63
- else
64
- Esse.config.async_indexing.sidekiq.redis_pool.with do |redis|
65
- redis.lpush(immediate_queue_name, to_json(@payload))
66
- end
67
- end
68
- @payload
69
- end
70
-
71
- protected
72
-
73
- def namespace
74
- Esse.config.async_indexing.sidekiq.namespace
75
- end
76
-
77
- def scheduled_queue_name
78
- "#{namespace}:schedule"
79
- end
80
-
81
- def immediate_queue_name
82
- "#{namespace}:queue:#{queue}"
83
- end
84
-
85
- def to_json(value)
86
- MultiJson.dump(value, mode: :compat)
87
- end
88
-
89
- def normalize_before_push
90
- @payload["enqueued_at"] = Time.now.to_f
91
- end
92
- end
93
- end
94
- end
@@ -1,12 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Esse
4
- module AsyncIndexing
5
- module Adapters
6
- end
7
- end
8
- end
9
-
10
- require_relative "adapters/adapter"
11
- require_relative "adapters/sidekiq"
12
- require_relative "adapters/faktory"
@@ -1,65 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Esse::AsyncIndexing::Configuration::Base
4
- class << self
5
- private
6
-
7
- def attribute_accessor(field, validator: nil, normalizer: nil, default: nil)
8
- normalizer ||= :"normalize_#{field}"
9
- validator ||= :"validate_#{field}"
10
-
11
- define_method(field) do
12
- unless instance_variable_defined?(:"@#{field}")
13
- return if default.nil?
14
-
15
- send(:"#{field}=", default.respond_to?(:call) ? default.call : default)
16
- end
17
- instance_variable_get(:"@#{field}")
18
- end
19
-
20
- define_method(:"#{field}=") do |value|
21
- value = send(normalizer, field, value) if respond_to?(normalizer, true)
22
- send(validator, field, value) if respond_to?(validator, true)
23
-
24
- instance_variable_set(:"@#{field}", value)
25
- end
26
- end
27
- end
28
-
29
- # A Hash with all workers definitions. The worker class name must be the main hash key
30
- # Example:
31
- # "FaktoryIndexWorker":
32
- # retry: false
33
- # queue: "indexing"
34
- # adapter: "faktory"
35
- # "FaktoryBatchIndexWorker":
36
- # retry: 5
37
- # queue: "batch_index"
38
- # adapter: "faktory"
39
- attribute_accessor :workers, default: {}
40
-
41
- def worker_options(class_name)
42
- class_name = class_name.to_s
43
- if strict? && !workers.key?(class_name)
44
- raise Esse::AsyncIndexing::NotDefinedWorkerError.new(class_name)
45
- end
46
-
47
- workers.fetch(class_name, {})
48
- end
49
-
50
- def strict?
51
- true
52
- end
53
-
54
- protected
55
-
56
- def normalize_workers(_, value)
57
- return unless value.is_a?(Hash)
58
-
59
- hash = Esse::AsyncIndexing::Workers::DEFAULT.values.map { |v| [v, {}] }.to_h
60
- value.each do |class_name, opts|
61
- hash[class_name.to_s] = Esse::HashUtils.deep_transform_keys(opts.to_h, &:to_sym)
62
- end
63
- hash
64
- end
65
- end
@@ -1,6 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Esse::AsyncIndexing
4
- class Configuration::Faktory < Configuration::Base
5
- end
6
- end
@@ -1,12 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Esse::AsyncIndexing
4
- class Configuration::Sidekiq < Configuration::Base
5
- attribute_accessor :redis
6
- attribute_accessor :namespace, default: "sidekiq"
7
-
8
- def redis_pool
9
- @redis_pool ||= Esse::RedisStorage::Pool.new(redis)
10
- end
11
- end
12
- end
@@ -1,7 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Esse::AsyncIndexing::Jobs::BulkUpdateLazyDocumentAttributeJob
4
- def perform(index_class_name, repo_name, attribute_name, batch_id, options = {})
5
- Esse::AsyncIndexing::Actions::BulkUpdateLazyDocumentAttribute.call(index_class_name, repo_name, attribute_name, batch_id, options)
6
- end
7
- end
@@ -1,34 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Esse::AsyncIndexing::Jobs::ImportBatchIdJob
4
- LAZY_ATTR_WORKER = "Esse::AsyncIndexing::Jobs::BulkUpdateLazyDocumentAttributeJob"
5
-
6
- def perform(index_class_name, repo_name, batch_id, options = {})
7
- total, ids = Esse::AsyncIndexing::Actions::ImportBatchId.call(index_class_name, repo_name, batch_id, options)
8
-
9
- options = Esse::HashUtils.deep_transform_keys(options, &:to_s)
10
- return total if total.zero?
11
- return total if lazy_already_imported?(options)
12
- return total unless self.class.respond_to?(:bg_worker_options)
13
-
14
- _index_class, repo_class = Esse::AsyncIndexing::Actions::CoerceIndexRepository.call(index_class_name, repo_name)
15
-
16
- repo_class.lazy_document_attributes.each_key do |attr_name|
17
- queue = Esse::RedisStorage::Queue.for(repo: repo_class, attribute_name: attr_name)
18
- queue.enqueue(id: batch_id, values: ids)
19
- Esse::AsyncIndexing.worker(LAZY_ATTR_WORKER, service: self.class.bg_worker_options[:service])
20
- .with_args(index_class_name, repo_name, attr_name.to_s, batch_id, options)
21
- .push
22
- end
23
- total
24
- end
25
-
26
- protected
27
-
28
- # The `import` action already eager or lazy load the document attributes when some of these options are set.
29
- def lazy_already_imported?(options)
30
- eager = options.delete("eager_include_document_attributes") || false
31
- lazy = options.delete("lazy_update_document_attributes") || false
32
- eager || lazy
33
- end
34
- end
@@ -1,7 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Esse::AsyncIndexing::Jobs::UpdateLazyDocumentAttributeJob
4
- def perform(index_class_name, repo_name, attribute_name, ids, options = {})
5
- Esse::AsyncIndexing::Actions::UpdateLazyDocumentAttribute.call(index_class_name, repo_name, attribute_name, ids, options)
6
- end
7
- end
@@ -1,79 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Esse
4
- module AsyncIndexing
5
- class Testing
6
- class << self
7
- def enable!
8
- Thread.current[:esse_async_indexing_testing] = true
9
- end
10
-
11
- def disable!
12
- Thread.current[:esse_async_indexing_testing] = false
13
- end
14
-
15
- def enabled?
16
- Thread.current[:esse_async_indexing_testing] == true
17
- end
18
-
19
- def disabled?
20
- !enabled?
21
- end
22
- end
23
- end
24
- end
25
- end
26
-
27
- Esse::AsyncIndexing::Testing.disable!
28
-
29
- module Esse::AsyncIndexing::Jobs
30
- class << self
31
- def jobs
32
- @jobs ||= []
33
- end
34
-
35
- def push(job)
36
- jobs.push(job)
37
- end
38
-
39
- def clear
40
- jobs.clear
41
- end
42
-
43
- def size
44
- jobs.size
45
- end
46
-
47
- def jobs_for(service: nil, class_name: nil)
48
- filtered = jobs
49
- if service
50
- filtered = filtered.select { |job| job["service"] == service.to_s }
51
- end
52
- if class_name
53
- filtered = filtered.select { |job| job["__class_name__"] == class_name.to_s }
54
- end
55
- filtered
56
- end
57
- end
58
- end
59
-
60
- module Esse::AsyncIndexing::JobsInterceptorAdapter
61
- def push
62
- return super unless Esse::AsyncIndexing::Testing.enabled?
63
-
64
- normalize_before_push
65
- test_payload = @payload.dup
66
- if @payload["jobtype"]
67
- test_payload["service"] = "faktory"
68
- test_payload["__class_name__"] = @payload["jobtype"]
69
- else
70
- test_payload["service"] = "sidekiq"
71
- test_payload["__class_name__"] = @payload["class"]
72
- end
73
- Esse::AsyncIndexing::Jobs.push(test_payload)
74
- end
75
- end
76
-
77
- Esse::AsyncIndexing::SERVICES.each_value do |adapter|
78
- adapter.prepend(Esse::AsyncIndexing::JobsInterceptorAdapter)
79
- end
@@ -1,85 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Esse::AsyncIndexing
4
- class Worker
5
- attr_reader :options, :payload, :worker_class, :service
6
-
7
- attr_reader :arguments
8
-
9
- def initialize(worker_class, service: nil, **options)
10
- @worker_class = worker_class
11
- @service = service
12
- @options = options
13
- @payload = {}
14
- end
15
-
16
- def self.coerce(service:, payload:, **opts)
17
- Esse::AsyncIndexing::SERVICES.fetch(service).coerce_to_worker(payload, **opts)
18
- end
19
-
20
- %i[created_at enqueued_at].each do |method_name|
21
- define_method method_name do |value|
22
- @payload[method_name.to_s] =
23
- case value
24
- when Numeric then value.to_f
25
- when String then Time.parse(value).to_f
26
- when Time, DateTime then value.to_f
27
- else
28
- raise ArgumentError, format("The %<v>p is not a valid value for %<m>s.", v: value, m: method_name)
29
- end
30
-
31
- self
32
- end
33
- end
34
-
35
- # Adds arguments to the job
36
- # @return self
37
- def with_args(*args)
38
- @payload["args"] = args
39
-
40
- self
41
- end
42
-
43
- # Schedule the time when a job will be executed. Jobs which are scheduled in the past are enqueued for immediate execution.
44
- # @param timestamp [Numeric] timestamp, numeric or something that acts numeric.
45
- # @return self
46
- def in(timestamp)
47
- now = Time.now.to_f
48
- timestamp = Time.parse(timestamp) if timestamp.is_a?(String)
49
- int = timestamp.respond_to?(:strftime) ? timestamp.to_f : now + timestamp.to_f
50
- return self if int <= now
51
-
52
- @payload["at"] = int
53
- @payload["created_at"] = now
54
-
55
- self
56
- end
57
- alias_method :at, :in
58
-
59
- def with_job_jid(jid = nil)
60
- @payload["jid"] ||= jid || Esse::AsyncIndexing.jid
61
-
62
- self
63
- end
64
-
65
- # @return Response of service
66
- # @see Esse::AsyncIndexing::Adapters::** for more details
67
- def push
68
- unless Esse::AsyncIndexing::SERVICES.key?(service)
69
- raise Esse::AsyncIndexing::Error, format("Service %<service>p is not implemented. Please use one of #{Esse::AsyncIndexing::SERVICES.keys.map(&:inspect).join(" or ")}.", service: service)
70
- end
71
- @payload["created_at"] ||= Time.now.to_f
72
- worker_to_push = with_job_jid
73
- Esse::AsyncIndexing::SERVICES[service].push(worker_to_push)
74
- end
75
-
76
- def eql?(other)
77
- return false unless other.is_a?(self.class)
78
-
79
- worker_class == other.worker_class &&
80
- payload == other.payload &&
81
- options == other.options
82
- end
83
- alias_method :==, :eql?
84
- end
85
- end
@@ -1,28 +0,0 @@
1
- # frizen_string_literal: true
2
-
3
- require_relative "shared_class_methods"
4
-
5
- module Esse::AsyncIndexing
6
- module Workers
7
- module Faktory
8
- def self.extended(base)
9
- base.include(::Faktory::Job) if defined?(::Faktory)
10
- base.extend SharedClassMethods
11
- base.extend ClassMethods
12
- end
13
-
14
- module ClassMethods
15
- def service_worker_options
16
- default_queue = Esse.config.async_indexing.faktory.workers.dig(name, :queue)
17
- default_retry = Esse.config.async_indexing.faktory.workers.dig(name, :retry)
18
- default_queue ||= ::Faktory.default_job_options["queue"] if defined?(::Faktory)
19
- default_retry ||= ::Faktory.default_job_options["retry"] if defined?(::Faktory)
20
- {
21
- queue: default_queue || "default",
22
- retry: default_retry || 25
23
- }
24
- end
25
- end
26
- end
27
- end
28
- end
@@ -1,26 +0,0 @@
1
- # frizen_string_literal: true
2
-
3
- module Esse::AsyncIndexing
4
- module Workers
5
- module SharedClassMethods
6
- def perform_async(*args)
7
- build_worker.with_args(*args).push
8
- end
9
-
10
- def perform_in(interval, *args)
11
- build_worker.with_args(*args).at(interval).push
12
- end
13
- alias_method :perform_at, :perform_in
14
-
15
- protected
16
-
17
- def service_worker_options
18
- {}
19
- end
20
-
21
- def build_worker
22
- Esse::AsyncIndexing.worker(name, **service_worker_options.merge(bg_worker_options))
23
- end
24
- end
25
- end
26
- end