inst_data_shipper 0.2.8 → 0.2.10.beta1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 75cf640fef52a5846408607d92b4cbeaedefec03e733542508c17ea245b7d3cf
4
- data.tar.gz: 07bae82a7237af5d1720503a45f35208711c299c05485adc02f045de65462e49
3
+ metadata.gz: da87b45d1f05a92db75d71ce6fa414c4d30872bb2fe970f032151e0f0997378f
4
+ data.tar.gz: 25419ac15df71e1ec6e0d4b9dd0b3aca94ef5c812265386ce375cfb80c23d4f2
5
5
  SHA512:
6
- metadata.gz: 81cb6a9801d399f0952f74083506938f9e3fd68b966a1afa4c24cbd9df393659ef01c1c4ae5cbd3a526809c2c1214966b798a9e30727d059fdfc00730a6931a1
7
- data.tar.gz: 39930b880f8acd83230fda54bf559c9deb7fc95a31039212b7ab92eb81cc69b270cc0ed6e28237f0449a6e314146082d4c1f3203cc176eacf0b8c75dc6d3407f
6
+ metadata.gz: 20a9ffd8cf6934beb86d8e52048707263ebf77a8f43f071899649851d345aeecd789e7029baa0a31cefd6785cb0e0dc4c260f09dedaba6c83d09008805cd2235
7
+ data.tar.gz: b280466a01b6986bf418e978fb8be1edc7fd4d783d72173055d3deb78790296ffb6d04bd74416d2b0c6947f74d9defd9f6d8897b6b1e9b17fb6b1c6cb380bdd4
@@ -45,6 +45,13 @@ module InstDataShipper
45
45
  end
46
46
  end
47
47
  end
48
+
49
+ class MismatchingRowCounts < StandardError
50
+ def initialize(table_def={}, expected_row_count=0, processed_row_count=0)
51
+ message = "#{table_def[:warehouse_name]} expected #{expected_row_count} rows, processed #{processed_row_count} rows in local table."
52
+ super(message)
53
+ end
54
+ end
48
55
  end
49
56
  end
50
57
  end
@@ -11,23 +11,46 @@ module InstDataShipper
11
11
 
12
12
  table_def = lookup_table_schema!(schema_name, { model: model })
13
13
 
14
- inner_block = ->(file) {
15
- query = model.all
16
- query = _resolve_model_query(query, table_def[:query])
17
-
18
- if table_is_incremental?(table_def)
19
- query = _resolve_model_query(
20
- query,
21
- table_def.dig(:incremental, :scope),
22
- string: ->(query, column) { query.where("#{column} > ?", incremental_since) },
23
- default: "updated_at",
24
- )
25
- end
26
-
27
- process_raw_data_enumerator(table_def, query.find_each, file)
14
+ upload_data(table_def, &make_data_factory(model, table_def))
15
+ end
16
+
17
+ def make_data_factory(model, table_def)
18
+ ->(file) {
19
+ query = build_query(model, table_def)
20
+ expected_row_count, processed_row_count = iterate_query(query, table_def, file)
21
+ raise MismatchingRowCounts.new(table_def, expected_row_count, processed_row_count) if !acceptable_row_counts_mismatch?(expected_row_count, processed_row_count)
28
22
  }
23
+ end
29
24
 
30
- upload_data(table_def, &inner_block)
25
+ def build_query(model, table_def)
26
+ query = model.all
27
+ query = _resolve_model_query(query, table_def[:query])
28
+
29
+ if table_is_incremental?(table_def)
30
+ query = _resolve_model_query(
31
+ query,
32
+ table_def.dig(:incremental, :scope),
33
+ string: ->(query, column) { query.where("#{column} > ?", incremental_since) },
34
+ default: "updated_at",
35
+ )
36
+ end
37
+ query
38
+ end
39
+
40
+ def iterate_query(query, table_def, file)
41
+ processed_row_count = 0
42
+ expected_row_count = query.count
43
+
44
+ process_raw_data_enumerator(table_def, query.find_each.lazy.map { |x| processed_row_count += 1; x }, file)
45
+ [expected_row_count, processed_row_count]
46
+ end
47
+ #
48
+ # The count of rows in the database and the exported files may not always match. We accept a small range difference
49
+ def acceptable_row_counts_mismatch?(expected_row_count, processed_row_count, variation: 0.01)
50
+ return true if expected_row_count.nil?
51
+
52
+ expected_row_count = expected_row_count.to_f
53
+ expected_row_count * (1 - variation) <= processed_row_count && processed_row_count <= expected_row_count * (1 + variation)
31
54
  end
32
55
 
33
56
  private
@@ -47,7 +70,6 @@ module InstDataShipper
47
70
  raise "Invalid query: #{query.inspect}"
48
71
  end
49
72
  end
50
-
51
73
  end
52
74
  end
53
75
  end
@@ -272,7 +272,6 @@ module InstDataShipper
272
272
  dest.upload_data_chunk(table_def, chunk)
273
273
  end
274
274
  end
275
-
276
275
  # TODO Consider how to handle errors in this method.
277
276
  # Retriable errors must not be allowed to bubble - if dest 1 succeeds and dest 2 fails, dest 1 must not be retried
278
277
  # Each destination should handle its own retries
File without changes
@@ -1,3 +1,3 @@
1
1
  module InstDataShipper
2
- VERSION = "0.2.8".freeze
2
+ VERSION = "0.2.10.beta1".freeze
3
3
  end
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe InstDataShipper::DataSources::LocalTables do
4
+ let(:dumper) do
5
+ dumper = TestDumper.new
6
+ dumper.extend(InstDataShipper::DataSources::LocalTables)
7
+ dumper
8
+ end
9
+
10
+ describe "#import_local_table" do
11
+ before do
12
+ allow(dumper).to receive(:iterate_query).and_return([5, 5])
13
+ end
14
+
15
+ it "counts expected rows and processes data" do
16
+ allow(dumper).to receive(:upload_data) do |td, &make_data_factory|
17
+ make_data_factory.call("filename")
18
+ end
19
+
20
+ expect { dumper.send(:_delayed_import_local_table, InstDataShipper::DumpBatch, schema_name: "local_table_test") }.not_to raise_error
21
+ end
22
+ end
23
+
24
+ describe '#make_data_factory' do
25
+ before do
26
+ allow(dumper).to receive(:build_query).and_return(true)
27
+ end
28
+ it 'raises an error when expected row count does not match the processed count' do
29
+ allow(dumper).to receive(:iterate_query).and_return([50, 100])
30
+ expect { dumper.make_data_factory(InstDataShipper::DumpBatch, {}).call("filename") }.to raise_error(InstDataShipper::DataSources::Base::MismatchingRowCounts)
31
+ end
32
+
33
+ it 'does not raise an error when the expected count matches the processed count' do
34
+ allow(dumper).to receive(:iterate_query).and_return([50, 50])
35
+ expect { dumper.make_data_factory(InstDataShipper::DumpBatch, {}).call("filename") }.not_to raise_error(InstDataShipper::DataSources::Base::MismatchingRowCounts)
36
+ end
37
+ end
38
+
39
+ describe '#acceptable_row_counts_mismatch?' do
40
+ it 'returns whether the counts are within the range or not' do
41
+ expect(dumper.acceptable_row_counts_mismatch?(100, 105, variation: 0.01)).to eq(false)
42
+ expect(dumper.acceptable_row_counts_mismatch?(100, 100, variation: 0.01)).to eq(true)
43
+ expect(dumper.acceptable_row_counts_mismatch?(100, 105, variation: 0.1)).to eq(true)
44
+ expect(dumper.acceptable_row_counts_mismatch?(100, 111, variation: 0.1)).to eq(false)
45
+ end
46
+
47
+ it 'returns false for the upper/lower bound' do
48
+ # current implementation accepts the upper / lower bound
49
+ expect(dumper.acceptable_row_counts_mismatch?(100, 101, variation: 0.01)).to eq(true)
50
+ expect(dumper.acceptable_row_counts_mismatch?(100, 99, variation: 0.01)).to eq(true)
51
+ end
52
+
53
+ it 'returns true for 0 rows expected and 0 rows processed' do
54
+ expect(dumper.acceptable_row_counts_mismatch?(0, 0, variation: 0.01)).to eq(true)
55
+ end
56
+ end
57
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: inst_data_shipper
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.8
4
+ version: 0.2.10.beta1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Instructure CustomDev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-11-04 00:00:00.000000000 Z
11
+ date: 2026-01-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -361,6 +361,7 @@ files:
361
361
  - lib/inst_data_shipper/record.rb
362
362
  - lib/inst_data_shipper/schema_builder.rb
363
363
  - lib/inst_data_shipper/version.rb
364
+ - spec/inst_data_shipper/data_sources/local_tables.rb
364
365
  - spec/inst_data_shipper/destinations/hosted_data_spec.rb
365
366
  - spec/inst_data_shipper/dumper_spec.rb
366
367
  - spec/internal/app/assets/config/manifest.js
@@ -396,6 +397,7 @@ signing_key:
396
397
  specification_version: 4
397
398
  summary: Gem for uploading app data to Instructure CustomDev Hosted Data tooling
398
399
  test_files:
400
+ - spec/inst_data_shipper/data_sources/local_tables.rb
399
401
  - spec/inst_data_shipper/destinations/hosted_data_spec.rb
400
402
  - spec/inst_data_shipper/dumper_spec.rb
401
403
  - spec/internal/app/assets/config/manifest.js