sq-dbsync 1.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.
- data/HISTORY.md +5 -0
- data/LICENSE +14 -0
- data/README.md +218 -0
- data/lib/sq/dbsync/all_tables_plan.rb +51 -0
- data/lib/sq/dbsync/batch_load_action.rb +95 -0
- data/lib/sq/dbsync/config.rb +12 -0
- data/lib/sq/dbsync/consistency_verifier.rb +70 -0
- data/lib/sq/dbsync/database/common.rb +91 -0
- data/lib/sq/dbsync/database/connection.rb +23 -0
- data/lib/sq/dbsync/database/mysql.rb +163 -0
- data/lib/sq/dbsync/database/postgres.rb +77 -0
- data/lib/sq/dbsync/error_handler.rb +59 -0
- data/lib/sq/dbsync/example_record_destroyer.rb +77 -0
- data/lib/sq/dbsync/incremental_load_action.rb +95 -0
- data/lib/sq/dbsync/load_action.rb +156 -0
- data/lib/sq/dbsync/loggers.rb +135 -0
- data/lib/sq/dbsync/manager.rb +241 -0
- data/lib/sq/dbsync/pipeline/simple_context.rb +15 -0
- data/lib/sq/dbsync/pipeline/threaded_context.rb +95 -0
- data/lib/sq/dbsync/pipeline.rb +80 -0
- data/lib/sq/dbsync/refresh_recent_load_action.rb +71 -0
- data/lib/sq/dbsync/schema_maker.rb +87 -0
- data/lib/sq/dbsync/static_table_plan.rb +42 -0
- data/lib/sq/dbsync/table_registry.rb +75 -0
- data/lib/sq/dbsync/tempfile_factory.rb +41 -0
- data/lib/sq/dbsync/version.rb +5 -0
- data/lib/sq/dbsync.rb +9 -0
- data/spec/acceptance/loading_spec.rb +237 -0
- data/spec/acceptance_helper.rb +2 -0
- data/spec/database_helper.rb +86 -0
- data/spec/integration/all_tables_plan_spec.rb +36 -0
- data/spec/integration/batch_load_action_spec.rb +229 -0
- data/spec/integration/consistency_verifier_spec.rb +54 -0
- data/spec/integration/database_connection_spec.rb +61 -0
- data/spec/integration/incremental_load_action_spec.rb +196 -0
- data/spec/integration/manager_spec.rb +109 -0
- data/spec/integration/schema_maker_spec.rb +119 -0
- data/spec/integration_helper.rb +43 -0
- data/spec/spec_helper.rb +27 -0
- data/spec/unit/config_spec.rb +18 -0
- data/spec/unit/error_handler_spec.rb +52 -0
- data/spec/unit/pipeline_spec.rb +42 -0
- data/spec/unit/stream_logger_spec.rb +33 -0
- data/spec/unit_helper.rb +1 -0
- data/sq-dbsync.gemspec +32 -0
- metadata +188 -0
@@ -0,0 +1,119 @@
|
|
1
|
+
require 'integration_helper'
|
2
|
+
|
3
|
+
require 'sq/dbsync/schema_maker'
|
4
|
+
require 'ostruct'
|
5
|
+
|
6
|
+
describe SQD::SchemaMaker do
|
7
|
+
let(:target) { test_target }
|
8
|
+
|
9
|
+
it 'creates a table with a compound index' do
|
10
|
+
index = {
|
11
|
+
index_on_col1: { columns: [:col1, :col2], unique: false }
|
12
|
+
}
|
13
|
+
|
14
|
+
plan = {
|
15
|
+
prefixed_table_name: :test_table,
|
16
|
+
table_name: :test_table,
|
17
|
+
columns: [:col1, :col2],
|
18
|
+
indexes: index,
|
19
|
+
schema: {
|
20
|
+
col1: { db_type: 'varchar(255)', primary_key: true },
|
21
|
+
col2: { db_type: 'varchar(255)', primary_key: false }
|
22
|
+
}
|
23
|
+
}
|
24
|
+
|
25
|
+
described_class.create_table(target, OpenStruct.new(plan))
|
26
|
+
|
27
|
+
target.indexes(:test_table).should == index
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'defaults primary key to id' do
|
31
|
+
plan = {
|
32
|
+
prefixed_table_name: :test_table,
|
33
|
+
table_name: :test_table,
|
34
|
+
columns: [:id],
|
35
|
+
schema: { id: {db_type: 'varchar(255)', primary_key: false }}
|
36
|
+
}
|
37
|
+
|
38
|
+
described_class.create_table(target, OpenStruct.new(plan))
|
39
|
+
|
40
|
+
target.schema(:test_table)[0][1][:primary_key].should == true
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'allows primary key override' do
|
44
|
+
plan = {
|
45
|
+
prefixed_table_name: :test_table,
|
46
|
+
table_name: :test_table,
|
47
|
+
columns: [:id, :col1],
|
48
|
+
primary_key: [:id, :col1],
|
49
|
+
schema: {
|
50
|
+
id: {db_type: 'varchar(255)', primary_key: false },
|
51
|
+
col1: {db_type: 'varchar(255)', primary_key: false }
|
52
|
+
}
|
53
|
+
}
|
54
|
+
|
55
|
+
described_class.create_table(target, OpenStruct.new(plan))
|
56
|
+
|
57
|
+
target.schema(:test_table)[0][1][:primary_key].should == true
|
58
|
+
target.schema(:test_table)[1][1][:primary_key].should == true
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
it 'creates a table with an enum column' do
|
63
|
+
plan = {
|
64
|
+
prefixed_table_name: :test_table,
|
65
|
+
table_name: :test_table,
|
66
|
+
columns: [:col1],
|
67
|
+
db_types: {:col1 => [:enum, %w(a b)]},
|
68
|
+
schema: { col1: { primary_key: true }}
|
69
|
+
}
|
70
|
+
|
71
|
+
described_class.create_table(target, OpenStruct.new(plan))
|
72
|
+
|
73
|
+
target.schema(:test_table)[0][1][:db_type].should == "enum('a','b')"
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'creates a table with non-id primary key' do
|
77
|
+
plan = {
|
78
|
+
prefixed_table_name: :test_table,
|
79
|
+
table_name: :test_table,
|
80
|
+
columns: [:col1],
|
81
|
+
schema: { col1: { db_type: 'varchar(255)', primary_key: true }}
|
82
|
+
}
|
83
|
+
|
84
|
+
described_class.create_table(target, OpenStruct.new(plan))
|
85
|
+
|
86
|
+
target.schema(:test_table)[0][1][:primary_key].should == true
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'creates a table with a not-null column' do
|
90
|
+
plan = {
|
91
|
+
prefixed_table_name: :test_table,
|
92
|
+
table_name: :test_table,
|
93
|
+
columns: [:col1],
|
94
|
+
db_types: {:col1 => ['int(1) not null']},
|
95
|
+
schema: { col1: { primary_key: true }}
|
96
|
+
}
|
97
|
+
|
98
|
+
described_class.create_table(target, OpenStruct.new(plan))
|
99
|
+
|
100
|
+
target.schema(:test_table)[0][1][:allow_null].should == false
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'creates a table with a composite primary key' do
|
104
|
+
plan = {
|
105
|
+
prefixed_table_name: :test_table,
|
106
|
+
table_name: :test_table,
|
107
|
+
columns: [:a, :b],
|
108
|
+
schema: {
|
109
|
+
a: { db_type: 'int', primary_key: true },
|
110
|
+
b: { db_type: 'int', primary_key: true }
|
111
|
+
}
|
112
|
+
}
|
113
|
+
|
114
|
+
described_class.create_table(target, OpenStruct.new(plan))
|
115
|
+
|
116
|
+
target.schema(:test_table)[0][1][:primary_key].should == true
|
117
|
+
target.schema(:test_table)[1][1][:primary_key].should == true
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'database_helper'
|
3
|
+
|
4
|
+
def create_source_table_with(*rows)
|
5
|
+
# Total hack to allow source db to be passed as optional first argument.
|
6
|
+
if rows[0].is_a?(Hash)
|
7
|
+
source_db = source
|
8
|
+
else
|
9
|
+
source_db = rows.shift
|
10
|
+
end
|
11
|
+
table_name = :test_table
|
12
|
+
|
13
|
+
source_db.create_table! table_name do
|
14
|
+
primary_key :id
|
15
|
+
String :col1
|
16
|
+
String :pii
|
17
|
+
DateTime :updated_at
|
18
|
+
DateTime :created_at
|
19
|
+
DateTime :imported_at
|
20
|
+
end
|
21
|
+
|
22
|
+
rows.each do |row|
|
23
|
+
source_db[table_name].insert(row)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def setup_target_table(last_synced_at)
|
28
|
+
target.create_table! :test_table do
|
29
|
+
Integer :id
|
30
|
+
String :col1
|
31
|
+
DateTime :updated_at
|
32
|
+
DateTime :created_at
|
33
|
+
end
|
34
|
+
|
35
|
+
target.add_index :test_table, :id, :unique => true
|
36
|
+
|
37
|
+
registry.ensure_storage_exists
|
38
|
+
registry.set(:test_table,
|
39
|
+
last_synced_at: last_synced_at,
|
40
|
+
last_row_at: last_synced_at,
|
41
|
+
last_batch_synced_at: last_synced_at
|
42
|
+
)
|
43
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
ENV['APP_ENV'] = 'test'
|
2
|
+
|
3
|
+
if ENV['COVERAGE'] != "0" && RUBY_PLATFORM != 'java'
|
4
|
+
require 'simplecov'
|
5
|
+
|
6
|
+
class SimpleCov::Formatter::MergedFormatter
|
7
|
+
def format(result)
|
8
|
+
SimpleCov::Formatter::HTMLFormatter.new.format(result)
|
9
|
+
File.open("coverage/covered_percent", "w") do |f|
|
10
|
+
f.puts result.source_files.covered_percent.to_i
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
SimpleCov.formatter = SimpleCov::Formatter::MergedFormatter
|
16
|
+
SimpleCov.start do
|
17
|
+
add_filter "/config/"
|
18
|
+
add_filter "/spec/"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
module Sq
|
23
|
+
module Dbsync
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
SQD = Sq::Dbsync
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'unit_helper'
|
2
|
+
|
3
|
+
require 'sq/dbsync/config'
|
4
|
+
|
5
|
+
describe Sq::Dbsync::Config do
|
6
|
+
it 'provides a default error handler' do
|
7
|
+
described_class.make({})[:error_handler].should respond_to(:call)
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'provides a default clock' do
|
11
|
+
described_class.make({})[:clock].().should be_instance_of(Time)
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'provides a default logger' do
|
15
|
+
described_class.make({})[:logger].should \
|
16
|
+
be_a_kind_of(Sq::Dbsync::Loggers::Abstract)
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'unit_helper'
|
2
|
+
|
3
|
+
require 'sq/dbsync/error_handler'
|
4
|
+
|
5
|
+
describe Sq::Dbsync::ErrorHandler do
|
6
|
+
let(:config) { {
|
7
|
+
sources: {
|
8
|
+
db_a: { password: 'redactme' },
|
9
|
+
db_b: { password: 'alsome' },
|
10
|
+
db_c: {}
|
11
|
+
},
|
12
|
+
target: { password: 'thistoo'},
|
13
|
+
}}
|
14
|
+
|
15
|
+
describe '#wrap' do
|
16
|
+
it 'redacts message' do
|
17
|
+
called = nil
|
18
|
+
config[:error_handler] = ->(ex) { called = ex }
|
19
|
+
handler = described_class.new(config)
|
20
|
+
->{
|
21
|
+
handler.wrap do
|
22
|
+
raise "redactme alsome thistoo notthis"
|
23
|
+
end
|
24
|
+
}.should raise_error("REDACTED REDACTED REDACTED notthis")
|
25
|
+
called.message.should == "REDACTED REDACTED REDACTED notthis"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '#notify_error' do
|
30
|
+
it 'includes tag in exception message' do
|
31
|
+
called = nil
|
32
|
+
config[:error_handler] = ->(ex) { called = ex }
|
33
|
+
handler = described_class.new(config)
|
34
|
+
|
35
|
+
handler.notify_error(:test_table, RuntimeError.new('hello'))
|
36
|
+
|
37
|
+
called.message.should include('[test_table]')
|
38
|
+
called.message.should include('hello')
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'redacts message' do
|
42
|
+
called = nil
|
43
|
+
config[:error_handler] = ->(ex) { called = ex }
|
44
|
+
handler = described_class.new(config)
|
45
|
+
|
46
|
+
handler.notify_error(:test_table,
|
47
|
+
RuntimeError.new("redactme alsome thistoo notthis"))
|
48
|
+
|
49
|
+
called.message.should include("REDACTED REDACTED REDACTED notthis")
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'unit_helper'
|
2
|
+
|
3
|
+
require 'sq/dbsync/pipeline'
|
4
|
+
|
5
|
+
shared_examples_for 'a pipeline' do
|
6
|
+
it 'passes tasks through each stage' do
|
7
|
+
ret = SQD::Pipeline.new([3, 4],
|
8
|
+
->(x) { x * x },
|
9
|
+
->(x) { x + x }
|
10
|
+
).run(described_class)
|
11
|
+
ret.should == [18, 32]
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'returns errors' do
|
15
|
+
ret = SQD::Pipeline.new([1],
|
16
|
+
->(x) { raise("fail") }
|
17
|
+
).run(described_class)
|
18
|
+
ret.length.should == 1
|
19
|
+
ret = ret[0]
|
20
|
+
ret.should be_instance_of(SQD::Pipeline::Failure)
|
21
|
+
ret.wrapped_exception.should be_instance_of(RuntimeError)
|
22
|
+
ret.wrapped_exception.message.should == "fail"
|
23
|
+
ret.task.should == 1
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'handles errors in the middle of a pipeline' do
|
27
|
+
ret = SQD::Pipeline.new([1, 2],
|
28
|
+
->(x) { x == 1 ? 10 : raise("fail") },
|
29
|
+
->(x) { x + 1 }
|
30
|
+
).run(described_class)
|
31
|
+
ret[0].should == 11
|
32
|
+
ret[1].should be_instance_of(SQD::Pipeline::Failure)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe SQD::Pipeline::ThreadedContext do
|
37
|
+
it_should_behave_like 'a pipeline'
|
38
|
+
end
|
39
|
+
|
40
|
+
describe SQD::Pipeline::SimpleContext do
|
41
|
+
it_should_behave_like 'a pipeline'
|
42
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'unit_helper'
|
2
|
+
|
3
|
+
require 'sq/dbsync/loggers'
|
4
|
+
|
5
|
+
describe SQD::Loggers::Stream do
|
6
|
+
let(:buffer) { "" }
|
7
|
+
let(:logger) { described_class.new(StringIO.new(buffer)) }
|
8
|
+
|
9
|
+
it 'logs :finished when no exception is raised' do
|
10
|
+
logger.measure(:ok) {}
|
11
|
+
buffer.should include('finished')
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'logs :failed when exception is raised' do
|
15
|
+
lambda {
|
16
|
+
logger.measure(:fail) { raise("fail") }
|
17
|
+
}.should raise_error("fail")
|
18
|
+
buffer.should include('failed')
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'logs error message when exception is raised' do
|
22
|
+
lambda {
|
23
|
+
logger.measure(:fail) { raise("oh no") }
|
24
|
+
}.should raise_error("oh no")
|
25
|
+
buffer.should include('oh no')
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
it 'logs specified strings' do
|
30
|
+
logger.log('logging is good')
|
31
|
+
buffer.should include('logging is good')
|
32
|
+
end
|
33
|
+
end
|
data/spec/unit_helper.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'spec_helper'
|
data/sq-dbsync.gemspec
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/sq/dbsync/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Xavier Shay"]
|
6
|
+
gem.email = ["xavier@squareup.com"]
|
7
|
+
gem.description =
|
8
|
+
%q{Column based, timestamp replication of MySQL and Postgres databases.}
|
9
|
+
gem.summary = %q{
|
10
|
+
Column based, timestamp replication of MySQL and Postgres databases. Uses
|
11
|
+
Ruby for the glue code but pushes the heavy lifting on to the database.
|
12
|
+
}
|
13
|
+
gem.homepage = "http://github.com/square/sq-dbsync"
|
14
|
+
|
15
|
+
gem.executables = []
|
16
|
+
gem.files = Dir.glob("{spec,lib}/**/*.rb") + %w(
|
17
|
+
README.md
|
18
|
+
HISTORY.md
|
19
|
+
LICENSE
|
20
|
+
sq-dbsync.gemspec
|
21
|
+
)
|
22
|
+
gem.test_files = Dir.glob("spec/**/*.rb")
|
23
|
+
gem.name = "sq-dbsync"
|
24
|
+
gem.require_paths = ["lib"]
|
25
|
+
gem.version = Sq::Dbsync::VERSION
|
26
|
+
gem.has_rdoc = false
|
27
|
+
gem.add_development_dependency 'rspec', '~> 2.0'
|
28
|
+
gem.add_development_dependency 'rake'
|
29
|
+
gem.add_development_dependency 'simplecov'
|
30
|
+
gem.add_development_dependency 'cane'
|
31
|
+
gem.add_dependency 'sequel'
|
32
|
+
end
|
metadata
ADDED
@@ -0,0 +1,188 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sq-dbsync
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Xavier Shay
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-02-23 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '2.0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '2.0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rake
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: simplecov
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: cane
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: sequel
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :runtime
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
description: Column based, timestamp replication of MySQL and Postgres databases.
|
95
|
+
email:
|
96
|
+
- xavier@squareup.com
|
97
|
+
executables: []
|
98
|
+
extensions: []
|
99
|
+
extra_rdoc_files: []
|
100
|
+
files:
|
101
|
+
- spec/acceptance/loading_spec.rb
|
102
|
+
- spec/acceptance_helper.rb
|
103
|
+
- spec/database_helper.rb
|
104
|
+
- spec/integration/all_tables_plan_spec.rb
|
105
|
+
- spec/integration/batch_load_action_spec.rb
|
106
|
+
- spec/integration/consistency_verifier_spec.rb
|
107
|
+
- spec/integration/database_connection_spec.rb
|
108
|
+
- spec/integration/incremental_load_action_spec.rb
|
109
|
+
- spec/integration/manager_spec.rb
|
110
|
+
- spec/integration/schema_maker_spec.rb
|
111
|
+
- spec/integration_helper.rb
|
112
|
+
- spec/spec_helper.rb
|
113
|
+
- spec/unit/config_spec.rb
|
114
|
+
- spec/unit/error_handler_spec.rb
|
115
|
+
- spec/unit/pipeline_spec.rb
|
116
|
+
- spec/unit/stream_logger_spec.rb
|
117
|
+
- spec/unit_helper.rb
|
118
|
+
- lib/sq/dbsync/all_tables_plan.rb
|
119
|
+
- lib/sq/dbsync/batch_load_action.rb
|
120
|
+
- lib/sq/dbsync/config.rb
|
121
|
+
- lib/sq/dbsync/consistency_verifier.rb
|
122
|
+
- lib/sq/dbsync/database/common.rb
|
123
|
+
- lib/sq/dbsync/database/connection.rb
|
124
|
+
- lib/sq/dbsync/database/mysql.rb
|
125
|
+
- lib/sq/dbsync/database/postgres.rb
|
126
|
+
- lib/sq/dbsync/error_handler.rb
|
127
|
+
- lib/sq/dbsync/example_record_destroyer.rb
|
128
|
+
- lib/sq/dbsync/incremental_load_action.rb
|
129
|
+
- lib/sq/dbsync/load_action.rb
|
130
|
+
- lib/sq/dbsync/loggers.rb
|
131
|
+
- lib/sq/dbsync/manager.rb
|
132
|
+
- lib/sq/dbsync/pipeline/simple_context.rb
|
133
|
+
- lib/sq/dbsync/pipeline/threaded_context.rb
|
134
|
+
- lib/sq/dbsync/pipeline.rb
|
135
|
+
- lib/sq/dbsync/refresh_recent_load_action.rb
|
136
|
+
- lib/sq/dbsync/schema_maker.rb
|
137
|
+
- lib/sq/dbsync/static_table_plan.rb
|
138
|
+
- lib/sq/dbsync/table_registry.rb
|
139
|
+
- lib/sq/dbsync/tempfile_factory.rb
|
140
|
+
- lib/sq/dbsync/version.rb
|
141
|
+
- lib/sq/dbsync.rb
|
142
|
+
- README.md
|
143
|
+
- HISTORY.md
|
144
|
+
- LICENSE
|
145
|
+
- sq-dbsync.gemspec
|
146
|
+
homepage: http://github.com/square/sq-dbsync
|
147
|
+
licenses: []
|
148
|
+
post_install_message:
|
149
|
+
rdoc_options: []
|
150
|
+
require_paths:
|
151
|
+
- lib
|
152
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
153
|
+
none: false
|
154
|
+
requirements:
|
155
|
+
- - ! '>='
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
version: '0'
|
158
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
159
|
+
none: false
|
160
|
+
requirements:
|
161
|
+
- - ! '>='
|
162
|
+
- !ruby/object:Gem::Version
|
163
|
+
version: '0'
|
164
|
+
requirements: []
|
165
|
+
rubyforge_project:
|
166
|
+
rubygems_version: 1.8.23
|
167
|
+
signing_key:
|
168
|
+
specification_version: 3
|
169
|
+
summary: Column based, timestamp replication of MySQL and Postgres databases. Uses
|
170
|
+
Ruby for the glue code but pushes the heavy lifting on to the database.
|
171
|
+
test_files:
|
172
|
+
- spec/acceptance/loading_spec.rb
|
173
|
+
- spec/acceptance_helper.rb
|
174
|
+
- spec/database_helper.rb
|
175
|
+
- spec/integration/all_tables_plan_spec.rb
|
176
|
+
- spec/integration/batch_load_action_spec.rb
|
177
|
+
- spec/integration/consistency_verifier_spec.rb
|
178
|
+
- spec/integration/database_connection_spec.rb
|
179
|
+
- spec/integration/incremental_load_action_spec.rb
|
180
|
+
- spec/integration/manager_spec.rb
|
181
|
+
- spec/integration/schema_maker_spec.rb
|
182
|
+
- spec/integration_helper.rb
|
183
|
+
- spec/spec_helper.rb
|
184
|
+
- spec/unit/config_spec.rb
|
185
|
+
- spec/unit/error_handler_spec.rb
|
186
|
+
- spec/unit/pipeline_spec.rb
|
187
|
+
- spec/unit/stream_logger_spec.rb
|
188
|
+
- spec/unit_helper.rb
|