anway 0.5.1 → 0.5.2
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 +4 -4
- data/README.md +15 -1
- data/lib/anway/client.rb +36 -5
- data/lib/anway/testing.rb +9 -0
- data/lib/anway/version.rb +2 -2
- data/lib/anway.rb +20 -0
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 879b6b41434558306382e3c24155f9fd38bf307af3782a7540fadb7047e6874f
|
|
4
|
+
data.tar.gz: c1daefd209281acc66457927bd76cd5914c1ddabb881e58de993fcb6cdc9652a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e255b3d87fc235bad83961e227598b577588aa8940fb3acce0e499bb8e262a5fb6d070c392013c6e3ca314a747dd0f44e3bf21aa62284bbcadd7c35181a71834
|
|
7
|
+
data.tar.gz: fea336b393f25fee2227dcd9cb6a326df8c847b531e979740978f0001d5d32b0fce2448a9b36455c10775a532b1eb44a4037ea6ce018b0d24e8eec7d6f78cbb6
|
data/README.md
CHANGED
|
@@ -211,6 +211,20 @@ client.subscribe('chat.message', queue: 'realtime', event: 'BroadcastMessage', r
|
|
|
211
211
|
client.unsubscribe('chat.message', queue: 'realtime', event: 'BroadcastMessage')
|
|
212
212
|
```
|
|
213
213
|
|
|
214
|
+
### Bulk publish
|
|
215
|
+
|
|
216
|
+
`Anway.publish_bulk` sends many events with one `PUBLISHB` for each 1,000 events. The server saves all copies of the events of one `PUBLISHB` in one write, so an import, an outbox relay, or a replay is much faster than one `publish` for each event. Use `publish` for one event, such as in a request.
|
|
217
|
+
|
|
218
|
+
```ruby
|
|
219
|
+
results = Anway.publish_bulk(orders.map { |order| { topic: 'order.paid', args: [order.id], id: "order-#{order.id}" } })
|
|
220
|
+
|
|
221
|
+
results.reject { |result| result.error.nil? }.each { |result| Rails.logger.warn("event #{result.event}: #{result.error}") }
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
- Each event is a hash with `topic:` and `args:`, and the options of `publish`: `id:`, `unique_for:`, and `custom:`.
|
|
225
|
+
- The results are `Anway::Client::PublishResult` values (`event`, `jobs`, `duplicate`, `error`), in the order of the events. A refused event, such as a bad topic, has `error` and does not stop the others.
|
|
226
|
+
- `client.publish_bulk(events)` sends one `PUBLISHB`. It takes at most 1,000 events, and more raise `ArgumentError` before the send. A bulk can make at most 10,000 jobs over all subscriptions.
|
|
227
|
+
|
|
214
228
|
[docs/topics.md](docs/topics.md) explains the chat example with three apps, the options, the tests, and problems.
|
|
215
229
|
|
|
216
230
|
## Rails
|
|
@@ -327,7 +341,7 @@ Anway::Testing.events.last['topic']
|
|
|
327
341
|
Anway::Testing.inline!
|
|
328
342
|
```
|
|
329
343
|
|
|
330
|
-
In inline mode, `Anway.publish` runs one copy in each job class of the app that subscribes to the topic.
|
|
344
|
+
In inline mode, `Anway.publish` runs one copy in each job class of the app that subscribes to the topic. `Anway.publish_bulk` works as one `Anway.publish` for each event.
|
|
331
345
|
|
|
332
346
|
`perform_bulk` and `Anway.push_bulk` work as single pushes do: fake mode adds each job to `Anway::Testing.jobs`, and inline mode runs each job. The result is `{}`.
|
|
333
347
|
|
data/lib/anway/client.rb
CHANGED
|
@@ -10,7 +10,8 @@ module Anway
|
|
|
10
10
|
DEFAULT_PORT = 7419
|
|
11
11
|
FETCH_WAIT = 2
|
|
12
12
|
|
|
13
|
-
# The most jobs that one PUSHB takes
|
|
13
|
+
# The most jobs that one PUSHB takes, and the most events that one
|
|
14
|
+
# PUBLISHB takes.
|
|
14
15
|
MAX_BULK = 1000
|
|
15
16
|
|
|
16
17
|
Endpoint = Data.define(:host, :port, :password, :tls)
|
|
@@ -23,6 +24,10 @@ module Anway
|
|
|
23
24
|
# server already had an event with this id.
|
|
24
25
|
Published = Data.define(:event, :jobs, :duplicate)
|
|
25
26
|
|
|
27
|
+
# One result of a PUBLISHB: as Published, and the reason in error when the
|
|
28
|
+
# server refused the event.
|
|
29
|
+
PublishResult = Data.define(:event, :jobs, :duplicate, :error)
|
|
30
|
+
|
|
26
31
|
# A blank URL uses ANWAY_URL, then the local default.
|
|
27
32
|
def initialize(url = nil, pool_size: 8, timeout: 10, tls: nil, wid: nil, labels: [], identity: {})
|
|
28
33
|
@endpoint = parse_url(url || ENV.fetch('ANWAY_URL', nil) || DEFAULT_URL)
|
|
@@ -135,14 +140,33 @@ module Anway
|
|
|
135
140
|
# publish of the same id within unique_for seconds makes no job, and the
|
|
136
141
|
# reply has duplicate true. Returns a Published.
|
|
137
142
|
def publish(topic, args = [], id: nil, unique_for: nil, custom: nil)
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
event = { topic: topic, args: args, id: id, unique_for: unique_for, custom: custom&.transform_keys(&:to_s) }
|
|
141
|
-
data = JSON.parse(call('PUBLISH', event.compact))
|
|
143
|
+
data = JSON.parse(call('PUBLISH', event_payload(topic, args, id: id, unique_for: unique_for, custom: custom)))
|
|
142
144
|
|
|
143
145
|
Published.new(event: data['event'], jobs: data['jobs'], duplicate: data['duplicate'] == true)
|
|
144
146
|
end
|
|
145
147
|
|
|
148
|
+
# Sends up to MAX_BULK events with one PUBLISHB, and the server saves them
|
|
149
|
+
# in one write. Each event is a hash with topic: and args:, and the
|
|
150
|
+
# options of publish (id:, unique_for:, custom:). Returns one
|
|
151
|
+
# PublishResult for each event, in the same order. A refused event, such
|
|
152
|
+
# as a bad topic, has error, and does not stop the others. More than
|
|
153
|
+
# MAX_BULK events raise ArgumentError before the send.
|
|
154
|
+
def publish_bulk(events)
|
|
155
|
+
events = events.to_a
|
|
156
|
+
|
|
157
|
+
raise ArgumentError, "a bulk publish has at most #{MAX_BULK} events, not #{events.size}" if events.size > MAX_BULK
|
|
158
|
+
|
|
159
|
+
return [] if events.empty?
|
|
160
|
+
|
|
161
|
+
payload = events.map do |event|
|
|
162
|
+
event_payload(event.fetch(:topic), event.fetch(:args, []), **event.slice(:id, :unique_for, :custom))
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
JSON.parse(call('PUBLISHB', payload)).map do |data|
|
|
166
|
+
PublishResult.new(event: data['event'], jobs: data['jobs'], duplicate: data['duplicate'] == true, error: data['error'])
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
146
170
|
# Each event of the topic makes one job in queue, with event as its job
|
|
147
171
|
# type. A second call with the same topic, queue, and event sets new retry
|
|
148
172
|
# and reserve_for.
|
|
@@ -199,6 +223,13 @@ module Anway
|
|
|
199
223
|
|
|
200
224
|
private
|
|
201
225
|
|
|
226
|
+
# The argument of PUBLISH, and of each event of PUBLISHB.
|
|
227
|
+
def event_payload(topic, args, id: nil, unique_for: nil, custom: nil)
|
|
228
|
+
Job.validate_args!(args)
|
|
229
|
+
|
|
230
|
+
{ topic: topic, args: args, id: id, unique_for: unique_for, custom: custom&.transform_keys(&:to_s) }.compact
|
|
231
|
+
end
|
|
232
|
+
|
|
202
233
|
def queue_command(action, queues)
|
|
203
234
|
call('QUEUE', "#{action} #{queues.join(' ')}")
|
|
204
235
|
|
data/lib/anway/testing.rb
CHANGED
|
@@ -67,6 +67,15 @@ module Anway
|
|
|
67
67
|
Client::Published.new(event: event_id, jobs: subscriptions.size, duplicate: false)
|
|
68
68
|
end
|
|
69
69
|
|
|
70
|
+
# Publishes each event as a single publish does. No event is refused.
|
|
71
|
+
def publish_bulk(events)
|
|
72
|
+
events.map do |event|
|
|
73
|
+
published = publish(event.fetch(:topic), event.fetch(:args, []), **event.slice(:id, :unique_for, :custom))
|
|
74
|
+
|
|
75
|
+
Client::PublishResult.new(event: published.event, jobs: published.jobs, duplicate: false, error: nil)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
70
79
|
# Runs and removes all fake jobs. Jobs that they push also run.
|
|
71
80
|
def drain
|
|
72
81
|
Executor.call(@jobs.shift) until @jobs.empty?
|
data/lib/anway/version.rb
CHANGED
data/lib/anway.rb
CHANGED
|
@@ -93,6 +93,26 @@ module Anway
|
|
|
93
93
|
published
|
|
94
94
|
end
|
|
95
95
|
|
|
96
|
+
# Sends the events with one PUBLISHB for each Client::MAX_BULK events.
|
|
97
|
+
# Each event is a hash with topic: and args:, and the options of publish.
|
|
98
|
+
# Returns one Client::PublishResult for each event, in the same order.
|
|
99
|
+
# Inside a database transaction, the publish waits for the commit and
|
|
100
|
+
# returns nil.
|
|
101
|
+
def publish_bulk(events)
|
|
102
|
+
events = events.to_a
|
|
103
|
+
testing = const_defined?(:Testing) ? Testing : nil
|
|
104
|
+
|
|
105
|
+
return testing.publish_bulk(events) if testing&.mode
|
|
106
|
+
|
|
107
|
+
results = nil
|
|
108
|
+
|
|
109
|
+
config.push_wrapper.call do
|
|
110
|
+
results = events.each_slice(Client::MAX_BULK).flat_map { |slice| client.publish_bulk(slice) }
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
results
|
|
114
|
+
end
|
|
115
|
+
|
|
96
116
|
def reset!
|
|
97
117
|
@lock.synchronize do
|
|
98
118
|
@client&.close
|