rocketjob 6.3.2 → 7.0.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 +4 -4
- data/README.md +38 -316
- data/bin/rocketjob_batch_perf +1 -1
- data/lib/rocket_job/batch/categories.rb +25 -25
- data/lib/rocket_job/batch/io.rb +21 -15
- data/lib/rocket_job/batch/logger.rb +2 -2
- data/lib/rocket_job/batch/model.rb +2 -2
- data/lib/rocket_job/batch/performance.rb +1 -1
- data/lib/rocket_job/batch/statistics.rb +9 -2
- data/lib/rocket_job/batch/throttle.rb +7 -2
- data/lib/rocket_job/batch/throttle_running_workers.rb +5 -1
- data/lib/rocket_job/batch/throttle_windows.rb +4 -2
- data/lib/rocket_job/batch/worker.rb +51 -11
- data/lib/rocket_job/config.rb +6 -1
- data/lib/rocket_job/dirmon_entry.rb +6 -4
- data/lib/rocket_job/event.rb +84 -4
- data/lib/rocket_job/extensions/mongo/logging.rb +1 -0
- data/lib/rocket_job/extensions/mongoid/clients/options.rb +3 -3
- data/lib/rocket_job/extensions/mongoid/contextual/mongo.rb +3 -4
- data/lib/rocket_job/extensions/mongoid/factory.rb +2 -2
- data/lib/rocket_job/extensions/psych/yaml_tree.rb +8 -4
- data/lib/rocket_job/extensions/rocket_job_adapter.rb +1 -1
- data/lib/rocket_job/jobs/active_job.rb +1 -1
- data/lib/rocket_job/jobs/dirmon_job.rb +3 -1
- data/lib/rocket_job/jobs/on_demand_batch_job.rb +1 -1
- data/lib/rocket_job/jobs/upload_file_job.rb +8 -5
- data/lib/rocket_job/lookup_collection.rb +2 -2
- data/lib/rocket_job/performance.rb +1 -1
- data/lib/rocket_job/plugins/cron.rb +6 -3
- data/lib/rocket_job/plugins/document.rb +0 -2
- data/lib/rocket_job/plugins/job/logger.rb +2 -2
- data/lib/rocket_job/plugins/job/model.rb +1 -1
- data/lib/rocket_job/plugins/job/persistence.rb +2 -2
- data/lib/rocket_job/plugins/job/throttle.rb +14 -2
- data/lib/rocket_job/plugins/job/throttle_running_jobs.rb +4 -1
- data/lib/rocket_job/plugins/job/worker.rb +5 -2
- data/lib/rocket_job/plugins/retry.rb +1 -1
- data/lib/rocket_job/plugins/throttle_dependent_jobs.rb +7 -2
- data/lib/rocket_job/plugins/transaction.rb +2 -2
- data/lib/rocket_job/sliced/input.rb +17 -12
- data/lib/rocket_job/sliced/slice.rb +3 -3
- data/lib/rocket_job/sliced/slices.rb +3 -6
- data/lib/rocket_job/supervisor.rb +2 -2
- data/lib/rocket_job/thread_worker.rb +3 -3
- data/lib/rocket_job/throttle_definition.rb +19 -2
- data/lib/rocket_job/throttle_definitions.rb +14 -9
- data/lib/rocket_job/version.rb +1 -1
- data/lib/rocket_job/worker.rb +77 -28
- data/lib/rocketjob.rb +1 -2
- metadata +33 -27
- data/lib/rocket_job/ractor_worker.rb +0 -42
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7cf0e18a83d97aadac0d2741a399bcb55fa33884ccf2660836a5a3cfd946f772
|
|
4
|
+
data.tar.gz: d95563d0c77495dcdb3498dccf7cfc22fefee78bd22df244b823fc3939ef5373
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8f379b7890ddce715719616c311b501a916bc081bfd8eaba5055fa124badd58084985d9f38da0c081a8b5bcff3c67108ba3ea5ca52d8f2a8d7a92aa7297c94e8
|
|
7
|
+
data.tar.gz: db4e047d9c07faed020db569f7268fc0dea981ede5792ec40b7636718b118514fc6edc8d08b961d3dfe1d4ecadada40f548dde490ed4ede5326bbcb12ef5bedd
|
data/README.md
CHANGED
|
@@ -1,344 +1,66 @@
|
|
|
1
1
|
# Rocket Job
|
|
2
|
-
[](https://rubygems.org/gems/rocketjob) [](https://rubygems.org/gems/rocketjob) [](http://opensource.org/licenses/Apache-2.0) 
|
|
2
|
+
[](https://rubygems.org/gems/rocketjob) [](https://rubygems.org/gems/rocketjob) [](http://opensource.org/licenses/Apache-2.0) 
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
**Process millions of records across thousands of workers.**
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
Rocket Job is a distributed, priority-based, MongoDB-backed batch processing system for Ruby. Run
|
|
7
|
+
conventional background jobs, or split a single job's input into slices and process it concurrently
|
|
8
|
+
across thousands of workers, spilling from memory to disk so very large files never fall over.
|
|
7
9
|
|
|
8
|
-
|
|
10
|
+
Full documentation is at **[rocketjob.reidmorrison.com](https://rocketjob.reidmorrison.com/)**.
|
|
11
|
+
|
|
12
|
+

|
|
9
13
|
|
|
10
14
|
## Documentation
|
|
11
15
|
|
|
12
|
-
* [
|
|
13
|
-
* [
|
|
16
|
+
* [Introduction](https://rocketjob.reidmorrison.com/) — what Rocket Job is and why it exists
|
|
17
|
+
* [Installation](https://rocketjob.reidmorrison.com/installation.html)
|
|
18
|
+
* [Programmer's Guide](https://rocketjob.reidmorrison.com/guide.html) — simple jobs
|
|
19
|
+
* [Batch Guide](https://rocketjob.reidmorrison.com/batch.html) — parallel batch jobs
|
|
20
|
+
* [Included Jobs](https://rocketjob.reidmorrison.com/jobs.html) and [Directory Monitor](https://rocketjob.reidmorrison.com/dirmon.html)
|
|
21
|
+
* [Events](https://rocketjob.reidmorrison.com/events.html)
|
|
22
|
+
* [Web UI (Mission Control)](https://rocketjob.reidmorrison.com/mission_control.html)
|
|
23
|
+
* [Deployment](https://rocketjob.reidmorrison.com/deployment.html)
|
|
24
|
+
* [Architecture and Internals](https://rocketjob.reidmorrison.com/architecture.html)
|
|
25
|
+
* [API Reference](https://www.rubydoc.info/gems/rocketjob/)
|
|
14
26
|
|
|
15
27
|
## Support
|
|
16
28
|
|
|
17
29
|
* Ask questions in [Rocket Job Discussions](https://github.com/reidmorrison/rocketjob/discussions)
|
|
18
|
-
* [Report bugs](https://github.com/
|
|
19
|
-
|
|
20
|
-
## Rocket Job v6
|
|
21
|
-
|
|
22
|
-
- Support for Ruby v3 and Rails 6.
|
|
23
|
-
- Major enhancements in Batch job support:
|
|
24
|
-
- Direct built-in Tabular support for all input and output categories.
|
|
25
|
-
- Multiple output file support, each with its own settings for:
|
|
26
|
-
- Compression
|
|
27
|
-
- GZip, Zip, BZip2 (Chunked for much faster loading into Apache Spark).
|
|
28
|
-
- Encryption
|
|
29
|
-
- PGP, Symmetric Encryption.
|
|
30
|
-
- File format
|
|
31
|
-
- CSV, PSV, JSON, Fixed Format, xlsx.
|
|
32
|
-
- Significant error handling improvements, especially around throttle failures
|
|
33
|
-
that used to result in "hanging" jobs.
|
|
34
|
-
- Support AWS DocumentDB in addition to MongoDB as the data store.
|
|
35
|
-
- Removed use of Symbols to meet Symbol deprecation in MongoDB and Mongoid.
|
|
36
|
-
|
|
37
|
-
### Upgrading to Rocket Job v6
|
|
38
|
-
|
|
39
|
-
The following plugins have been deprecated and are no longer loaded by default.
|
|
40
|
-
- `RocketJob::Batch::Tabular::Input`
|
|
41
|
-
- `RocketJob::Batch::Tabular::Output`
|
|
42
|
-
|
|
43
|
-
If your code relies on these plugins and you still want to upgrade to Rocket Job v6,
|
|
44
|
-
add the following require statement to any jobs that still use them:
|
|
45
|
-
|
|
46
|
-
~~~ruby
|
|
47
|
-
require "rocket_job/batch/tabular"
|
|
48
|
-
~~~
|
|
49
|
-
|
|
50
|
-
It is important to migrate away from these plugins, since they will be removed in a future release.
|
|
51
|
-
|
|
52
|
-
#### Scheduled Jobs
|
|
53
|
-
|
|
54
|
-
For any scheduled jobs that include the `RocketJob::Plugins::Cron` plugin, the default behavior has changed
|
|
55
|
-
so that the scheduled job instance is created immediately after the currently scheduled instance starts.
|
|
56
|
-
|
|
57
|
-
To maintain the old behavior of creating the job when it fails, aborts, or completes, add the following line
|
|
58
|
-
to each of the applicable jobs:
|
|
59
|
-
|
|
60
|
-
~~~ruby
|
|
61
|
-
self.cron_after_start = false
|
|
62
|
-
~~~
|
|
63
|
-
|
|
64
|
-
Additionally, scheduled jobs will now prevent a new one from being created when another scheduled instance
|
|
65
|
-
of the same job is already queued, or running with the _same_ `cron_schedule`.
|
|
66
|
-
|
|
67
|
-
To maintain the old behavior of allowing multiple instances with the same cron schedule, add the following
|
|
68
|
-
line to each of the applicable jobs:
|
|
69
|
-
|
|
70
|
-
~~~ruby
|
|
71
|
-
self.cron_singleton = false
|
|
72
|
-
~~~
|
|
73
|
-
|
|
74
|
-
##### Singleton
|
|
75
|
-
|
|
76
|
-
Since Scheduled jobs now implement their own singleton logic, remove the singleton plugin from any scheduled jobs.
|
|
77
|
-
|
|
78
|
-
#### Upgrading Batch Jobs to Rocket Job v6
|
|
79
|
-
|
|
80
|
-
Rocket Job v6 replaces the array of symbol type for `input_categories` and `output_categories`
|
|
81
|
-
with an array of `RocketJob::Category::Input` and `RocketJob::Category::Output`.
|
|
82
|
-
|
|
83
|
-
Jobs that added or modified the input or output categories need to be upgraded. For example:
|
|
84
|
-
~~~ruby
|
|
85
|
-
class MyJob < RocketJob::Job
|
|
86
|
-
include RocketJob::Batch
|
|
87
|
-
|
|
88
|
-
self.output_categories = [:main, :errors, :ignored]
|
|
89
|
-
end
|
|
90
|
-
~~~
|
|
30
|
+
* [Report bugs](https://github.com/reidmorrison/rocketjob/issues)
|
|
91
31
|
|
|
92
|
-
|
|
93
|
-
~~~ruby
|
|
94
|
-
class MyJob < RocketJob::Job
|
|
95
|
-
include RocketJob::Batch
|
|
96
|
-
|
|
97
|
-
output_category name: :main
|
|
98
|
-
output_category name: :errors
|
|
99
|
-
output_category name: :ignored
|
|
100
|
-
end
|
|
101
|
-
~~~
|
|
102
|
-
|
|
103
|
-
##### slice_size, encrypt, compress
|
|
104
|
-
|
|
105
|
-
These fields have been removed from the job itself:
|
|
106
|
-
~~~ruby
|
|
107
|
-
class MyJob < RocketJob::Job
|
|
108
|
-
include RocketJob::Batch
|
|
109
|
-
|
|
110
|
-
self.slice_size = 1_000
|
|
111
|
-
self.encrypt = true
|
|
112
|
-
self.compress = true
|
|
113
|
-
end
|
|
114
|
-
~~~
|
|
115
|
-
|
|
116
|
-
They are now specified on the `input_category` as follows:
|
|
117
|
-
- `slice_size` just moves under `input_category`.
|
|
118
|
-
- `encrypt` becomes an option to `serializer`.
|
|
119
|
-
- `compress` is now the default for all batch jobs so is not needed.
|
|
120
|
-
|
|
121
|
-
If the serializer is set to `encrypt` then it is automatically compressed.
|
|
122
|
-
|
|
123
|
-
~~~ruby
|
|
124
|
-
class MyJob < RocketJob::Job
|
|
125
|
-
include RocketJob::Batch
|
|
126
|
-
|
|
127
|
-
input_category slice_size: 1_000, serializer: :encrypt
|
|
128
|
-
end
|
|
129
|
-
~~~
|
|
130
|
-
|
|
131
|
-
##### collect_output, collect_nil_output
|
|
132
|
-
|
|
133
|
-
The following fields have been moved from the job itself:
|
|
134
|
-
~~~ruby
|
|
135
|
-
class MyJob < RocketJob::Job
|
|
136
|
-
include RocketJob::Batch
|
|
137
|
-
|
|
138
|
-
self.collect_output = true
|
|
139
|
-
self.collect_nil_output = true
|
|
140
|
-
end
|
|
141
|
-
~~~
|
|
142
|
-
|
|
143
|
-
Into the corresponding `output_category`:
|
|
144
|
-
- `collect_output` no longer has any meaning. Output is collected anytime an `output_category` is defined.
|
|
145
|
-
- `collect_nil_output` is now the option `nils` on the `output_category.
|
|
146
|
-
It defaults to `false` so that by default any `nil` output from the `perform` method is not collected.
|
|
147
|
-
~~~ruby
|
|
148
|
-
class MyJob < RocketJob::Job
|
|
149
|
-
include RocketJob::Batch
|
|
150
|
-
|
|
151
|
-
output_category nils: true
|
|
152
|
-
end
|
|
153
|
-
~~~
|
|
154
|
-
|
|
155
|
-
##### name
|
|
32
|
+
## Upgrading
|
|
156
33
|
|
|
157
|
-
|
|
158
|
-
|
|
34
|
+
See the [Upgrading guide](https://rocketjob.reidmorrison.com/upgrading.html) for the code and data changes needed
|
|
35
|
+
between major versions. Per-release notes are in the
|
|
36
|
+
[GitHub Releases](https://github.com/reidmorrison/rocketjob/releases).
|
|
159
37
|
|
|
160
|
-
|
|
161
|
-
~~~ruby
|
|
162
|
-
class MyJob < RocketJob::Job
|
|
163
|
-
include RocketJob::Batch
|
|
38
|
+
## Contributing
|
|
164
39
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
~~~
|
|
40
|
+
Contributions are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for the development setup and how
|
|
41
|
+
to run the test suite, and the [Architecture and Internals](https://rocketjob.reidmorrison.com/architecture.html)
|
|
42
|
+
page for how Rocket Job is put together.
|
|
169
43
|
|
|
170
|
-
|
|
171
|
-
~~~ruby
|
|
172
|
-
class MyJob < RocketJob::Job
|
|
173
|
-
include RocketJob::Batch
|
|
44
|
+
The documentation site lives in [`docs/`](docs/) as Jekyll markdown. To preview changes locally:
|
|
174
45
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
46
|
+
~~~bash
|
|
47
|
+
cd docs
|
|
48
|
+
bundle update
|
|
49
|
+
jekyll serve
|
|
178
50
|
~~~
|
|
179
51
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
When migrating to Rocket Job 6, it is recommended to load every job and then save it back again as part of the
|
|
183
|
-
deployment. When the job loads it will automatically convert itself from the old schema to the new v6 schema.
|
|
184
|
-
|
|
185
|
-
In flight jobs should not be affected, other than it is important to shutdown all running batch
|
|
186
|
-
servers _before_ running any new instances.
|
|
187
|
-
|
|
188
|
-
## Rocket Job v4
|
|
189
|
-
|
|
190
|
-
Rocket Job Pro is now fully open source and included in Rocket Job under the Apache License.
|
|
191
|
-
|
|
192
|
-
The `RocketJob::Batch` plugin now adds batch processing capabilities to break up a single task into many
|
|
193
|
-
concurrent workers processing slices of the entire job at the same time.
|
|
194
|
-
|
|
52
|
+
Then open [http://127.0.0.1:4000](http://127.0.0.1:4000) and edit the files under `docs/`.
|
|
195
53
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
```ruby
|
|
199
|
-
class MyJob < RocketJob::Job
|
|
200
|
-
include RocketJob::Batch
|
|
201
|
-
|
|
202
|
-
self.description = "Reverse names"
|
|
203
|
-
self.destroy_on_complete = false
|
|
204
|
-
|
|
205
|
-
# Collect the output for this job in the default output category: `:main`
|
|
206
|
-
output_category
|
|
207
|
-
|
|
208
|
-
# Method to call by all available workers at the same time.
|
|
209
|
-
# Reverse the characters for each line:
|
|
210
|
-
def perform(line)
|
|
211
|
-
line.reverse
|
|
212
|
-
end
|
|
213
|
-
end
|
|
214
|
-
```
|
|
215
|
-
|
|
216
|
-
Upload a file for processing, for example `names.csv` which could contain:
|
|
217
|
-
|
|
218
|
-
```
|
|
219
|
-
jack
|
|
220
|
-
jane
|
|
221
|
-
bill
|
|
222
|
-
john
|
|
223
|
-
blake
|
|
224
|
-
chris
|
|
225
|
-
dave
|
|
226
|
-
marc
|
|
227
|
-
```
|
|
228
|
-
|
|
229
|
-
To queue the above job for processing:
|
|
230
|
-
|
|
231
|
-
```ruby
|
|
232
|
-
job = MyJob.new
|
|
233
|
-
job.upload('names.csv')
|
|
234
|
-
job.save!
|
|
235
|
-
```
|
|
236
|
-
|
|
237
|
-
Once the job has completed, download the results into a file:
|
|
238
|
-
|
|
239
|
-
```ruby
|
|
240
|
-
job.download('names_reversed.csv')
|
|
241
|
-
```
|
|
242
|
-
|
|
243
|
-
## Contributing to the documentation
|
|
244
|
-
|
|
245
|
-
To contribute to the documentation it is as easy as forking the repository
|
|
246
|
-
and then editing the markdown pages directly via the github web interface.
|
|
247
|
-
|
|
248
|
-
For more complex documentation changes checkout the source code locally.
|
|
249
|
-
|
|
250
|
-
#### Local checkout
|
|
251
|
-
|
|
252
|
-
* Fork the repository in github.
|
|
253
|
-
* Checkout your fork of the source code locally.
|
|
254
|
-
* Install Jekyll
|
|
255
|
-
~~~
|
|
256
|
-
cd docs
|
|
257
|
-
bundle update
|
|
258
|
-
~~~
|
|
259
|
-
* Run Jekyll web server:
|
|
260
|
-
~~~
|
|
261
|
-
jekyll serve
|
|
262
|
-
~~~
|
|
263
|
-
* Open a web browser to view the local documentation:
|
|
264
|
-
[http://127.0.0.1:4000](http://127.0.0.1:4000)
|
|
265
|
-
* Edit the files in the `/docs` folder.
|
|
266
|
-
* Refresh the page to see the changes.
|
|
267
|
-
|
|
268
|
-
Once the changes are complete, submit a github pull request.
|
|
269
|
-
|
|
270
|
-
## Upgrading to V3
|
|
271
|
-
|
|
272
|
-
V3 replaces MongoMapper with Mongoid which supports the latest MongoDB Ruby client driver.
|
|
273
|
-
|
|
274
|
-
### Upgrading Mongo Config file
|
|
275
|
-
Replace `mongo.yml` with `mongoid.yml`.
|
|
276
|
-
|
|
277
|
-
Start with the sample [mongoid.yml](https://github.com/rocketjob/rocketjob/blob/feature/mongoid/test/config/mongoid.yml).
|
|
278
|
-
|
|
279
|
-
For more information on the new [Mongoid config file](https://docs.mongodb.com/ruby-driver/master/tutorials/5.1.0/mongoid-installation/).
|
|
280
|
-
|
|
281
|
-
Note: The `rocketjob` and `rocketjob_slices` clients in the above `mongoid.yml` file are required.
|
|
282
|
-
|
|
283
|
-
### Other changes
|
|
284
|
-
|
|
285
|
-
* Arguments are no longer supported, use fields for defining all named arguments for a job.
|
|
286
|
-
|
|
287
|
-
* Replace usages of `rocket_job do` to set default values:
|
|
288
|
-
|
|
289
|
-
~~~ruby
|
|
290
|
-
rocket_job do |job|
|
|
291
|
-
job.priority = 25
|
|
292
|
-
end
|
|
293
|
-
~~~
|
|
294
|
-
|
|
295
|
-
With:
|
|
296
|
-
|
|
297
|
-
~~~ruby
|
|
298
|
-
self.priority = 25
|
|
299
|
-
~~~
|
|
300
|
-
|
|
301
|
-
* Replace `key` with `field` when adding attributes to a job:
|
|
302
|
-
|
|
303
|
-
~~~ruby
|
|
304
|
-
key :inquiry_defaults, Hash
|
|
305
|
-
~~~
|
|
306
|
-
|
|
307
|
-
With:
|
|
308
|
-
|
|
309
|
-
~~~ruby
|
|
310
|
-
field :inquiry_defaults, type: Hash, default: {}
|
|
311
|
-
~~~
|
|
312
|
-
|
|
313
|
-
* Replace usage of `public_rocket_job_properties` with the `user_editable` option:
|
|
314
|
-
|
|
315
|
-
~~~ruby
|
|
316
|
-
field :priority, type: Integer, default: 50, user_editable: true
|
|
317
|
-
~~~
|
|
318
|
-
|
|
319
|
-
## Ruby Support
|
|
320
|
-
|
|
321
|
-
Rocket Job is tested and supported on the following Ruby platforms:
|
|
322
|
-
- Ruby 2.1, 2.2, 2.3, 2.4, and above
|
|
323
|
-
- JRuby 9.0.5 and above
|
|
324
|
-
|
|
325
|
-
## Dependencies
|
|
54
|
+
## Versioning
|
|
326
55
|
|
|
327
|
-
|
|
328
|
-
* Persists job information.
|
|
329
|
-
* Version 2.7 or greater.
|
|
330
|
-
* [Semantic Logger](https://rocketjob.github.io/semantic_logger)
|
|
331
|
-
* Highly concurrent scalable logging.
|
|
56
|
+
This project uses [Semantic Versioning](https://semver.org/).
|
|
332
57
|
|
|
333
|
-
##
|
|
58
|
+
## License
|
|
334
59
|
|
|
335
|
-
|
|
60
|
+
Apache License v2.0. See [LICENSE.txt](LICENSE.txt).
|
|
336
61
|
|
|
337
62
|
## Author
|
|
338
63
|
|
|
339
64
|
[Reid Morrison](https://github.com/reidmorrison)
|
|
340
65
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
[Contributors](https://github.com/rocketjob/rocketjob/graphs/contributors)
|
|
344
|
-
|
|
66
|
+
[Contributors](https://github.com/reidmorrison/rocketjob/graphs/contributors)
|
data/bin/rocketjob_batch_perf
CHANGED
|
@@ -51,12 +51,12 @@ module RocketJob
|
|
|
51
51
|
# Builds this job instance from the supplied properties hash that may contain input and output categories.
|
|
52
52
|
# Keeps the defaults and merges in settings without replacing existing categories.
|
|
53
53
|
def from_properties(properties)
|
|
54
|
-
return super
|
|
54
|
+
return super unless properties.key?("input_categories") || properties.key?("output_categories")
|
|
55
55
|
|
|
56
56
|
properties = properties.dup
|
|
57
57
|
input_categories = properties.delete("input_categories")
|
|
58
58
|
output_categories = properties.delete("output_categories")
|
|
59
|
-
job = super
|
|
59
|
+
job = super
|
|
60
60
|
job.merge_input_categories(input_categories)
|
|
61
61
|
job.merge_output_categories(output_categories)
|
|
62
62
|
job
|
|
@@ -126,7 +126,7 @@ module RocketJob
|
|
|
126
126
|
categories.each do |properties|
|
|
127
127
|
category_name = (properties["name"] || properties[:name] || :main).to_sym
|
|
128
128
|
category = input_category(category_name)
|
|
129
|
-
properties.each { |key, value| category.public_send("#{key}="
|
|
129
|
+
properties.each { |key, value| category.public_send(:"#{key}=", value) }
|
|
130
130
|
end
|
|
131
131
|
end
|
|
132
132
|
|
|
@@ -136,7 +136,7 @@ module RocketJob
|
|
|
136
136
|
categories.each do |properties|
|
|
137
137
|
category_name = (properties["name"] || properties[:name] || :main).to_sym
|
|
138
138
|
category = output_category(category_name)
|
|
139
|
-
properties.each { |key, value| category.public_send("#{key}="
|
|
139
|
+
properties.each { |key, value| category.public_send(:"#{key}=", value) }
|
|
140
140
|
end
|
|
141
141
|
end
|
|
142
142
|
|
|
@@ -314,27 +314,27 @@ module RocketJob
|
|
|
314
314
|
|
|
315
315
|
existing = self[:output_categories]
|
|
316
316
|
self[:output_categories] = []
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
)
|
|
337
|
-
|
|
317
|
+
return unless collect_output
|
|
318
|
+
|
|
319
|
+
if existing.blank?
|
|
320
|
+
self[:output_categories] = [
|
|
321
|
+
RocketJob::Category::Output.new(
|
|
322
|
+
nils: collect_nil_output,
|
|
323
|
+
format: main_output_format,
|
|
324
|
+
columns: main_output_columns,
|
|
325
|
+
format_options: main_output_options
|
|
326
|
+
).as_document
|
|
327
|
+
]
|
|
328
|
+
elsif existing.first.is_a?(Symbol)
|
|
329
|
+
self[:output_categories] = existing.collect do |category_name|
|
|
330
|
+
RocketJob::Category::Output.new(
|
|
331
|
+
name: category_name,
|
|
332
|
+
serializer: serializer,
|
|
333
|
+
nils: collect_nil_output,
|
|
334
|
+
format: [:main, "main"].include?(category_name) ? main_output_format : nil,
|
|
335
|
+
columns: [:main, "main"].include?(category_name) ? main_output_columns : nil,
|
|
336
|
+
format_options: [:main, "main"].include?(category_name) ? main_output_options : nil
|
|
337
|
+
).as_document
|
|
338
338
|
end
|
|
339
339
|
end
|
|
340
340
|
end
|
data/lib/rocket_job/batch/io.rb
CHANGED
|
@@ -269,13 +269,15 @@ module RocketJob
|
|
|
269
269
|
# * If an exception is raised while uploading data, the input collection is cleared out
|
|
270
270
|
# so that if a job is retried during an upload failure, data is not duplicated.
|
|
271
271
|
|
|
272
|
-
def upload(object = nil, category: :main, file_name: nil, stream_mode: nil, on_first: nil, columns: nil,
|
|
272
|
+
def upload(object = nil, category: :main, file_name: nil, stream_mode: nil, on_first: nil, columns: nil,
|
|
273
|
+
slice_batch_size: nil, **args, &block)
|
|
273
274
|
input_collection = input(category)
|
|
274
275
|
|
|
275
276
|
if block
|
|
276
277
|
raise(ArgumentError, "Cannot supply both an object to upload, and a block.") if object
|
|
277
|
-
if stream_mode || columns || slice_batch_size || args.size
|
|
278
|
-
raise(ArgumentError,
|
|
278
|
+
if stream_mode || columns || slice_batch_size || args.size.positive?
|
|
279
|
+
raise(ArgumentError,
|
|
280
|
+
"Unknown keyword arguments when uploading a block. Only accepts :category, :file_name, or :on_first")
|
|
279
281
|
end
|
|
280
282
|
|
|
281
283
|
category = input_category(category)
|
|
@@ -292,8 +294,9 @@ module RocketJob
|
|
|
292
294
|
count =
|
|
293
295
|
case object
|
|
294
296
|
when Range
|
|
295
|
-
if file_name || stream_mode || on_first || args.size
|
|
296
|
-
raise(ArgumentError,
|
|
297
|
+
if file_name || stream_mode || on_first || args.size.positive?
|
|
298
|
+
raise(ArgumentError,
|
|
299
|
+
"Unknown keyword arguments when uploading a Range. Only accepts :category, :columns, or :slice_batch_size")
|
|
297
300
|
end
|
|
298
301
|
|
|
299
302
|
first = object.first
|
|
@@ -304,14 +307,16 @@ module RocketJob
|
|
|
304
307
|
input_collection.upload_integer_range_in_reverse_order(last, first, slice_batch_size: slice_batch_size || 1_000)
|
|
305
308
|
end
|
|
306
309
|
when Mongoid::Criteria
|
|
307
|
-
if file_name || stream_mode || on_first || args.size
|
|
308
|
-
raise(ArgumentError,
|
|
310
|
+
if file_name || stream_mode || on_first || args.size.positive?
|
|
311
|
+
raise(ArgumentError,
|
|
312
|
+
"Unknown keyword arguments when uploading a Mongoid::Criteria. Only accepts :category, :columns, or :slice_batch_size")
|
|
309
313
|
end
|
|
310
314
|
|
|
311
315
|
input_collection.upload_mongo_query(object, columns: columns, slice_batch_size: slice_batch_size, &block)
|
|
312
316
|
when defined?(ActiveRecord::Relation) ? ActiveRecord::Relation : false
|
|
313
|
-
if file_name || stream_mode || on_first || args.size
|
|
314
|
-
raise(ArgumentError,
|
|
317
|
+
if file_name || stream_mode || on_first || args.size.positive?
|
|
318
|
+
raise(ArgumentError,
|
|
319
|
+
"Unknown keyword arguments when uploading an ActiveRecord::Relation. Only accepts :category, :columns, or :slice_batch_size")
|
|
315
320
|
end
|
|
316
321
|
|
|
317
322
|
input_collection.upload_arel(object, columns: columns, slice_batch_size: slice_batch_size, &block)
|
|
@@ -336,15 +341,15 @@ module RocketJob
|
|
|
336
341
|
end
|
|
337
342
|
|
|
338
343
|
# @deprecated
|
|
339
|
-
def upload_arel(arel, *column_names, category: :main, &
|
|
340
|
-
count = input(category).upload_arel(arel, columns: column_names, &
|
|
344
|
+
def upload_arel(arel, *column_names, category: :main, &)
|
|
345
|
+
count = input(category).upload_arel(arel, columns: column_names, &)
|
|
341
346
|
self.record_count = (record_count || 0) + count
|
|
342
347
|
count
|
|
343
348
|
end
|
|
344
349
|
|
|
345
350
|
# @deprecated
|
|
346
|
-
def upload_mongo_query(criteria, *column_names, category: :main, &
|
|
347
|
-
count = input(category).upload_mongo_query(criteria, columns: column_names, &
|
|
351
|
+
def upload_mongo_query(criteria, *column_names, category: :main, &)
|
|
352
|
+
count = input(category).upload_mongo_query(criteria, columns: column_names, &)
|
|
348
353
|
self.record_count = (record_count || 0) + count
|
|
349
354
|
count
|
|
350
355
|
end
|
|
@@ -358,7 +363,8 @@ module RocketJob
|
|
|
358
363
|
|
|
359
364
|
# @deprecated
|
|
360
365
|
def upload_integer_range_in_reverse_order(start_id, last_id, category: :main, slice_batch_size: 1_000)
|
|
361
|
-
count = input(category).upload_integer_range_in_reverse_order(start_id, last_id,
|
|
366
|
+
count = input(category).upload_integer_range_in_reverse_order(start_id, last_id,
|
|
367
|
+
slice_batch_size: slice_batch_size)
|
|
362
368
|
self.record_count = (record_count || 0) + count
|
|
363
369
|
count
|
|
364
370
|
end
|
|
@@ -459,7 +465,7 @@ module RocketJob
|
|
|
459
465
|
binary_header_line = output_collection.slice_class.to_binary(header_line) if header_line
|
|
460
466
|
|
|
461
467
|
# Don't overwrite supplied stream options if any
|
|
462
|
-
stream = stream
|
|
468
|
+
stream = stream.is_a?(IOStreams::Stream) ? stream.dup : IOStreams.new(category.file_name)
|
|
463
469
|
stream.remove_from_pipeline(output_collection.slice_class.binary_format)
|
|
464
470
|
stream.writer(**args) do |io|
|
|
465
471
|
# TODO: Binary formats should return the record count, instead of the slice count.
|
|
@@ -29,7 +29,7 @@ module RocketJob
|
|
|
29
29
|
# - log_exception logs entire exception if raised
|
|
30
30
|
# - on_exception_level changes log level from info to error on exception
|
|
31
31
|
# - silence noisy jobs by raising log level
|
|
32
|
-
def rocket_job_batch_slice_logger(&
|
|
32
|
+
def rocket_job_batch_slice_logger(&)
|
|
33
33
|
logger.measure_info(
|
|
34
34
|
"Completed slice",
|
|
35
35
|
metric: "#{self.class.name}/slice",
|
|
@@ -37,7 +37,7 @@ module RocketJob
|
|
|
37
37
|
on_exception_level: :error,
|
|
38
38
|
silence: log_level,
|
|
39
39
|
payload: {records: rocket_job_slice&.size},
|
|
40
|
-
&
|
|
40
|
+
&
|
|
41
41
|
)
|
|
42
42
|
end
|
|
43
43
|
|
|
@@ -66,14 +66,14 @@ module RocketJob
|
|
|
66
66
|
percent = percent_complete
|
|
67
67
|
if percent >= 5
|
|
68
68
|
secs = seconds.to_f
|
|
69
|
-
h["est_remaining_duration"] = RocketJob.seconds_as_duration(((
|
|
69
|
+
h["est_remaining_duration"] = RocketJob.seconds_as_duration(((secs / percent) * 100) - secs)
|
|
70
70
|
end
|
|
71
71
|
end
|
|
72
72
|
elsif completed?
|
|
73
73
|
secs = seconds.to_f
|
|
74
74
|
h["records_per_hour"] = ((record_count.to_f / secs) * 60 * 60).round if record_count&.positive? && (secs > 0.0)
|
|
75
75
|
end
|
|
76
|
-
h.merge!(super
|
|
76
|
+
h.merge!(super)
|
|
77
77
|
h.delete("result")
|
|
78
78
|
# Worker name should be retrieved from the slices when processing
|
|
79
79
|
h.delete("worker_name") if sub_state == :processing
|
|
@@ -50,9 +50,16 @@ module RocketJob
|
|
|
50
50
|
return unless last
|
|
51
51
|
|
|
52
52
|
last_target = paths.inject(in_memory) do |target, sub_key|
|
|
53
|
-
|
|
53
|
+
# Assigning a Hash into a BSON::Document (Mongoid 9) stores a
|
|
54
|
+
# converted copy, so read the value back rather than reusing the
|
|
55
|
+
# assigned object, otherwise nested increments are lost.
|
|
56
|
+
target[sub_key] = Hash.new(0) unless target.key?(sub_key)
|
|
57
|
+
target[sub_key]
|
|
54
58
|
end
|
|
55
|
-
|
|
59
|
+
# Mongoid 9 demongoizes Hash fields to a BSON::Document without a
|
|
60
|
+
# default, so the leaf value may be nil even when the field default
|
|
61
|
+
# is `Hash.new(0)`. Default missing leaves to zero before adding.
|
|
62
|
+
last_target[last] = (last_target[last] || 0) + increment
|
|
56
63
|
end
|
|
57
64
|
end
|
|
58
65
|
|
|
@@ -45,11 +45,16 @@ module RocketJob
|
|
|
45
45
|
# Or, a block that will return the filter.
|
|
46
46
|
# Default: :throttle_filter_class (Throttle all jobs of this class)
|
|
47
47
|
#
|
|
48
|
+
# description: [String|Proc]
|
|
49
|
+
# Human readable reason why the job is throttled, persisted to `throttled_by`
|
|
50
|
+
# and shown in Mission Control. A Proc is called with the job and slice and
|
|
51
|
+
# must return a String. Default: a humanized version of the method name.
|
|
52
|
+
#
|
|
48
53
|
# Note: Throttles are executed in the order they are defined.
|
|
49
|
-
def define_batch_throttle(method_name, filter: :throttle_filter_class)
|
|
54
|
+
def define_batch_throttle(method_name, filter: :throttle_filter_class, description: nil)
|
|
50
55
|
# Duplicate to prevent modifying parent class throttles
|
|
51
56
|
definitions = rocket_job_batch_throttles ? rocket_job_batch_throttles.dup : ThrottleDefinitions.new
|
|
52
|
-
definitions.add(method_name, filter)
|
|
57
|
+
definitions.add(method_name, filter, description)
|
|
53
58
|
self.rocket_job_batch_throttles = definitions
|
|
54
59
|
end
|
|
55
60
|
|