active_record_data_loader 1.2.0 → 1.3.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/.github/workflows/codeql-analysis.yml +70 -0
- data/.rubocop.yml +8 -2
- data/CHANGELOG.md +9 -0
- data/CODE_OF_CONDUCT.md +2 -2
- data/Gemfile.lock +24 -24
- data/README.md +88 -18
- data/active_record_data_loader.gemspec +1 -1
- data/lib/active_record_data_loader/active_record/{belongs_to_configuration.rb → belongs_to_data_provider.rb} +7 -6
- data/lib/active_record_data_loader/active_record/{column_configuration.rb → column_data_provider.rb} +2 -2
- data/lib/active_record_data_loader/active_record/list.rb +35 -0
- data/lib/active_record_data_loader/active_record/model_data_generator.rb +60 -5
- data/lib/active_record_data_loader/active_record/{polymorphic_belongs_to_configuration.rb → polymorphic_belongs_to_data_provider.rb} +11 -6
- data/lib/active_record_data_loader/active_record/unique_index_tracker.rb +67 -0
- data/lib/active_record_data_loader/bulk_insert_strategy.rb +16 -9
- data/lib/active_record_data_loader/configuration.rb +13 -30
- data/lib/active_record_data_loader/connection_handler.rb +23 -45
- data/lib/active_record_data_loader/copy_strategy.rb +21 -7
- data/lib/active_record_data_loader/data_faker.rb +12 -4
- data/lib/active_record_data_loader/dsl/model.rb +19 -2
- data/lib/active_record_data_loader/errors.rb +5 -0
- data/lib/active_record_data_loader/file_output_adapter.rb +20 -12
- data/lib/active_record_data_loader/loader.rb +61 -55
- data/lib/active_record_data_loader/null_output_adapter.rb +15 -0
- data/lib/active_record_data_loader/table_loader.rb +59 -0
- data/lib/active_record_data_loader/version.rb +1 -1
- data/lib/active_record_data_loader.rb +9 -41
- metadata +12 -7
- data/lib/active_record_data_loader/connection_output_adapter.rb +0 -20
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecordDataLoader
|
4
|
+
class NullOutputAdapter
|
5
|
+
def self.with_output_options(_options)
|
6
|
+
yield new
|
7
|
+
end
|
8
|
+
|
9
|
+
def copy(table:, columns:, data:, row_numbers:); end
|
10
|
+
|
11
|
+
def insert(command); end
|
12
|
+
|
13
|
+
def write_command(command); end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "benchmark"
|
4
|
+
|
5
|
+
module ActiveRecordDataLoader
|
6
|
+
class TableLoader
|
7
|
+
def self.load_data(
|
8
|
+
total_rows:,
|
9
|
+
batch_size:,
|
10
|
+
logger:,
|
11
|
+
connection_handler:,
|
12
|
+
strategy:
|
13
|
+
)
|
14
|
+
new(logger: logger, connection_handler: connection_handler, strategy: strategy)
|
15
|
+
.load_data(batch_size, total_rows)
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(logger:, connection_handler:, strategy:)
|
19
|
+
@logger = logger
|
20
|
+
@connection_handler = connection_handler
|
21
|
+
@strategy = strategy
|
22
|
+
end
|
23
|
+
|
24
|
+
def load_data(batch_size, total_rows)
|
25
|
+
batch_count = (total_rows / batch_size.to_f).ceil
|
26
|
+
|
27
|
+
logger.info(
|
28
|
+
"[ActiveRecordDataLoader] "\
|
29
|
+
"Loading #{total_rows} row(s) into '#{strategy.table_name}' via #{strategy.name}. "\
|
30
|
+
"#{batch_size} row(s) per batch, #{batch_count} batch(es)."
|
31
|
+
)
|
32
|
+
total_time = Benchmark.realtime do
|
33
|
+
load_in_batches(batch_size, total_rows, batch_count)
|
34
|
+
end
|
35
|
+
logger.info(
|
36
|
+
"[ActiveRecordDataLoader] "\
|
37
|
+
"Completed loading #{total_rows} row(s) into '#{strategy.table_name}' "\
|
38
|
+
"in #{total_time} seconds."
|
39
|
+
)
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
attr_reader :strategy, :connection_handler, :logger
|
45
|
+
|
46
|
+
def load_in_batches(batch_size, total_rows, batch_count)
|
47
|
+
connection_handler.with_connection do |connection|
|
48
|
+
total_rows.times.each_slice(batch_size).with_index do |row_numbers, i|
|
49
|
+
time = Benchmark.realtime { strategy.load_batch(row_numbers, connection) }
|
50
|
+
|
51
|
+
logger.debug(
|
52
|
+
"[ActiveRecordDataLoader] "\
|
53
|
+
"Completed batch #{i + 1}/#{batch_count}, #{row_numbers.count} row(s) in #{time} seconds"
|
54
|
+
)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -2,31 +2,35 @@
|
|
2
2
|
|
3
3
|
require "active_record_data_loader/version"
|
4
4
|
require "active_record"
|
5
|
+
require "active_record_data_loader/errors"
|
5
6
|
require "active_record_data_loader/configuration"
|
6
7
|
require "active_record_data_loader/connection_handler"
|
7
8
|
require "active_record_data_loader/data_faker"
|
9
|
+
require "active_record_data_loader/active_record/list"
|
8
10
|
require "active_record_data_loader/active_record/per_row_value_cache"
|
9
11
|
require "active_record_data_loader/active_record/integer_value_generator"
|
10
12
|
require "active_record_data_loader/active_record/text_value_generator"
|
11
13
|
require "active_record_data_loader/active_record/enum_value_generator"
|
12
14
|
require "active_record_data_loader/active_record/datetime_value_generator"
|
13
|
-
require "active_record_data_loader/active_record/
|
14
|
-
require "active_record_data_loader/active_record/
|
15
|
-
require "active_record_data_loader/active_record/
|
15
|
+
require "active_record_data_loader/active_record/column_data_provider"
|
16
|
+
require "active_record_data_loader/active_record/belongs_to_data_provider"
|
17
|
+
require "active_record_data_loader/active_record/polymorphic_belongs_to_data_provider"
|
18
|
+
require "active_record_data_loader/active_record/unique_index_tracker"
|
16
19
|
require "active_record_data_loader/active_record/model_data_generator"
|
17
20
|
require "active_record_data_loader/dsl/belongs_to_association"
|
18
21
|
require "active_record_data_loader/dsl/polymorphic_association"
|
19
22
|
require "active_record_data_loader/dsl/model"
|
20
23
|
require "active_record_data_loader/dsl/definition"
|
21
|
-
require "active_record_data_loader/connection_output_adapter"
|
22
24
|
require "active_record_data_loader/file_output_adapter"
|
25
|
+
require "active_record_data_loader/null_output_adapter"
|
23
26
|
require "active_record_data_loader/copy_strategy"
|
24
27
|
require "active_record_data_loader/bulk_insert_strategy"
|
28
|
+
require "active_record_data_loader/table_loader"
|
25
29
|
require "active_record_data_loader/loader"
|
26
30
|
|
27
31
|
module ActiveRecordDataLoader
|
28
32
|
def self.define(config = ActiveRecordDataLoader.configuration, &block)
|
29
|
-
|
33
|
+
ActiveRecordDataLoader::Loader.new(
|
30
34
|
config,
|
31
35
|
ActiveRecordDataLoader::Dsl::Definition.new(config).tap { |l| l.instance_eval(&block) }
|
32
36
|
)
|
@@ -39,40 +43,4 @@ module ActiveRecordDataLoader
|
|
39
43
|
def self.configuration
|
40
44
|
@configuration ||= ActiveRecordDataLoader::Configuration.new
|
41
45
|
end
|
42
|
-
|
43
|
-
class LoaderProxy
|
44
|
-
def initialize(configuration, definition)
|
45
|
-
@configuration = configuration
|
46
|
-
@definition = definition
|
47
|
-
end
|
48
|
-
|
49
|
-
def load_data
|
50
|
-
ActiveRecordDataLoader::ActiveRecord::PerRowValueCache.clear
|
51
|
-
|
52
|
-
configuration.connection_handler.with_statement_timeout_for_output do
|
53
|
-
definition.models.map { |m| load_model(m) }
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
private
|
58
|
-
|
59
|
-
attr_reader :definition, :configuration
|
60
|
-
|
61
|
-
def load_model(model)
|
62
|
-
generator = ActiveRecordDataLoader::ActiveRecord::ModelDataGenerator.new(
|
63
|
-
model: model.klass,
|
64
|
-
column_settings: model.columns,
|
65
|
-
polymorphic_settings: model.polymorphic_associations,
|
66
|
-
belongs_to_settings: model.belongs_to_associations,
|
67
|
-
connection_factory: configuration.connection_factory
|
68
|
-
)
|
69
|
-
|
70
|
-
ActiveRecordDataLoader::Loader.load_data(
|
71
|
-
data_generator: generator,
|
72
|
-
batch_size: model.batch_size,
|
73
|
-
total_rows: model.row_count,
|
74
|
-
configuration: configuration
|
75
|
-
)
|
76
|
-
end
|
77
|
-
end
|
78
46
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_record_data_loader
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alejandro Beiderman
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-12-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -208,7 +208,7 @@ dependencies:
|
|
208
208
|
version: '0'
|
209
209
|
description: A utility to bulk load test data for performance testing.
|
210
210
|
email:
|
211
|
-
-
|
211
|
+
- active_record_data_loader@ossprojects.dev
|
212
212
|
executables:
|
213
213
|
- console
|
214
214
|
- setup
|
@@ -216,6 +216,7 @@ extensions: []
|
|
216
216
|
extra_rdoc_files: []
|
217
217
|
files:
|
218
218
|
- ".github/workflows/build.yml"
|
219
|
+
- ".github/workflows/codeql-analysis.yml"
|
219
220
|
- ".github/workflows/gem-push.yml"
|
220
221
|
- ".gitignore"
|
221
222
|
- ".rspec"
|
@@ -240,27 +241,31 @@ files:
|
|
240
241
|
- gemfiles/ffaker.gemfile
|
241
242
|
- gemfiles/rails.gemfile
|
242
243
|
- lib/active_record_data_loader.rb
|
243
|
-
- lib/active_record_data_loader/active_record/
|
244
|
-
- lib/active_record_data_loader/active_record/
|
244
|
+
- lib/active_record_data_loader/active_record/belongs_to_data_provider.rb
|
245
|
+
- lib/active_record_data_loader/active_record/column_data_provider.rb
|
245
246
|
- lib/active_record_data_loader/active_record/datetime_value_generator.rb
|
246
247
|
- lib/active_record_data_loader/active_record/enum_value_generator.rb
|
247
248
|
- lib/active_record_data_loader/active_record/integer_value_generator.rb
|
249
|
+
- lib/active_record_data_loader/active_record/list.rb
|
248
250
|
- lib/active_record_data_loader/active_record/model_data_generator.rb
|
249
251
|
- lib/active_record_data_loader/active_record/per_row_value_cache.rb
|
250
|
-
- lib/active_record_data_loader/active_record/
|
252
|
+
- lib/active_record_data_loader/active_record/polymorphic_belongs_to_data_provider.rb
|
251
253
|
- lib/active_record_data_loader/active_record/text_value_generator.rb
|
254
|
+
- lib/active_record_data_loader/active_record/unique_index_tracker.rb
|
252
255
|
- lib/active_record_data_loader/bulk_insert_strategy.rb
|
253
256
|
- lib/active_record_data_loader/configuration.rb
|
254
257
|
- lib/active_record_data_loader/connection_handler.rb
|
255
|
-
- lib/active_record_data_loader/connection_output_adapter.rb
|
256
258
|
- lib/active_record_data_loader/copy_strategy.rb
|
257
259
|
- lib/active_record_data_loader/data_faker.rb
|
258
260
|
- lib/active_record_data_loader/dsl/belongs_to_association.rb
|
259
261
|
- lib/active_record_data_loader/dsl/definition.rb
|
260
262
|
- lib/active_record_data_loader/dsl/model.rb
|
261
263
|
- lib/active_record_data_loader/dsl/polymorphic_association.rb
|
264
|
+
- lib/active_record_data_loader/errors.rb
|
262
265
|
- lib/active_record_data_loader/file_output_adapter.rb
|
263
266
|
- lib/active_record_data_loader/loader.rb
|
267
|
+
- lib/active_record_data_loader/null_output_adapter.rb
|
268
|
+
- lib/active_record_data_loader/table_loader.rb
|
264
269
|
- lib/active_record_data_loader/version.rb
|
265
270
|
- log/.keep
|
266
271
|
homepage:
|
@@ -1,20 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module ActiveRecordDataLoader
|
4
|
-
class ConnectionOutputAdapter
|
5
|
-
def needs_timeout_output?
|
6
|
-
false
|
7
|
-
end
|
8
|
-
|
9
|
-
def copy(connection:, table:, columns:, data:, row_numbers:)
|
10
|
-
raw_connection = connection.raw_connection
|
11
|
-
raw_connection.copy_data("COPY #{table} (#{columns}) FROM STDIN WITH (FORMAT CSV)") do
|
12
|
-
raw_connection.put_copy_data(data.join("\n"))
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
def insert(connection:, command:)
|
17
|
-
connection.insert(command)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|