inst_data_shipper 0.1.0.beta1 → 0.2.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 +139 -1
- data/db/migrate/{20240301090836_create_canvas_sync_sync_batches.rb → 20240301090836_create_inst_data_shipper_dump_batches.rb} +6 -3
- data/lib/inst_data_shipper/basic_dumper.rb +2 -2
- data/lib/inst_data_shipper/concerns/hooks.rb +18 -4
- data/lib/inst_data_shipper/data_sources/canvas_reports.rb +58 -21
- data/lib/inst_data_shipper/data_sources/local_tables.rb +35 -7
- data/lib/inst_data_shipper/destinations/base.rb +33 -6
- data/lib/inst_data_shipper/destinations/hosted_data.rb +63 -19
- data/lib/inst_data_shipper/destinations/s3.rb +1 -1
- data/lib/inst_data_shipper/dumper.rb +158 -50
- data/lib/inst_data_shipper/engine.rb +6 -0
- data/lib/inst_data_shipper/jobs/async_caller.rb +10 -2
- data/lib/inst_data_shipper/schema_builder.rb +99 -37
- data/lib/inst_data_shipper/version.rb +1 -1
- data/lib/inst_data_shipper.rb +13 -3
- data/spec/spec_helper.rb +2 -2
- metadata +22 -9
- data/lib/inst_data_shipper/jobs/basic_dump_job.rb +0 -11
- /data/app/models/{hosted_data_dumper → inst_data_shipper}/dump_batch.rb +0 -0
@@ -4,7 +4,7 @@ module InstDataShipper
|
|
4
4
|
include Concerns::Chunking
|
5
5
|
|
6
6
|
def chunk_data(generator, table:, extra: nil)
|
7
|
-
warehouse_name =
|
7
|
+
warehouse_name = table[:warehouse_name]
|
8
8
|
|
9
9
|
super(generator) do |batch, idx|
|
10
10
|
bits = [warehouse_name, extra, idx].compact
|
@@ -5,7 +5,7 @@ module InstDataShipper
|
|
5
5
|
define_hook :initialize_dump_batch
|
6
6
|
define_hook :finalize_dump_batch
|
7
7
|
|
8
|
-
def self.perform_dump(destinations
|
8
|
+
def self.perform_dump(destinations)
|
9
9
|
raise "Must subclass Dumper to use perform_dump" if self == Dumper
|
10
10
|
|
11
11
|
dumper = new(destinations)
|
@@ -14,48 +14,166 @@ module InstDataShipper
|
|
14
14
|
dumper.tracker
|
15
15
|
end
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
def self.define(include: [], schema: , &blk)
|
18
|
+
Class.new(self) do
|
19
|
+
include(*include)
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
21
|
+
define_method(:enqueue_tasks, &blk)
|
22
|
+
define_method(:schema) { schema }
|
23
|
+
end
|
24
24
|
end
|
25
25
|
|
26
|
-
def
|
27
|
-
|
26
|
+
def self.current(executor: nil)
|
27
|
+
cur_batch = Thread.current[CanvasSync::JobBatches::CURRENT_BATCH_THREAD_KEY]
|
28
|
+
ctx = cur_batch&.context || {}
|
29
|
+
return nil unless ctx[:origin_class].present? && ctx[:tracker_id].present?
|
30
|
+
|
31
|
+
clazz = ctx[:origin_class]
|
32
|
+
clazz = clazz.constantize if clazz.is_a?(String)
|
33
|
+
clazz.new(executor: executor)
|
28
34
|
end
|
29
35
|
|
36
|
+
public
|
37
|
+
|
30
38
|
def begin_dump
|
31
39
|
raise "Dump already begun" unless @raw_destinations.present?
|
32
40
|
|
33
|
-
@tracker = tracker = DumpBatch.create(job_class: self.class.to_s, status: 'in_progress')
|
41
|
+
@tracker = tracker = DumpBatch.create(job_class: self.class.to_s, genre: export_genre, status: 'in_progress')
|
42
|
+
|
43
|
+
@batch_context = context = {
|
44
|
+
# TODO Consider behavior if last is still running
|
45
|
+
incremental_since: last_successful_tracker&.created_at,
|
46
|
+
}
|
34
47
|
|
35
48
|
destinations.each do |dest|
|
36
|
-
dest.
|
49
|
+
dest.preinitialize_dump(context)
|
50
|
+
end
|
51
|
+
|
52
|
+
begin
|
53
|
+
begin
|
54
|
+
destinations.each do |dest|
|
55
|
+
dest.initialize_dump(context)
|
56
|
+
end
|
57
|
+
|
58
|
+
run_hook(:initialize_dump_batch, context)
|
59
|
+
ensure
|
60
|
+
@batch_context = nil
|
61
|
+
context[:tracker_id] = tracker.id
|
62
|
+
context[:origin_class] = batch_context[:origin_class] || self.class.to_s
|
63
|
+
context[:destinations] = @raw_destinations
|
64
|
+
end
|
65
|
+
|
66
|
+
Sidekiq::Batch.new.tap do |batch|
|
67
|
+
context[:root_bid] = batch.bid
|
68
|
+
tracker.update(batch_id: batch.bid)
|
69
|
+
|
70
|
+
batch.description = "HD #{export_genre} Export #{tracker.id} Root"
|
71
|
+
batch.context = context
|
72
|
+
batch.on(:success, "#{self.class}#finalize_dump")
|
73
|
+
batch.on(:death, "#{self.class}#cleanup_fatal_error!")
|
74
|
+
batch.jobs do
|
75
|
+
enqueue_tasks
|
76
|
+
rescue => ex
|
77
|
+
delayed :cleanup_fatal_error!
|
78
|
+
InstDataShipper.handle_suppressed_error(ex)
|
79
|
+
tracker.update(status: 'failed', exception: ex.message, backtrace: ex.backtrace.join("\n"))
|
80
|
+
end
|
81
|
+
end
|
82
|
+
rescue => ex
|
83
|
+
if context
|
84
|
+
batch ||= Sidekiq::Batch.new.tap do |batch|
|
85
|
+
batch.description = "HD #{export_genre} Export #{tracker.id} Early Failure Cleanup"
|
86
|
+
batch.context = context
|
87
|
+
batch.jobs do
|
88
|
+
delayed :cleanup_fatal_error!
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
tracker.update(status: 'failed', exception: ex.message, backtrace: ex.backtrace.join("\n"))
|
93
|
+
raise ex
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def tracker
|
98
|
+
@tracker ||= batch_context[:tracker_id].present? ? DumpBatch.find(batch_context[:tracker_id]) : nil
|
99
|
+
end
|
100
|
+
|
101
|
+
def last_successful_tracker
|
102
|
+
@last_successful_tracker ||= DumpBatch.where(job_class: self.class.to_s, genre: export_genre, status: 'completed').order(created_at: :desc).first
|
103
|
+
end
|
104
|
+
|
105
|
+
def export_genre
|
106
|
+
self.class.to_s
|
107
|
+
end
|
108
|
+
|
109
|
+
def origin_class
|
110
|
+
batch_context[:origin_class]&.constantize || self.class
|
111
|
+
end
|
112
|
+
|
113
|
+
def schema
|
114
|
+
return origin_class::SCHEMA if defined?(origin_class::SCHEMA)
|
115
|
+
raise NotImplementedError
|
116
|
+
end
|
117
|
+
|
118
|
+
def schema_digest
|
119
|
+
Digest::MD5.hexdigest(schema.to_json)[0...8]
|
120
|
+
end
|
121
|
+
|
122
|
+
def table_is_incremental?(table_def)
|
123
|
+
return false unless incremental_since.present?
|
124
|
+
|
125
|
+
# TODO Return false if table's schema changes
|
126
|
+
if (inc = table_def[:incremental]).present?
|
127
|
+
differ = inc[:if]
|
128
|
+
return !!incremental_since if differ.nil?
|
129
|
+
|
130
|
+
differ = :"#{differ}".to_proc if differ.is_a?(Symbol)
|
131
|
+
differ = instance_exec(&differ) if differ.is_a?(Proc)
|
132
|
+
return !!differ
|
37
133
|
end
|
38
134
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
135
|
+
false
|
136
|
+
end
|
137
|
+
|
138
|
+
def incremental_since
|
139
|
+
batch_context[:incremental_since]
|
140
|
+
end
|
141
|
+
|
142
|
+
def lookup_table_schema(*identifiers)
|
143
|
+
identifiers.compact.each do |ident|
|
144
|
+
if ident.is_a?(Hash)
|
145
|
+
key = ident.keys.first
|
146
|
+
value = ident.values.first
|
147
|
+
else
|
148
|
+
key = :warehouse_name
|
149
|
+
value = ident
|
150
|
+
end
|
151
|
+
|
152
|
+
value = Array(value).compact
|
153
|
+
|
154
|
+
schema[:tables].each do |ts|
|
155
|
+
return ts if value.include?(ts[key])
|
55
156
|
end
|
56
157
|
end
|
57
158
|
|
58
|
-
|
159
|
+
nil
|
160
|
+
end
|
161
|
+
|
162
|
+
def lookup_table_schema!(*identifiers)
|
163
|
+
lookup_table_schema(*identifiers) || raise("No table schema found for #{identifiers.inspect}")
|
164
|
+
end
|
165
|
+
|
166
|
+
protected
|
167
|
+
|
168
|
+
attr_reader :executor
|
169
|
+
|
170
|
+
def initialize(destinations = nil, executor: nil)
|
171
|
+
@raw_destinations = Array(destinations)
|
172
|
+
@executor = executor
|
173
|
+
end
|
174
|
+
|
175
|
+
def enqueue_tasks
|
176
|
+
raise NotImplementedError
|
59
177
|
end
|
60
178
|
|
61
179
|
def upload_data(table_def, extra: nil, &datagen)
|
@@ -96,7 +214,7 @@ module InstDataShipper
|
|
96
214
|
def finalize_dump(_status, _opts)
|
97
215
|
run_hook(:finalize_dump_batch)
|
98
216
|
|
99
|
-
|
217
|
+
destinations.each do |dest|
|
100
218
|
dest.finalize_dump
|
101
219
|
end
|
102
220
|
|
@@ -108,41 +226,31 @@ module InstDataShipper
|
|
108
226
|
|
109
227
|
run_hook(:finalize_dump_batch)
|
110
228
|
|
111
|
-
|
229
|
+
destinations.each do |dest|
|
112
230
|
dest.cleanup_fatal_error
|
113
|
-
rescue
|
231
|
+
rescue => ex
|
232
|
+
InstDataShipper.handle_suppressed_error(ex)
|
114
233
|
end
|
115
234
|
|
116
235
|
DumpBatch.find(batch_context[:tracker_id]).update(status: 'failed')
|
117
236
|
|
118
|
-
CanvasSync::JobBatches::Batch.delete_prematurely!(batch_context[:root_bid])
|
237
|
+
CanvasSync::JobBatches::Batch.delete_prematurely!(batch_context[:root_bid]) if batch_context[:root_bid].present?
|
119
238
|
end
|
120
239
|
|
121
240
|
# Helper Methods
|
122
241
|
|
123
|
-
def table_schemas
|
124
|
-
return origin_class::TABLE_SCHEMAS if defined?(origin_class::TABLE_SCHEMAS)
|
125
|
-
raise NotImplementedError
|
126
|
-
end
|
127
|
-
|
128
242
|
def delayed(mthd, *args, **kwargs)
|
129
|
-
AsyncCaller.perform_later(self.class.to_s, mthd.to_s, *args, **kwargs)
|
243
|
+
Jobs::AsyncCaller.perform_later(self.class.to_s, mthd.to_s, *args, **kwargs)
|
130
244
|
end
|
131
245
|
|
132
|
-
|
133
|
-
@tracker ||= batch_context[:tracker_id].present? ? DumpBatch.find(batch_context[:tracker_id]) : nil
|
134
|
-
end
|
246
|
+
delegate :working_dir, to: :executor
|
135
247
|
|
136
|
-
def
|
137
|
-
|
138
|
-
end
|
139
|
-
|
140
|
-
def origin_class
|
141
|
-
batch_context[:origin_class]&.constantize || self.class
|
248
|
+
def batch
|
249
|
+
Thread.current[CanvasSync::JobBatches::CURRENT_BATCH_THREAD_KEY]
|
142
250
|
end
|
143
251
|
|
144
|
-
def
|
145
|
-
|
252
|
+
def batch_context
|
253
|
+
@batch_context || batch&.context || {}
|
146
254
|
end
|
147
255
|
|
148
256
|
def destinations_for_table(table_def)
|
@@ -150,7 +258,7 @@ module InstDataShipper
|
|
150
258
|
end
|
151
259
|
|
152
260
|
def destinations
|
153
|
-
@destinations ||= (@raw_destinations || batch_context[:destinations]).map.with_index do |dest, i|
|
261
|
+
@destinations ||= (@raw_destinations.presence || batch_context[:destinations]).map.with_index do |dest, i|
|
154
262
|
dcls = InstDataShipper.resolve_destination(dest)
|
155
263
|
dcls.new("#{InstDataShipper.redis_prefix}:dump#{tracker.id}:dest#{i}", dest, self)
|
156
264
|
end
|
@@ -4,5 +4,11 @@ module InstDataShipper
|
|
4
4
|
class Engine < ::Rails::Engine
|
5
5
|
isolate_namespace InstDataShipper
|
6
6
|
|
7
|
+
initializer :append_migrations do |app|
|
8
|
+
config.paths["db/migrate"].expanded.each do |expanded_path|
|
9
|
+
app.config.paths["db/migrate"] << expanded_path
|
10
|
+
end
|
11
|
+
ActiveRecord::Migrator.migrations_paths = Rails.application.paths['db/migrate'].to_a
|
12
|
+
end
|
7
13
|
end
|
8
14
|
end
|
@@ -1,7 +1,14 @@
|
|
1
|
+
|
2
|
+
require "sidekiq"
|
3
|
+
|
1
4
|
module InstDataShipper
|
2
5
|
module Jobs
|
3
6
|
class AsyncCaller < InstDataShipper::Jobs::Base
|
4
|
-
sidekiq_options
|
7
|
+
sidekiq_options(retry: 0) if defined?(sidekiq_options)
|
8
|
+
|
9
|
+
def self.get_sidekiq_options
|
10
|
+
{ retry: 0 }
|
11
|
+
end
|
5
12
|
|
6
13
|
def self.call_from_pool(pool, clazz, method, *args, **kwargs)
|
7
14
|
pool.add_job(
|
@@ -12,7 +19,8 @@ module InstDataShipper
|
|
12
19
|
end
|
13
20
|
|
14
21
|
def perform(clazz, method, *args, **kwargs)
|
15
|
-
clazz.constantize
|
22
|
+
clazz = clazz.constantize if clazz.is_a?(String)
|
23
|
+
clazz.new(executor: self).send(method.to_sym, *args, **kwargs)
|
16
24
|
end
|
17
25
|
end
|
18
26
|
end
|
@@ -1,35 +1,59 @@
|
|
1
1
|
module InstDataShipper
|
2
|
+
# This class ends up fill two roles - Schema and Mapping.
|
3
|
+
# It makes for a clean API, but it's a little less canonical since, (eg) the S3 destination doesn't need column type annotations.
|
2
4
|
class SchemaBuilder
|
3
|
-
attr_reader :
|
5
|
+
attr_reader :schema
|
4
6
|
|
5
7
|
def initialize
|
6
|
-
@
|
8
|
+
@schema = {
|
9
|
+
tables: [],
|
10
|
+
}
|
7
11
|
end
|
8
12
|
|
9
13
|
def self.build(&block)
|
10
14
|
builder = new
|
11
15
|
builder.instance_exec(&block)
|
12
|
-
builder.
|
16
|
+
builder.schema
|
17
|
+
end
|
18
|
+
|
19
|
+
def version(version)
|
20
|
+
@schema[:version] = version
|
13
21
|
end
|
14
22
|
|
15
|
-
def
|
16
|
-
|
17
|
-
|
23
|
+
def extend_table_builder(&block)
|
24
|
+
@table_builder_class ||= Class.new(TableSchemaBuilder)
|
25
|
+
@table_builder_class.class_eval(&block)
|
26
|
+
end
|
18
27
|
|
28
|
+
def table(model_or_name, description = nil, model: nil, query: nil, **extra, &block)
|
19
29
|
tdef = {
|
30
|
+
warehouse_name: nil,
|
20
31
|
description: description,
|
21
|
-
model: model_or_name.is_a?(String) ? nil : model_or_name,
|
22
|
-
warehouse_name: as.to_s,
|
23
|
-
incremental: incremental,
|
24
32
|
columns: [],
|
25
|
-
|
33
|
+
|
34
|
+
model: model,
|
35
|
+
query: query,
|
36
|
+
**extra,
|
26
37
|
}
|
27
38
|
|
28
|
-
|
39
|
+
if model_or_name.is_a?(ActiveRecord::Relation)
|
40
|
+
raise "model specified twice" if model.present?
|
41
|
+
raise "query specified twice" if query.present?
|
42
|
+
|
43
|
+
tdef[:query] = model_or_name
|
44
|
+
tdef[:model] = model_or_name.model
|
45
|
+
elsif model_or_name.is_a?(Class) && model_or_name < ActiveRecord::Base
|
46
|
+
tdef[:warehouse_name] = model_or_name.table_name
|
47
|
+
tdef[:model] = model_or_name
|
48
|
+
else
|
49
|
+
tdef[:warehouse_name] = model_or_name
|
50
|
+
end
|
51
|
+
|
52
|
+
@table_builder_class.build(tdef, &block)
|
29
53
|
|
30
|
-
@tables << tdef
|
54
|
+
@schema[:tables] << tdef
|
31
55
|
|
32
|
-
|
56
|
+
tdef
|
33
57
|
end
|
34
58
|
|
35
59
|
class TableSchemaBuilder
|
@@ -46,48 +70,86 @@ module InstDataShipper
|
|
46
70
|
builder.columns
|
47
71
|
end
|
48
72
|
|
49
|
-
#
|
50
|
-
|
51
|
-
|
52
|
-
|
73
|
+
# def annotate(key, value)
|
74
|
+
# options[key] = value
|
75
|
+
# end
|
76
|
+
|
77
|
+
def version(version)
|
78
|
+
options[:version] = version
|
79
|
+
end
|
80
|
+
|
81
|
+
def incremental(scope=nil, **kwargs)
|
82
|
+
if (extras = kwargs.keys - %i[on if]).present?
|
83
|
+
raise ArgumentError, "Unsuppored options: #{extras.inspect}"
|
84
|
+
end
|
85
|
+
|
86
|
+
options[:incremental] = {
|
87
|
+
on: Array(kwargs[:on]),
|
88
|
+
scope: scope,
|
89
|
+
if: kwargs[:if],
|
90
|
+
}
|
91
|
+
end
|
92
|
+
|
93
|
+
def column(name, *args, refs: [], from: nil, **extra, &block)
|
94
|
+
from ||= name.to_s
|
53
95
|
|
54
96
|
cdef = {
|
55
|
-
|
56
|
-
|
57
|
-
|
97
|
+
warehouse_name: name.to_s,
|
98
|
+
from: from,
|
99
|
+
**extra,
|
58
100
|
}
|
59
101
|
|
60
|
-
[
|
61
|
-
|
62
|
-
k.each do |hk, hv|
|
63
|
-
cdef[hv] = kwargs.delete(hk) if kwargs.key?(hk)
|
64
|
-
end
|
65
|
-
elsif kwargs.key?(k)
|
66
|
-
cdef[k] = kwargs.delete(k)
|
67
|
-
end
|
102
|
+
if args[0].is_a?(Symbol)
|
103
|
+
cdef[:type] = args.shift()
|
68
104
|
end
|
69
105
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
k = (a.is_a?(String) && :description) || (a.is_a?(Symbol) && :type) || nil
|
74
|
-
raise ArgumentError, 'Unsupported Argument' if k.nil?
|
75
|
-
raise ArgumentError, "Duplicate Argument for #{k}" if cdef.key?(k)
|
106
|
+
if args[0].is_a?(String)
|
107
|
+
cdef[:description] = args.shift()
|
108
|
+
end
|
76
109
|
|
77
|
-
|
110
|
+
if args.present?
|
111
|
+
raise ArgumentError, "Received unexpected arguments: #{args.inspect}"
|
78
112
|
end
|
79
113
|
|
114
|
+
cdef[:references] = Array(refs)
|
115
|
+
|
80
116
|
if options[:model].is_a?(Class) && cdef[:local_name].to_s.ends_with?('_id')
|
81
117
|
rel_name = cdef[:local_name].to_s[0...-3]
|
82
118
|
refl = options[:model].reflections[rel_name]
|
83
119
|
cdef[:references] << "#{refl.klass}##{refl.options[:primary_key] || 'id'}" if refl.present? && !refl.polymorphic?
|
84
120
|
end
|
85
121
|
|
122
|
+
compiled_from = compile_transformer(from)
|
123
|
+
|
124
|
+
cdef[:block] = ->(row) {
|
125
|
+
value = instance_exec(row, &compiled_from)
|
126
|
+
value = instance_exec(value, row, &block) if block.present?
|
127
|
+
value
|
128
|
+
}
|
129
|
+
|
86
130
|
@columns << cdef
|
87
131
|
|
88
|
-
|
132
|
+
cdef
|
133
|
+
end
|
134
|
+
|
135
|
+
protected
|
136
|
+
|
137
|
+
def compile_transformer(from)
|
138
|
+
if from.present?
|
139
|
+
if from.is_a?(Symbol)
|
140
|
+
->(row) { row.send(from) }
|
141
|
+
elsif from.is_a?(Proc)
|
142
|
+
from
|
143
|
+
elsif from.is_a?(String)
|
144
|
+
->(row) { row[from] }
|
145
|
+
else
|
146
|
+
raise ArgumentError, "Invalid transformer: #{from.inspect}"
|
147
|
+
end
|
148
|
+
else
|
149
|
+
->(row) { row }
|
150
|
+
end
|
89
151
|
end
|
90
|
-
|
152
|
+
|
91
153
|
end
|
92
154
|
end
|
93
155
|
end
|
data/lib/inst_data_shipper.rb
CHANGED
@@ -23,15 +23,23 @@ module InstDataShipper
|
|
23
23
|
destination = @destination_aliases[type]
|
24
24
|
end
|
25
25
|
|
26
|
-
|
26
|
+
destination.constantize
|
27
27
|
end
|
28
28
|
|
29
29
|
def start_basic_dump(*args, **kwargs, &block)
|
30
30
|
BasicDumper.perform_dump(*args, **kwargs, &block)
|
31
31
|
end
|
32
32
|
|
33
|
+
def handle_suppressed_error(ex)
|
34
|
+
logger.error "Suppressed Error: #{ex.message}"
|
35
|
+
logger.error ex.backtrace.join("\n")
|
36
|
+
Raven.capture_exception(ex) if defined?(Raven)
|
37
|
+
Sentry.capture_exception(ex) if defined?(Sentry)
|
38
|
+
end
|
39
|
+
|
33
40
|
def logger
|
34
41
|
return @logger if defined? @logger
|
42
|
+
# TODO Annotate logs with DumpBatch ID
|
35
43
|
@logger = Logger.new(STDOUT)
|
36
44
|
@logger.level = Logger::DEBUG
|
37
45
|
@logger
|
@@ -42,7 +50,7 @@ module InstDataShipper
|
|
42
50
|
end
|
43
51
|
|
44
52
|
def redis_prefix
|
45
|
-
pfx = "
|
53
|
+
pfx = "ids"
|
46
54
|
pfx = "#{Apartment::Tenant.current}:#{pfx}" if defined?(Apartment)
|
47
55
|
pfx
|
48
56
|
end
|
@@ -66,6 +74,8 @@ Dir[File.dirname(__FILE__) + "/inst_data_shipper/destinations/*.rb"].each do |fi
|
|
66
74
|
basename = File.basename(file, ".rb")
|
67
75
|
next if basename == "base"
|
68
76
|
|
69
|
-
InstDataShipper.alias_destination(basename.dasherize, "InstDataShipper::Destinations::#{basename.
|
77
|
+
InstDataShipper.alias_destination(basename.dasherize, "InstDataShipper::Destinations::#{basename.camelize}")
|
70
78
|
end
|
71
79
|
|
80
|
+
require "inst_data_shipper/dumper"
|
81
|
+
require "inst_data_shipper/basic_dumper"
|
data/spec/spec_helper.rb
CHANGED
@@ -7,7 +7,7 @@ require File.expand_path("../dummy/config/environment.rb", __FILE__)
|
|
7
7
|
require "bundler/setup"
|
8
8
|
require 'rspec/rails'
|
9
9
|
require 'spec_helper'
|
10
|
-
require '
|
10
|
+
require 'factory_bot_rails'
|
11
11
|
require 'timecop'
|
12
12
|
require 'webmock/rspec'
|
13
13
|
require 'support/fake_canvas'
|
@@ -29,7 +29,7 @@ ActiveRecord::Migration.maintain_test_schema!
|
|
29
29
|
RSpec.configure do |config|
|
30
30
|
config.extend WithModel
|
31
31
|
|
32
|
-
config.include
|
32
|
+
config.include FactoryBot::Syntax::Methods
|
33
33
|
config.use_transactional_fixtures = true
|
34
34
|
config.infer_spec_type_from_file_location!
|
35
35
|
config.filter_rails_from_backtrace!
|
metadata
CHANGED
@@ -1,27 +1,27 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: inst_data_shipper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Instructure CustomDev
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-03-
|
11
|
+
date: 2024-03-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '6.0'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '6.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
@@ -360,6 +360,20 @@ dependencies:
|
|
360
360
|
- - ">="
|
361
361
|
- !ruby/object:Gem::Version
|
362
362
|
version: '0'
|
363
|
+
- !ruby/object:Gem::Dependency
|
364
|
+
name: faraday_middleware
|
365
|
+
requirement: !ruby/object:Gem::Requirement
|
366
|
+
requirements:
|
367
|
+
- - ">="
|
368
|
+
- !ruby/object:Gem::Version
|
369
|
+
version: '0'
|
370
|
+
type: :runtime
|
371
|
+
prerelease: false
|
372
|
+
version_requirements: !ruby/object:Gem::Requirement
|
373
|
+
requirements:
|
374
|
+
- - ">="
|
375
|
+
- !ruby/object:Gem::Version
|
376
|
+
version: '0'
|
363
377
|
description:
|
364
378
|
email:
|
365
379
|
- pseng@instructure.com
|
@@ -369,8 +383,8 @@ extra_rdoc_files: []
|
|
369
383
|
files:
|
370
384
|
- README.md
|
371
385
|
- Rakefile
|
372
|
-
- app/models/
|
373
|
-
- db/migrate/
|
386
|
+
- app/models/inst_data_shipper/dump_batch.rb
|
387
|
+
- db/migrate/20240301090836_create_inst_data_shipper_dump_batches.rb
|
374
388
|
- lib/inst_data_shipper.rb
|
375
389
|
- lib/inst_data_shipper/basic_dumper.rb
|
376
390
|
- lib/inst_data_shipper/concerns/hooks.rb
|
@@ -385,7 +399,6 @@ files:
|
|
385
399
|
- lib/inst_data_shipper/engine.rb
|
386
400
|
- lib/inst_data_shipper/jobs/async_caller.rb
|
387
401
|
- lib/inst_data_shipper/jobs/base.rb
|
388
|
-
- lib/inst_data_shipper/jobs/basic_dump_job.rb
|
389
402
|
- lib/inst_data_shipper/record.rb
|
390
403
|
- lib/inst_data_shipper/schema_builder.rb
|
391
404
|
- lib/inst_data_shipper/version.rb
|
@@ -422,9 +435,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
422
435
|
version: '0'
|
423
436
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
424
437
|
requirements:
|
425
|
-
- - "
|
438
|
+
- - ">="
|
426
439
|
- !ruby/object:Gem::Version
|
427
|
-
version:
|
440
|
+
version: '0'
|
428
441
|
requirements: []
|
429
442
|
rubygems_version: 3.1.6
|
430
443
|
signing_key:
|
File without changes
|