scripterator 1.2.0 → 1.4.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 +5 -5
- data/.gitignore +1 -1
- data/.travis.yml +5 -5
- data/CHANGELOG.md +16 -1
- data/Gemfile +2 -6
- data/Gemfile-rails-5.0.x +6 -0
- data/Gemfile-rails-5.1.x +6 -0
- data/Gemfile-rails-5.2.x +6 -0
- data/README.md +9 -0
- data/lib/scripterator.rb +1 -0
- data/lib/scripterator/runner.rb +17 -11
- data/lib/scripterator/version.rb +1 -1
- data/scripterator.gemspec +5 -5
- data/spec/runner_spec.rb +25 -22
- data/spec/support/widget.rb +1 -0
- metadata +21 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: e6b0a2c0390962d5310ff31c294faa74b5d74186c949ed04170c62f0506dc656
|
4
|
+
data.tar.gz: 123f12425a1ee3e941b5cdbdff78d8f7bdfcf49d968dc4c006ba21f240931856
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b90ca2a2ef31b7e112c96d3a9560a0d40f27feae22ccea6e79614387d5527a9f891c630467b66cf14dde73315f0b832d075b680efc3f99edb4709a91ac3baf08
|
7
|
+
data.tar.gz: 65f43d3eebeae7b0b5b64fe9e259ac61b6f43984eed5b976e76660ba3fa06d7b1ca567ce3f1b358aa60c305a5334820857ac645ebed52a10d065a2d890053947
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,2 +1,17 @@
|
|
1
|
+
# 1.4.0
|
2
|
+
- Update redis to 4+
|
3
|
+
- Update rspec
|
4
|
+
- Update fakeredis
|
5
|
+
|
6
|
+
# 1.3.2
|
7
|
+
- Rails 5 support
|
8
|
+
|
9
|
+
# 1.3.1
|
10
|
+
- Fix things from 1.3.0 that didn't work
|
11
|
+
|
12
|
+
# 1.3.0
|
13
|
+
- Add support for changing batch size
|
14
|
+
- Add support for `after_batch` and `before_batch` callbacks
|
15
|
+
|
1
16
|
# 1.2.0
|
2
|
-
Add support for ActiveRecord versions 3.0 through 4.2
|
17
|
+
- Add support for ActiveRecord versions 3.0 through 4.2
|
data/Gemfile
CHANGED
data/Gemfile-rails-5.0.x
ADDED
data/Gemfile-rails-5.1.x
ADDED
data/Gemfile-rails-5.2.x
ADDED
data/README.md
CHANGED
@@ -32,10 +32,18 @@ Scripterator.run "Convert users from legacy auth data" do
|
|
32
32
|
User.skip_some_callbacks_we_want_to_avoid_during_script_running
|
33
33
|
end
|
34
34
|
|
35
|
+
before_batch do |batch|
|
36
|
+
# do stuff
|
37
|
+
end
|
38
|
+
|
35
39
|
for_each_user do |user|
|
36
40
|
user.do_legacy_conversion
|
37
41
|
end
|
38
42
|
|
43
|
+
after_batch do |batch|
|
44
|
+
# do stuff
|
45
|
+
end
|
46
|
+
|
39
47
|
after do
|
40
48
|
# some code to run after everything's finished
|
41
49
|
end
|
@@ -93,6 +101,7 @@ Environment variable options:
|
|
93
101
|
|
94
102
|
- `START`: first model ID to scripterate
|
95
103
|
- `END`: last model ID to scripterate
|
104
|
+
- `BATCH_SIZE`: how many records to process in a batch
|
96
105
|
- `ID_LIST`: comma-delimited list of IDs to scripterate (e.g. "ID_LIST=1,99,440,23")
|
97
106
|
- `REDIS_EXPIRATION`: amount of time (in seconds) before Redis result sets (checked IDs and failed IDs) are expired
|
98
107
|
|
data/lib/scripterator.rb
CHANGED
@@ -18,6 +18,7 @@ module Scripterator
|
|
18
18
|
options = {}.tap do |o|
|
19
19
|
o[:start_id] = ENV['START'].try(:to_i)
|
20
20
|
o[:end_id] = ENV['END'].try(:to_i)
|
21
|
+
o[:batch_size] = ENV['BATCH_SIZE'].try(:to_i)
|
21
22
|
o[:id_list] = ENV['ID_LIST'].try(:split, ',')
|
22
23
|
o[:redis_expiration] = ENV['REDIS_EXPIRATION'].try(:to_i) || config.redis_expiration
|
23
24
|
end
|
data/lib/scripterator/runner.rb
CHANGED
@@ -23,6 +23,7 @@ module Scripterator
|
|
23
23
|
@id_list = options[:id_list] || []
|
24
24
|
@start_id = options[:start_id] || 1
|
25
25
|
@end_id = options[:end_id]
|
26
|
+
@batch_size = options[:batch_size] || 1000
|
26
27
|
@redis_expiration = options[:redis_expiration]
|
27
28
|
@output_stream = options[:output_stream] || $stdout
|
28
29
|
|
@@ -34,7 +35,7 @@ module Scripterator
|
|
34
35
|
output_stats
|
35
36
|
end
|
36
37
|
|
37
|
-
%w(model before per_record after).each do |callback|
|
38
|
+
%w(model before per_record after before_batch after_batch).each do |callback|
|
38
39
|
define_method callback do |&block|
|
39
40
|
instance_variable_set "@#{callback}", block
|
40
41
|
end
|
@@ -102,20 +103,25 @@ module Scripterator
|
|
102
103
|
end
|
103
104
|
|
104
105
|
def run_loop
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
106
|
+
@id_list = (@start_id..@end_id) if @end_id
|
107
|
+
relation = model_finder
|
108
|
+
opts = {
|
109
|
+
batch_size: @batch_size
|
110
|
+
}
|
111
|
+
|
112
|
+
if @id_list.count < 1
|
113
|
+
opts[:start] = @start_id
|
110
114
|
else
|
111
|
-
model_finder.
|
115
|
+
relation = model_finder.where(id: @id_list)
|
112
116
|
end
|
113
117
|
|
114
|
-
|
115
|
-
|
118
|
+
relation.find_in_batches(opts) do |group|
|
119
|
+
self.instance_exec(group, &@before_batch) if @before_batch
|
120
|
+
group.each { |record| transform_one_record(record) }
|
121
|
+
self.instance_exec(group, &@after_batch) if @after_batch
|
122
|
+
end
|
116
123
|
|
117
|
-
|
118
|
-
model_finder.where(id: @id_list).find_each { |record| transform_one_record(record) }
|
124
|
+
expire_redis_sets
|
119
125
|
end
|
120
126
|
|
121
127
|
def transform_one_record(record)
|
data/lib/scripterator/version.rb
CHANGED
data/scripterator.gemspec
CHANGED
@@ -15,10 +15,10 @@ Gem::Specification.new do |gem|
|
|
15
15
|
gem.require_paths = ["lib"]
|
16
16
|
gem.version = Scripterator::VERSION
|
17
17
|
|
18
|
-
gem.add_dependency 'activerecord', '<
|
19
|
-
gem.add_dependency 'redis', '~>
|
18
|
+
gem.add_dependency 'activerecord', '< 6'
|
19
|
+
gem.add_dependency 'redis', '~> 4.0'
|
20
20
|
|
21
|
-
gem.add_development_dependency 'fakeredis', '~> 0.
|
22
|
-
gem.add_development_dependency 'rspec', '~>
|
23
|
-
gem.add_development_dependency 'sqlite3'
|
21
|
+
gem.add_development_dependency 'fakeredis', '~> 0.8.0'
|
22
|
+
gem.add_development_dependency 'rspec', '~> 3.0'
|
23
|
+
gem.add_development_dependency 'sqlite3'
|
24
24
|
end
|
data/spec/runner_spec.rb
CHANGED
@@ -10,6 +10,7 @@ describe Scripterator::Runner do
|
|
10
10
|
Proc.new do
|
11
11
|
before { Widget.before_stuff }
|
12
12
|
for_each_widget { |widget| Widget.transform_a_widget(widget) }
|
13
|
+
after_batch { |batch| Widget.after_batch_stuff(batch) }
|
13
14
|
end
|
14
15
|
end
|
15
16
|
|
@@ -17,12 +18,12 @@ describe Scripterator::Runner do
|
|
17
18
|
|
18
19
|
shared_examples_for 'raises an error' do
|
19
20
|
specify do
|
20
|
-
expect { subject }.to raise_error
|
21
|
+
expect { subject }.to raise_error(StandardError)
|
21
22
|
end
|
22
23
|
end
|
23
24
|
|
24
25
|
it 'infers the model from the for_each block' do
|
25
|
-
runner.send(:model_finder).
|
26
|
+
expect(runner.send(:model_finder)).to eq Widget
|
26
27
|
end
|
27
28
|
|
28
29
|
context 'when a model block is defined' do
|
@@ -31,14 +32,15 @@ describe Scripterator::Runner do
|
|
31
32
|
model { Widget.where(name: 'bla') }
|
32
33
|
before { Widget.before_stuff }
|
33
34
|
for_each_widget { |widget| Widget.transform_a_widget(widget) }
|
35
|
+
after_batch { |batch| Widget.after_batch_stuff(batch) }
|
34
36
|
end
|
35
37
|
end
|
36
38
|
let!(:widget1) { Widget.create(name: 'foo') }
|
37
39
|
let!(:widget2) { Widget.create(name: 'bla') }
|
38
40
|
|
39
41
|
it 'uses the given model finder code' do
|
40
|
-
Widget.
|
41
|
-
Widget.
|
42
|
+
expect(Widget).to receive(:transform_a_widget).once.with(widget2)
|
43
|
+
expect(Widget).not_to receive(:transform_a_widget).with(widget1)
|
42
44
|
subject
|
43
45
|
end
|
44
46
|
end
|
@@ -57,8 +59,8 @@ describe Scripterator::Runner do
|
|
57
59
|
|
58
60
|
it 'transforms each widget in the list' do
|
59
61
|
options[:id_list].each do |id|
|
60
|
-
runner.
|
61
|
-
arg1.id.
|
62
|
+
expect(runner).to receive(:transform_one_record) do |arg1|
|
63
|
+
expect(arg1.id).to eq id
|
62
64
|
end
|
63
65
|
end
|
64
66
|
subject
|
@@ -76,14 +78,14 @@ describe Scripterator::Runner do
|
|
76
78
|
it_behaves_like 'raises an error'
|
77
79
|
|
78
80
|
it 'does not run any other given blocks' do
|
79
|
-
Widget.
|
81
|
+
expect(Widget).to_not receive(:before_stuff)
|
80
82
|
subject rescue nil
|
81
83
|
end
|
82
84
|
end
|
83
85
|
|
84
86
|
context 'when there are no records for the specified model' do
|
85
87
|
it 'does not run the per-record block' do
|
86
|
-
Widget.
|
88
|
+
expect(Widget).to_not receive(:transform_a_widget)
|
87
89
|
subject
|
88
90
|
end
|
89
91
|
end
|
@@ -94,8 +96,9 @@ describe Scripterator::Runner do
|
|
94
96
|
before { num_widgets.times { Widget.create! } }
|
95
97
|
|
96
98
|
it 'runs the given script blocks' do
|
97
|
-
Widget.
|
98
|
-
Widget.
|
99
|
+
expect(Widget).to receive(:before_stuff)
|
100
|
+
expect(Widget).to receive(:transform_a_widget).exactly(num_widgets).times
|
101
|
+
expect(Widget).to receive(:after_batch_stuff)
|
99
102
|
subject
|
100
103
|
end
|
101
104
|
|
@@ -104,10 +107,10 @@ describe Scripterator::Runner do
|
|
104
107
|
|
105
108
|
it 'marks only the checked IDs as checked' do
|
106
109
|
subject
|
107
|
-
Scripterator.already_run_for?(description, Widget.first.id).
|
108
|
-
Scripterator.checked_ids(description).
|
109
|
-
Scripterator.already_run_for?(description, Widget.last.id).
|
110
|
-
Scripterator.checked_ids(description).
|
110
|
+
expect(Scripterator.already_run_for?(description, Widget.first.id)).to be_falsey
|
111
|
+
expect(Scripterator.checked_ids(description)).to_not include Widget.first.id
|
112
|
+
expect(Scripterator.already_run_for?(description, Widget.last.id)).to be_truthy
|
113
|
+
expect(Scripterator.checked_ids(description)).to include Widget.last.id
|
111
114
|
end
|
112
115
|
end
|
113
116
|
|
@@ -115,20 +118,20 @@ describe Scripterator::Runner do
|
|
115
118
|
let(:checked_ids) { [Widget.first.id] }
|
116
119
|
|
117
120
|
before do
|
118
|
-
Scripterator.
|
119
|
-
Scripterator::ScriptRedis.
|
120
|
-
Scripterator::ScriptRedis.
|
121
|
+
allow(Scripterator).to receive(:checked_ids).and_return(checked_ids)
|
122
|
+
allow_any_instance_of(Scripterator::ScriptRedis).to receive(:already_run_for?).and_return(false)
|
123
|
+
allow_any_instance_of(Scripterator::ScriptRedis).to receive(:already_run_for?).with(Widget.first.id).and_return(true)
|
121
124
|
end
|
122
125
|
|
123
126
|
it 'only runs the per-record code for unchecked records' do
|
124
|
-
Widget.
|
127
|
+
expect(Widget).to receive(:transform_a_widget).exactly(num_widgets - 1).times
|
125
128
|
subject
|
126
129
|
end
|
127
130
|
end
|
128
131
|
|
129
132
|
context 'when the code for some records fails' do
|
130
133
|
before do
|
131
|
-
Widget.
|
134
|
+
allow(Widget).to receive(:transform_a_widget) do |widget|
|
132
135
|
raise 'Last widget expl0de' if widget.id == Widget.last.id
|
133
136
|
true
|
134
137
|
end
|
@@ -136,8 +139,8 @@ describe Scripterator::Runner do
|
|
136
139
|
|
137
140
|
it 'marks only the failed IDs as failed' do
|
138
141
|
subject
|
139
|
-
Scripterator.failed_ids(description).
|
140
|
-
Scripterator.failed_ids(description).
|
142
|
+
expect(Scripterator.failed_ids(description)).to_not include Widget.first.id
|
143
|
+
expect(Scripterator.failed_ids(description)).to include Widget.last.id
|
141
144
|
end
|
142
145
|
end
|
143
146
|
|
@@ -147,7 +150,7 @@ describe Scripterator::Runner do
|
|
147
150
|
|
148
151
|
it 'runs without Redis' do
|
149
152
|
expect { subject }.not_to raise_error
|
150
|
-
Scripterator.checked_ids(description).
|
153
|
+
expect(Scripterator.checked_ids(description)).to be_empty
|
151
154
|
end
|
152
155
|
end
|
153
156
|
end
|
data/spec/support/widget.rb
CHANGED
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: scripterator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ted Dumitrescu
|
8
8
|
- Carl Furrow
|
9
|
-
autorequire:
|
9
|
+
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2021-04-21 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activerecord
|
@@ -17,70 +17,70 @@ dependencies:
|
|
17
17
|
requirements:
|
18
18
|
- - "<"
|
19
19
|
- !ruby/object:Gem::Version
|
20
|
-
version: '
|
20
|
+
version: '6'
|
21
21
|
type: :runtime
|
22
22
|
prerelease: false
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
25
25
|
- - "<"
|
26
26
|
- !ruby/object:Gem::Version
|
27
|
-
version: '
|
27
|
+
version: '6'
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
29
|
name: redis
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
31
31
|
requirements:
|
32
32
|
- - "~>"
|
33
33
|
- !ruby/object:Gem::Version
|
34
|
-
version: '
|
34
|
+
version: '4.0'
|
35
35
|
type: :runtime
|
36
36
|
prerelease: false
|
37
37
|
version_requirements: !ruby/object:Gem::Requirement
|
38
38
|
requirements:
|
39
39
|
- - "~>"
|
40
40
|
- !ruby/object:Gem::Version
|
41
|
-
version: '
|
41
|
+
version: '4.0'
|
42
42
|
- !ruby/object:Gem::Dependency
|
43
43
|
name: fakeredis
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
45
45
|
requirements:
|
46
46
|
- - "~>"
|
47
47
|
- !ruby/object:Gem::Version
|
48
|
-
version:
|
48
|
+
version: 0.8.0
|
49
49
|
type: :development
|
50
50
|
prerelease: false
|
51
51
|
version_requirements: !ruby/object:Gem::Requirement
|
52
52
|
requirements:
|
53
53
|
- - "~>"
|
54
54
|
- !ruby/object:Gem::Version
|
55
|
-
version:
|
55
|
+
version: 0.8.0
|
56
56
|
- !ruby/object:Gem::Dependency
|
57
57
|
name: rspec
|
58
58
|
requirement: !ruby/object:Gem::Requirement
|
59
59
|
requirements:
|
60
60
|
- - "~>"
|
61
61
|
- !ruby/object:Gem::Version
|
62
|
-
version: '
|
62
|
+
version: '3.0'
|
63
63
|
type: :development
|
64
64
|
prerelease: false
|
65
65
|
version_requirements: !ruby/object:Gem::Requirement
|
66
66
|
requirements:
|
67
67
|
- - "~>"
|
68
68
|
- !ruby/object:Gem::Version
|
69
|
-
version: '
|
69
|
+
version: '3.0'
|
70
70
|
- !ruby/object:Gem::Dependency
|
71
71
|
name: sqlite3
|
72
72
|
requirement: !ruby/object:Gem::Requirement
|
73
73
|
requirements:
|
74
|
-
- - "
|
74
|
+
- - ">="
|
75
75
|
- !ruby/object:Gem::Version
|
76
|
-
version:
|
76
|
+
version: '0'
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
79
|
version_requirements: !ruby/object:Gem::Requirement
|
80
80
|
requirements:
|
81
|
-
- - "
|
81
|
+
- - ">="
|
82
82
|
- !ruby/object:Gem::Version
|
83
|
-
version:
|
83
|
+
version: '0'
|
84
84
|
description: Script iterator for ActiveRecord models
|
85
85
|
email:
|
86
86
|
- ted@lumoslabs.com
|
@@ -94,6 +94,9 @@ files:
|
|
94
94
|
- ".travis.yml"
|
95
95
|
- CHANGELOG.md
|
96
96
|
- Gemfile
|
97
|
+
- Gemfile-rails-5.0.x
|
98
|
+
- Gemfile-rails-5.1.x
|
99
|
+
- Gemfile-rails-5.2.x
|
97
100
|
- LICENSE
|
98
101
|
- README.md
|
99
102
|
- lib/scripterator.rb
|
@@ -108,7 +111,7 @@ files:
|
|
108
111
|
homepage: http://lumosity.com
|
109
112
|
licenses: []
|
110
113
|
metadata: {}
|
111
|
-
post_install_message:
|
114
|
+
post_install_message:
|
112
115
|
rdoc_options: []
|
113
116
|
require_paths:
|
114
117
|
- lib
|
@@ -123,13 +126,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
123
126
|
- !ruby/object:Gem::Version
|
124
127
|
version: '0'
|
125
128
|
requirements: []
|
126
|
-
|
127
|
-
|
128
|
-
signing_key:
|
129
|
+
rubygems_version: 3.1.2
|
130
|
+
signing_key:
|
129
131
|
specification_version: 4
|
130
132
|
summary: DSL for running operations on each of a set of models
|
131
133
|
test_files:
|
132
134
|
- spec/runner_spec.rb
|
133
135
|
- spec/spec_helper.rb
|
134
136
|
- spec/support/widget.rb
|
135
|
-
has_rdoc:
|