active_delivery 1.0.0 → 1.1.0

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: 34afeceddc78be6864aed136f68bc0a0f0eb43c203ef1520260fe94a8c934b39
4
- data.tar.gz: dab4270f8b7a4c5e14b18c3fd36ceb081587425f26a50060191778bab768d688
3
+ metadata.gz: dfc96638e6c019dd1b13f57eef8ab3b9bf2a34df2b58ca7f7ea8ea167886c59e
4
+ data.tar.gz: b50d556edef4a01fc7d1a8af1659a05f99a821584c2d4818418401f3a03350dd
5
5
  SHA512:
6
- metadata.gz: 67992b515155ae977dd2f839448b3fe89d8c1391906e3c20bd425782241378f70d0b933834433a5e30904a7f3a1176c1313cd690267f001258f9584b078f0367
7
- data.tar.gz: c811abf777c5c0c7552749fcedd228e7914bc80ded1a14129f4194097d74049f72e80c229c59549ac09141fed3145ab4c4199706ca29055ce6a405c3c16e13a2
6
+ metadata.gz: 518d226591f5114383c2d138c163b4bac13e62666cce4f7edde7d2df5bca7e770c17576f00fee378b9a8733cc72372960efa2692839a6dc4d274d130787fcb41
7
+ data.tar.gz: 2bd5eed0775fd32d83ca45364d8ecdc4f28c275eb2ffbbcad768ef98d8581b1cd0e66eb72f7e012c9d4dbd0a18e8a72cb40a858f0459614e18a5ee3e24fb0420
data/CHANGELOG.md CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ## 1.1.0 (2023-12-01) ❄️
6
+
7
+ - Support delayed delivery options (e.g, `wait_until`). ([@palkan][])
8
+
5
9
  ## 📬 1.0.0 (2023-08-29)
6
10
 
7
11
  - Add `resolver_pattern` option to specify naming pattern for notifiers without using Procs. ([@palkan][])
@@ -43,6 +47,20 @@
43
47
 
44
48
  - Add `#deliver_via(*lines)` RSpec matcher. ([@palkan][])
45
49
 
50
+ - **BREAKING** The `#resolve_class` method in Line classes now receive a delivery class instead of a name:
51
+
52
+ ```ruby
53
+ # before
54
+ def resolve_class(name)
55
+ name.gsub(/Delivery$/, "Channel").safe_constantize
56
+ end
57
+
58
+ # after
59
+ def resolve_class(name)
60
+ name.to_s.gsub(/Delivery$/, "Channel").safe_constantize
61
+ end
62
+ ```
63
+
46
64
  - Provide ActionMailer-like interface to trigger notifications. ([@palkan][])
47
65
 
48
66
  Now you can send notifications as follows:
data/README.md CHANGED
@@ -113,6 +113,9 @@ PostsDelivery.published(user, post).deliver_later
113
113
  PostsMailer.published(user, post).deliver_later
114
114
  PostsSMSNotifier.published(user, post).notify_later
115
115
 
116
+ # You can also pass options supported by your async executor (such as ActiveJob)
117
+ PostsDelivery.published(user, post).deliver_later(wait_until: 1.day.from_now)
118
+
116
119
  # and whaterver your ActionCableDeliveryLine does
117
120
  # under the hood.
118
121
  ```
@@ -706,7 +709,7 @@ end
706
709
 
707
710
  ### Background jobs / async notifications
708
711
 
709
- To use `#notify_later` you **must** configure an async adapter for Abstract Notifier.
712
+ To use `#notify_later(**delivery_options)` you **must** configure an async adapter for Abstract Notifier.
710
713
 
711
714
  We provide an Active Job adapter out of the box and enable it if Active Job is found.
712
715
 
@@ -718,13 +721,13 @@ class MyAsyncAdapter
718
721
  def initialize(options = {})
719
722
  end
720
723
 
721
- # `enqueue` method accepts notifier class, action name and notification parameters
722
- def enqueue(notifier_class, action_name, params:, args:, kwargs:)
724
+ # `enqueue_delivery` method accepts notifier class, action name and notification parameters
725
+ def enqueue_delivery(delivery, **options)
723
726
  # <Your implementation here>
724
727
  # To trigger the notification delivery, you can use the following snippet:
725
728
  #
726
729
  # AbstractNotifier::NotificationDelivery.new(
727
- # notifier_class.constantize, action_name, params:, args:, kwargs:
730
+ # delivery.notifier_class, delivery.action_name, **delivery.delivery_params
728
731
  # ).notify_now
729
732
  end
730
733
  end
@@ -11,15 +11,24 @@ module AbstractNotifier
11
11
 
12
12
  DEFAULT_QUEUE = "notifiers"
13
13
 
14
- attr_reader :job
14
+ attr_reader :job, :queue
15
15
 
16
16
  def initialize(queue: DEFAULT_QUEUE, job: DeliveryJob)
17
- @job = job.set(queue: queue)
17
+ @job = job
18
+ @queue = queue
18
19
  end
19
20
 
20
21
  def enqueue(...)
21
- job.perform_later(...)
22
+ job.set(queue: queue).perform_later(...)
22
23
  end; respond_to?(:ruby2_keywords, true) && (ruby2_keywords :enqueue)
24
+
25
+ def enqueue_delivery(delivery, **opts)
26
+ job.set(queue: queue, **opts).perform_later(
27
+ delivery.notifier_class.name,
28
+ delivery.action_name,
29
+ **delivery.delivery_params
30
+ )
31
+ end
23
32
  end
24
33
  end
25
34
  end
@@ -0,0 +1,223 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AbstractNotifier
4
+ # NotificationDelivery payload wrapper which contains
5
+ # information about the current notifier class
6
+ # and knows how to trigger the delivery
7
+ class NotificationDelivery
8
+ attr_reader :action_name, :notifier_class
9
+
10
+ def initialize(notifier_class, action_name, params: {}, args: [], kwargs: {})
11
+ @notifier_class = notifier_class
12
+ @action_name = action_name
13
+ @params = params
14
+ @args = args
15
+ @kwargs = kwargs
16
+ end
17
+
18
+ def processed
19
+ return @processed if instance_variable_defined?(:@processed)
20
+
21
+ @processed = notifier.process_action(action_name, *args, **kwargs) || Notification.new(nil)
22
+ end
23
+
24
+ alias_method :notification, :processed
25
+
26
+ def notify_later(**opts)
27
+ if notifier_class.async_adapter.respond_to?(:enqueue_delivery)
28
+ notifier_class.async_adapter.enqueue_delivery(self, **opts)
29
+ else
30
+ notifier_class.async_adapter.enqueue(notifier_class.name, action_name, params: params, args: args, kwargs: kwargs)
31
+ end
32
+ end
33
+
34
+ def notify_now
35
+ return unless notification.payload
36
+
37
+ notifier.deliver!(notification)
38
+ end
39
+
40
+ def delivery_params ; {params: params, args: args, kwargs: kwargs}; end
41
+
42
+ private
43
+
44
+ attr_reader :params, :args, :kwargs
45
+
46
+ def notifier
47
+ @notifier ||= notifier_class.new(action_name, **params)
48
+ end
49
+ end
50
+
51
+ # Notification object contains the compiled payload to be delivered
52
+ class Notification
53
+ attr_reader :payload
54
+
55
+ def initialize(payload)
56
+ @payload = payload
57
+ end
58
+ end
59
+
60
+ # Base class for notifiers
61
+ class Base
62
+ class ParamsProxy
63
+ attr_reader :notifier_class, :params
64
+
65
+ def initialize(notifier_class, params)
66
+ @notifier_class = notifier_class
67
+ @params = params
68
+ end
69
+
70
+ # rubocop:disable Style/MethodMissingSuper
71
+ def method_missing(method_name, *args, **kwargs)
72
+ NotificationDelivery.new(notifier_class, method_name, params: params, args: args, kwargs: kwargs)
73
+ end
74
+ # rubocop:enable Style/MethodMissingSuper
75
+
76
+ def respond_to_missing?(*args)
77
+ notifier_class.respond_to_missing?(*args)
78
+ end
79
+ end
80
+
81
+ class << self
82
+ attr_writer :driver
83
+
84
+ def driver
85
+ return @driver if instance_variable_defined?(:@driver)
86
+
87
+ @driver =
88
+ if superclass.respond_to?(:driver)
89
+ superclass.driver
90
+ else
91
+ raise "Driver not found for #{name}. " \
92
+ "Please, specify driver via `self.driver = MyDriver`"
93
+ end
94
+ end
95
+
96
+ def async_adapter=(args)
97
+ adapter, options = Array(args)
98
+ @async_adapter = AsyncAdapters.lookup(adapter, options)
99
+ end
100
+
101
+ def async_adapter
102
+ return @async_adapter if instance_variable_defined?(:@async_adapter)
103
+
104
+ @async_adapter =
105
+ if superclass.respond_to?(:async_adapter)
106
+ superclass.async_adapter
107
+ else
108
+ AbstractNotifier.async_adapter
109
+ end
110
+ end
111
+
112
+ def default(method_name = nil, **hargs, &block)
113
+ return @defaults_generator = block if block
114
+
115
+ return @defaults_generator = proc { send(method_name) } unless method_name.nil?
116
+
117
+ @default_params =
118
+ if superclass.respond_to?(:default_params)
119
+ superclass.default_params.merge(hargs).freeze
120
+ else
121
+ hargs.freeze
122
+ end
123
+ end
124
+
125
+ def defaults_generator
126
+ return @defaults_generator if instance_variable_defined?(:@defaults_generator)
127
+
128
+ @defaults_generator =
129
+ if superclass.respond_to?(:defaults_generator)
130
+ superclass.defaults_generator
131
+ end
132
+ end
133
+
134
+ def default_params
135
+ return @default_params if instance_variable_defined?(:@default_params)
136
+
137
+ @default_params =
138
+ if superclass.respond_to?(:default_params)
139
+ superclass.default_params.dup
140
+ else
141
+ {}
142
+ end
143
+ end
144
+
145
+ def method_missing(method_name, *args, **kwargs)
146
+ if action_methods.include?(method_name.to_s)
147
+ NotificationDelivery.new(self, method_name, args: args, kwargs: kwargs)
148
+ else
149
+ super
150
+ end
151
+ end
152
+
153
+ def with(params)
154
+ ParamsProxy.new(self, params)
155
+ end
156
+
157
+ def respond_to_missing?(method_name, _include_private = false)
158
+ action_methods.include?(method_name.to_s) || super
159
+ end
160
+
161
+ # See https://github.com/rails/rails/blob/b13a5cb83ea00d6a3d71320fd276ca21049c2544/actionpack/lib/abstract_controller/base.rb#L74
162
+ def action_methods
163
+ @action_methods ||= begin
164
+ # All public instance methods of this class, including ancestors
165
+ methods = (public_instance_methods(true) -
166
+ # Except for public instance methods of Base and its ancestors
167
+ Base.public_instance_methods(true) +
168
+ # Be sure to include shadowed public instance methods of this class
169
+ public_instance_methods(false))
170
+
171
+ methods.map!(&:to_s)
172
+
173
+ methods.to_set
174
+ end
175
+ end
176
+ end
177
+
178
+ attr_reader :params, :notification_name
179
+
180
+ def initialize(notification_name, **params)
181
+ @notification_name = notification_name
182
+ @params = params.freeze
183
+ end
184
+
185
+ def process_action(...)
186
+ public_send(...)
187
+ end; respond_to?(:ruby2_keywords, true) && (ruby2_keywords :process_action)
188
+
189
+ def deliver!(notification)
190
+ self.class.driver.call(notification.payload)
191
+ end
192
+
193
+ def notification(**payload)
194
+ merge_defaults!(payload)
195
+
196
+ payload[:body] = implicit_payload_body unless payload.key?(:body)
197
+
198
+ raise ArgumentError, "Notification body must be present" if
199
+ payload[:body].nil? || payload[:body].empty?
200
+
201
+ @notification = Notification.new(payload)
202
+ end
203
+
204
+ private
205
+
206
+ def implicit_payload_body
207
+ # no-op — override to provide custom logic
208
+ end
209
+
210
+ def merge_defaults!(payload)
211
+ defaults =
212
+ if self.class.defaults_generator
213
+ instance_exec(&self.class.defaults_generator)
214
+ else
215
+ self.class.default_params
216
+ end
217
+
218
+ defaults.each do |k, v|
219
+ payload[k] = v unless payload.key?(k)
220
+ end
221
+ end
222
+ end
223
+ end
@@ -12,9 +12,9 @@ module ActiveDelivery
12
12
  @metadata = metadata.freeze
13
13
  end
14
14
 
15
- def deliver_later ; owner.perform_notify(self); end
15
+ def deliver_later(**opts) ; owner.perform_notify(self, enqueue_options: opts); end
16
16
 
17
- def deliver_now ; owner.perform_notify(self, sync: true); end
17
+ def deliver_now(**opts) ; owner.perform_notify(self, sync: true); end
18
18
 
19
19
  def delivery_class ; owner.class; end
20
20
  end
@@ -216,22 +216,23 @@ module ActiveDelivery
216
216
 
217
217
  protected
218
218
 
219
- def perform_notify(delivery, sync: false)
219
+ def perform_notify(delivery, sync: false, enqueue_options: {})
220
220
  delivery_lines.each do |type, line|
221
221
  next unless line.notify?(delivery.notification)
222
222
 
223
- notify_line(type, line, delivery, sync: sync)
223
+ notify_line(type, line, delivery, sync: sync, enqueue_options: enqueue_options)
224
224
  end
225
225
  end
226
226
 
227
227
  private
228
228
 
229
- def notify_line(type, line, delivery, sync:)
229
+ def notify_line(type, line, delivery, sync:, enqueue_options:)
230
230
  line.notify(
231
231
  delivery.notification,
232
232
  *delivery.params,
233
233
  params: params,
234
234
  sync: sync,
235
+ enqueue_options: enqueue_options,
235
236
  **delivery.options
236
237
  )
237
238
  true
@@ -37,9 +37,21 @@ module ActiveDelivery
37
37
  def notify_later(handler, mid, *__rest__, &__block__)
38
38
  end; respond_to?(:ruby2_keywords, true) && (ruby2_keywords :notify_later)
39
39
 
40
- def notify(mid, *args, params:, sync:, **kwargs)
40
+ def notify_later_with_options(handler, enqueue_options, mid, *__rest__, &__block__)
41
+ notify_later(handler, mid, *__rest__, &__block__)
42
+ end; respond_to?(:ruby2_keywords, true) && (ruby2_keywords :notify_later_with_options)
43
+
44
+ def notify(mid, *args, params:, sync:, enqueue_options:, **kwargs)
41
45
  clazz = params.empty? ? handler_class : handler_class.with(**params)
42
- sync ? notify_now(clazz, mid, *args, **kwargs) : notify_later(clazz, mid, *args, **kwargs)
46
+ if sync
47
+ return notify_now(clazz, mid, *args, **kwargs)
48
+ end
49
+
50
+ if enqueue_options.empty?
51
+ notify_later(clazz, mid, *args, **kwargs)
52
+ else
53
+ notify_later_with_options(clazz, enqueue_options, mid, *args, **kwargs)
54
+ end
43
55
  end
44
56
 
45
57
  def handler_class
@@ -19,6 +19,10 @@ module ActiveDelivery
19
19
  def notify_later(mailer, mid, *__rest__, &__block__)
20
20
  mailer.public_send(mid, *__rest__, &__block__).deliver_later
21
21
  end; respond_to?(:ruby2_keywords, true) && (ruby2_keywords :notify_later)
22
+
23
+ def notify_later_with_options(mailer, enqueue_options, mid, *__rest__, &__block__)
24
+ mailer.public_send(mid, *__rest__, &__block__).deliver_later(**enqueue_options)
25
+ end; respond_to?(:ruby2_keywords, true) && (ruby2_keywords :notify_later_with_options)
22
26
  end
23
27
 
24
28
  ActiveDelivery::Base.register_line :mailer, Mailer, resolver: Mailer::DEFAULT_RESOLVER
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AbstractNotifier
4
+ module AsyncAdapters
5
+ class ActiveJob
6
+ class DeliveryJob < ::ActiveJob::Base
7
+ def perform(notifier_class, ...)
8
+ AbstractNotifier::NotificationDelivery.new(notifier_class.constantize, ...).notify_now
9
+ end
10
+ end
11
+
12
+ DEFAULT_QUEUE = "notifiers"
13
+
14
+ attr_reader :job, :queue
15
+
16
+ def initialize(queue: DEFAULT_QUEUE, job: DeliveryJob)
17
+ @job = job
18
+ @queue = queue
19
+ end
20
+
21
+ def enqueue(...)
22
+ job.set(queue: queue).perform_later(...)
23
+ end
24
+
25
+ def enqueue_delivery(delivery, **opts)
26
+ job.set(queue: queue, **opts).perform_later(
27
+ delivery.notifier_class.name,
28
+ delivery.action_name,
29
+ **delivery.delivery_params
30
+ )
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ AbstractNotifier.async_adapter ||= :active_job
@@ -5,10 +5,10 @@ module AbstractNotifier
5
5
  # information about the current notifier class
6
6
  # and knows how to trigger the delivery
7
7
  class NotificationDelivery
8
- attr_reader :action_name
8
+ attr_reader :action_name, :notifier_class
9
9
 
10
- def initialize(owner_class, action_name, params: {}, args: [], kwargs: {})
11
- @owner_class = owner_class
10
+ def initialize(notifier_class, action_name, params: {}, args: [], kwargs: {})
11
+ @notifier_class = notifier_class
12
12
  @action_name = action_name
13
13
  @params = params
14
14
  @args = args
@@ -23,8 +23,12 @@ module AbstractNotifier
23
23
 
24
24
  alias_method :notification, :processed
25
25
 
26
- def notify_later
27
- owner_class.async_adapter.enqueue(owner_class.name, action_name, params: params, args: args, kwargs: kwargs)
26
+ def notify_later(**opts)
27
+ if notifier_class.async_adapter.respond_to?(:enqueue_delivery)
28
+ notifier_class.async_adapter.enqueue_delivery(self, **opts)
29
+ else
30
+ notifier_class.async_adapter.enqueue(notifier_class.name, action_name, params: params, args: args, kwargs: kwargs)
31
+ end
28
32
  end
29
33
 
30
34
  def notify_now
@@ -33,12 +37,14 @@ module AbstractNotifier
33
37
  notifier.deliver!(notification)
34
38
  end
35
39
 
40
+ def delivery_params ; {params: params, args: args, kwargs: kwargs}; end
41
+
36
42
  private
37
43
 
38
- attr_reader :owner_class, :params, :args, :kwargs
44
+ attr_reader :params, :args, :kwargs
39
45
 
40
46
  def notifier
41
- @notifier ||= owner_class.new(action_name, **params)
47
+ @notifier ||= notifier_class.new(action_name, **params)
42
48
  end
43
49
  end
44
50
 
@@ -178,7 +184,7 @@ module AbstractNotifier
178
184
 
179
185
  def process_action(...)
180
186
  public_send(...)
181
- end; respond_to?(:ruby2_keywords, true) && (ruby2_keywords :process_action)
187
+ end
182
188
 
183
189
  def deliver!(notification)
184
190
  self.class.driver.call(notification.payload)
@@ -12,9 +12,9 @@ module ActiveDelivery
12
12
  @metadata = metadata.freeze
13
13
  end
14
14
 
15
- def deliver_later = owner.perform_notify(self)
15
+ def deliver_later(**opts) = owner.perform_notify(self, enqueue_options: opts)
16
16
 
17
- def deliver_now = owner.perform_notify(self, sync: true)
17
+ def deliver_now(**opts) = owner.perform_notify(self, sync: true)
18
18
 
19
19
  def delivery_class = owner.class
20
20
  end
@@ -216,22 +216,23 @@ module ActiveDelivery
216
216
 
217
217
  protected
218
218
 
219
- def perform_notify(delivery, sync: false)
219
+ def perform_notify(delivery, sync: false, enqueue_options: {})
220
220
  delivery_lines.each do |type, line|
221
221
  next unless line.notify?(delivery.notification)
222
222
 
223
- notify_line(type, line, delivery, sync: sync)
223
+ notify_line(type, line, delivery, sync: sync, enqueue_options: enqueue_options)
224
224
  end
225
225
  end
226
226
 
227
227
  private
228
228
 
229
- def notify_line(type, line, delivery, sync:)
229
+ def notify_line(type, line, delivery, sync:, enqueue_options:)
230
230
  line.notify(
231
231
  delivery.notification,
232
232
  *delivery.params,
233
233
  params: params,
234
234
  sync: sync,
235
+ enqueue_options: enqueue_options,
235
236
  **delivery.options
236
237
  )
237
238
  true
@@ -37,9 +37,21 @@ module ActiveDelivery
37
37
  def notify_later(handler, mid, ...)
38
38
  end
39
39
 
40
- def notify(mid, *args, params:, sync:, **kwargs)
40
+ def notify_later_with_options(handler, enqueue_options, mid, ...)
41
+ notify_later(handler, mid, ...)
42
+ end
43
+
44
+ def notify(mid, *args, params:, sync:, enqueue_options:, **kwargs)
41
45
  clazz = params.empty? ? handler_class : handler_class.with(**params)
42
- sync ? notify_now(clazz, mid, *args, **kwargs) : notify_later(clazz, mid, *args, **kwargs)
46
+ if sync
47
+ return notify_now(clazz, mid, *args, **kwargs)
48
+ end
49
+
50
+ if enqueue_options.empty?
51
+ notify_later(clazz, mid, *args, **kwargs)
52
+ else
53
+ notify_later_with_options(clazz, enqueue_options, mid, *args, **kwargs)
54
+ end
43
55
  end
44
56
 
45
57
  def handler_class
@@ -11,14 +11,23 @@ module AbstractNotifier
11
11
 
12
12
  DEFAULT_QUEUE = "notifiers"
13
13
 
14
- attr_reader :job
14
+ attr_reader :job, :queue
15
15
 
16
16
  def initialize(queue: DEFAULT_QUEUE, job: DeliveryJob)
17
- @job = job.set(queue: queue)
17
+ @job = job
18
+ @queue = queue
18
19
  end
19
20
 
20
21
  def enqueue(...)
21
- job.perform_later(...)
22
+ job.set(queue:).perform_later(...)
23
+ end
24
+
25
+ def enqueue_delivery(delivery, **opts)
26
+ job.set(queue:, **opts).perform_later(
27
+ delivery.notifier_class.name,
28
+ delivery.action_name,
29
+ **delivery.delivery_params
30
+ )
22
31
  end
23
32
  end
24
33
  end
@@ -5,10 +5,10 @@ module AbstractNotifier
5
5
  # information about the current notifier class
6
6
  # and knows how to trigger the delivery
7
7
  class NotificationDelivery
8
- attr_reader :action_name
8
+ attr_reader :action_name, :notifier_class
9
9
 
10
- def initialize(owner_class, action_name, params: {}, args: [], kwargs: {})
11
- @owner_class = owner_class
10
+ def initialize(notifier_class, action_name, params: {}, args: [], kwargs: {})
11
+ @notifier_class = notifier_class
12
12
  @action_name = action_name
13
13
  @params = params
14
14
  @args = args
@@ -23,8 +23,12 @@ module AbstractNotifier
23
23
 
24
24
  alias_method :notification, :processed
25
25
 
26
- def notify_later
27
- owner_class.async_adapter.enqueue(owner_class.name, action_name, params:, args:, kwargs:)
26
+ def notify_later(**opts)
27
+ if notifier_class.async_adapter.respond_to?(:enqueue_delivery)
28
+ notifier_class.async_adapter.enqueue_delivery(self, **opts)
29
+ else
30
+ notifier_class.async_adapter.enqueue(notifier_class.name, action_name, params:, args:, kwargs:)
31
+ end
28
32
  end
29
33
 
30
34
  def notify_now
@@ -33,12 +37,14 @@ module AbstractNotifier
33
37
  notifier.deliver!(notification)
34
38
  end
35
39
 
40
+ def delivery_params = {params:, args:, kwargs:}
41
+
36
42
  private
37
43
 
38
- attr_reader :owner_class, :params, :args, :kwargs
44
+ attr_reader :params, :args, :kwargs
39
45
 
40
46
  def notifier
41
- @notifier ||= owner_class.new(action_name, **params)
47
+ @notifier ||= notifier_class.new(action_name, **params)
42
48
  end
43
49
  end
44
50
 
@@ -36,12 +36,12 @@ module AbstractNotifier
36
36
  Driver.send_notification payload.merge(via: notifier.class)
37
37
  end
38
38
 
39
- def notify_later
39
+ def notify_later(**opts)
40
40
  return super unless AbstractNotifier.test?
41
41
 
42
42
  payload = notification.payload
43
43
 
44
- Driver.enqueue_notification payload.merge(via: notifier.class)
44
+ Driver.enqueue_notification payload.merge(via: notifier.class, **opts)
45
45
  end
46
46
  end
47
47
  end
@@ -12,9 +12,9 @@ module ActiveDelivery
12
12
  @metadata = metadata.freeze
13
13
  end
14
14
 
15
- def deliver_later = owner.perform_notify(self)
15
+ def deliver_later(**opts) = owner.perform_notify(self, enqueue_options: opts)
16
16
 
17
- def deliver_now = owner.perform_notify(self, sync: true)
17
+ def deliver_now(**opts) = owner.perform_notify(self, sync: true)
18
18
 
19
19
  def delivery_class = owner.class
20
20
  end
@@ -216,22 +216,23 @@ module ActiveDelivery
216
216
 
217
217
  protected
218
218
 
219
- def perform_notify(delivery, sync: false)
219
+ def perform_notify(delivery, sync: false, enqueue_options: {})
220
220
  delivery_lines.each do |type, line|
221
221
  next unless line.notify?(delivery.notification)
222
222
 
223
- notify_line(type, line, delivery, sync:)
223
+ notify_line(type, line, delivery, sync:, enqueue_options:)
224
224
  end
225
225
  end
226
226
 
227
227
  private
228
228
 
229
- def notify_line(type, line, delivery, sync:)
229
+ def notify_line(type, line, delivery, sync:, enqueue_options:)
230
230
  line.notify(
231
231
  delivery.notification,
232
232
  *delivery.params,
233
233
  params:,
234
234
  sync:,
235
+ enqueue_options:,
235
236
  **delivery.options
236
237
  )
237
238
  true
@@ -37,9 +37,21 @@ module ActiveDelivery
37
37
  def notify_later(handler, mid, ...)
38
38
  end
39
39
 
40
- def notify(mid, *args, params:, sync:, **kwargs)
40
+ def notify_later_with_options(handler, enqueue_options, mid, ...)
41
+ notify_later(handler, mid, ...)
42
+ end
43
+
44
+ def notify(mid, *args, params:, sync:, enqueue_options:, **kwargs)
41
45
  clazz = params.empty? ? handler_class : handler_class.with(**params)
42
- sync ? notify_now(clazz, mid, *args, **kwargs) : notify_later(clazz, mid, *args, **kwargs)
46
+ if sync
47
+ return notify_now(clazz, mid, *args, **kwargs)
48
+ end
49
+
50
+ if enqueue_options.empty?
51
+ notify_later(clazz, mid, *args, **kwargs)
52
+ else
53
+ notify_later_with_options(clazz, enqueue_options, mid, *args, **kwargs)
54
+ end
43
55
  end
44
56
 
45
57
  def handler_class
@@ -19,6 +19,10 @@ module ActiveDelivery
19
19
  def notify_later(mailer, mid, ...)
20
20
  mailer.public_send(mid, ...).deliver_later
21
21
  end
22
+
23
+ def notify_later_with_options(mailer, enqueue_options, mid, ...)
24
+ mailer.public_send(mid, ...).deliver_later(**enqueue_options)
25
+ end
22
26
  end
23
27
 
24
28
  ActiveDelivery::Base.register_line :mailer, Mailer, resolver: Mailer::DEFAULT_RESOLVER
@@ -38,6 +38,10 @@ module ActiveDelivery
38
38
  handler.public_send(mid, *args).notify_later
39
39
  end
40
40
 
41
+ def notify_later_with_options(handler, enqueue_options, mid, *args)
42
+ handler.public_send(mid, *args).notify_later(**enqueue_options)
43
+ end
44
+
41
45
  private
42
46
 
43
47
  attr_reader :resolver
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveDelivery
4
- VERSION = "1.0.0"
4
+ VERSION = "1.1.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_delivery
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vladimir Dementyev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-08-29 00:00:00.000000000 Z
11
+ date: 2023-12-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -94,11 +94,13 @@ files:
94
94
  - bin/console
95
95
  - bin/setup
96
96
  - lib/.rbnext/3.0/abstract_notifier/async_adapters/active_job.rb
97
+ - lib/.rbnext/3.0/abstract_notifier/base.rb
97
98
  - lib/.rbnext/3.0/active_delivery/base.rb
98
99
  - lib/.rbnext/3.0/active_delivery/callbacks.rb
99
100
  - lib/.rbnext/3.0/active_delivery/lines/base.rb
100
101
  - lib/.rbnext/3.0/active_delivery/lines/mailer.rb
101
102
  - lib/.rbnext/3.0/active_delivery/testing.rb
103
+ - lib/.rbnext/3.1/abstract_notifier/async_adapters/active_job.rb
102
104
  - lib/.rbnext/3.1/abstract_notifier/base.rb
103
105
  - lib/.rbnext/3.1/active_delivery/base.rb
104
106
  - lib/.rbnext/3.1/active_delivery/lines/base.rb
@@ -146,7 +148,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
146
148
  - !ruby/object:Gem::Version
147
149
  version: '0'
148
150
  requirements: []
149
- rubygems_version: 3.4.8
151
+ rubygems_version: 3.4.20
150
152
  signing_key:
151
153
  specification_version: 4
152
154
  summary: Ruby and Rails framework for managing all types of notifications in one place