pg_easy_replicate 0.3.4 → 0.3.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +7 -7
- data/README.md +3 -3
- data/lib/pg_easy_replicate/cli.rb +31 -6
- data/lib/pg_easy_replicate/group.rb +2 -1
- data/lib/pg_easy_replicate/helper.rb +14 -3
- data/lib/pg_easy_replicate/orchestrate.rb +9 -14
- data/lib/pg_easy_replicate/version.rb +1 -1
- data/lib/pg_easy_replicate.rb +6 -0
- metadata +2 -3
- data/CHANGELOG.md +0 -112
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e7291bb160de0db280d2e11a7b5e46d89bdd6b259ea2acf070ab302a80b27579
|
4
|
+
data.tar.gz: 7b5f1df7f16a833ce6f9fc2bdac7765e0d8835b6b271d029834a06a0f21bd3b7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a066f7421b3be12ad1aa28017c9c680652f18477a37390fdaaf58efe2dc31aca28abc40715f15e33afbf628c973c2d8786d6d2818e22ea59e9ee6ca9c74dccd8
|
7
|
+
data.tar.gz: 45b5cfa989e4209ceddacc2582088ff712e45a17d34bfff423c30d3d350635cc894cc0f6c84dc5a68cb96ec4f0280d16cc8a2d4b108296543cde095b752312d6
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
pg_easy_replicate (0.3.
|
4
|
+
pg_easy_replicate (0.3.6)
|
5
5
|
ougai (~> 2.0.0)
|
6
6
|
pg (~> 1.5.3)
|
7
7
|
pg_query (~> 5.1.0)
|
@@ -25,21 +25,21 @@ GEM
|
|
25
25
|
temple (>= 0.8.2)
|
26
26
|
thor
|
27
27
|
tilt
|
28
|
-
json (2.
|
28
|
+
json (2.8.2)
|
29
29
|
language_server-protocol (3.17.0.3)
|
30
|
-
method_source (1.
|
30
|
+
method_source (1.1.0)
|
31
31
|
oj (3.14.3)
|
32
32
|
ougai (2.0.0)
|
33
33
|
oj (~> 3.10)
|
34
34
|
parallel (1.26.3)
|
35
|
-
parser (3.3.
|
35
|
+
parser (3.3.6.0)
|
36
36
|
ast (~> 2.4.1)
|
37
37
|
racc
|
38
38
|
pg (1.5.9)
|
39
39
|
pg_query (5.1.0)
|
40
40
|
google-protobuf (>= 3.22.3)
|
41
41
|
prettier_print (1.2.1)
|
42
|
-
pry (0.
|
42
|
+
pry (0.15.0)
|
43
43
|
coderay (~> 1.1)
|
44
44
|
method_source (~> 1.0)
|
45
45
|
racc (1.8.1)
|
@@ -72,7 +72,7 @@ GEM
|
|
72
72
|
rubocop-ast (>= 1.31.1, < 2.0)
|
73
73
|
ruby-progressbar (~> 1.7)
|
74
74
|
unicode-display_width (>= 2.4.0, < 3.0)
|
75
|
-
rubocop-ast (1.
|
75
|
+
rubocop-ast (1.36.1)
|
76
76
|
parser (>= 3.3.1.0)
|
77
77
|
rubocop-capybara (2.20.0)
|
78
78
|
rubocop (~> 1.41)
|
@@ -80,7 +80,7 @@ GEM
|
|
80
80
|
rubocop (~> 1.41)
|
81
81
|
rubocop-packaging (0.5.2)
|
82
82
|
rubocop (>= 1.33, < 2.0)
|
83
|
-
rubocop-performance (1.
|
83
|
+
rubocop-performance (1.23.0)
|
84
84
|
rubocop (>= 1.48.1, < 2.0)
|
85
85
|
rubocop-ast (>= 1.31.1, < 2.0)
|
86
86
|
rubocop-rake (0.6.0)
|
data/README.md
CHANGED
@@ -191,7 +191,7 @@ $ pg_easy_replicate start_sync --group-name database-cluster-1 [-d <track-ddl>]
|
|
191
191
|
|
192
192
|
### DDL Changes Management
|
193
193
|
|
194
|
-
`pg_easy_replicate` now supports tracking and applying DDL (Data Definition Language) changes between the source and target databases. To track DDLs you can pass
|
194
|
+
`pg_easy_replicate` now supports tracking and applying DDL (Data Definition Language) changes between the source and target databases. To track DDLs you can pass `--track-ddl` to `start_sync`.
|
195
195
|
|
196
196
|
This feature ensures that most schema changes made to the source database tables that are being replicated during the replication process are tracked, so that you can apply them at your will before or after switchover.
|
197
197
|
|
@@ -310,12 +310,12 @@ By default all tables are added for replication but you can create multiple grou
|
|
310
310
|
```bash
|
311
311
|
|
312
312
|
$ pg_easy_replicate bootstrap --group-name database-cluster-1 --copy-schema
|
313
|
-
$ pg_easy_replicate start_sync --group-name database-cluster-1 --schema-name public --tables "users,
|
313
|
+
$ pg_easy_replicate start_sync --group-name database-cluster-1 --schema-name public --tables "users,posts,events"
|
314
314
|
|
315
315
|
...
|
316
316
|
|
317
317
|
$ pg_easy_replicate bootstrap --group-name database-cluster-2 --copy-schema
|
318
|
-
$ pg_easy_replicate start_sync --group-name database-cluster-2 --schema-name public --tables "comments,
|
318
|
+
$ pg_easy_replicate start_sync --group-name database-cluster-2 --schema-name public --tables "comments,views"
|
319
319
|
|
320
320
|
...
|
321
321
|
$ pg_easy_replicate switchover --group-name database-cluster-1
|
@@ -78,6 +78,11 @@ module PgEasyReplicate
|
|
78
78
|
aliases: "-s",
|
79
79
|
desc:
|
80
80
|
"Cleans up the publication and subscription for the respective group"
|
81
|
+
method_option :restore_connection_on_source_db,
|
82
|
+
aliases: "-r",
|
83
|
+
type: :boolean,
|
84
|
+
default: false,
|
85
|
+
desc: "Restore connection on source db after switchover"
|
81
86
|
def cleanup
|
82
87
|
PgEasyReplicate.cleanup(options)
|
83
88
|
end
|
@@ -163,14 +168,34 @@ module PgEasyReplicate
|
|
163
168
|
end
|
164
169
|
end
|
165
170
|
|
166
|
-
desc "notify",
|
167
|
-
|
168
|
-
method_option :
|
169
|
-
|
170
|
-
|
171
|
+
desc "notify",
|
172
|
+
"Sends a notification with replication status to a specified url"
|
173
|
+
method_option :group_name,
|
174
|
+
aliases: "-g",
|
175
|
+
required: true,
|
176
|
+
desc: "Name of the group previously provisioned"
|
177
|
+
method_option :url,
|
178
|
+
aliases: "-u",
|
179
|
+
required: true,
|
180
|
+
desc: "URL for notification"
|
181
|
+
method_option :frequency,
|
182
|
+
aliases: "-f",
|
183
|
+
type: :numeric,
|
184
|
+
default: 10,
|
185
|
+
desc: "Frequency for sending stats to the endpoint provided"
|
186
|
+
method_option :timeout,
|
187
|
+
aliases: "-t",
|
188
|
+
type: :numeric,
|
189
|
+
default: 10,
|
190
|
+
desc: "Timeout for the notify request"
|
171
191
|
|
172
192
|
def notify
|
173
|
-
PgEasyReplicate::Stats.notify(
|
193
|
+
PgEasyReplicate::Stats.notify(
|
194
|
+
options[:group_name],
|
195
|
+
options[:url],
|
196
|
+
options[:frequency],
|
197
|
+
options[:timeout],
|
198
|
+
)
|
174
199
|
end
|
175
200
|
|
176
201
|
desc "list_ddl_changes", "Lists recent DDL changes in the source database"
|
@@ -20,7 +20,7 @@ module PgEasyReplicate
|
|
20
20
|
column(:updated_at, Time, default: Sequel::CURRENT_TIMESTAMP)
|
21
21
|
column(:started_at, Time)
|
22
22
|
column(:failed_at, Time)
|
23
|
-
column(:recreate_indices_post_copy, TrueClass, default:
|
23
|
+
column(:recreate_indices_post_copy, TrueClass, default: false)
|
24
24
|
column(:switchover_completed_at, Time)
|
25
25
|
end
|
26
26
|
ensure
|
@@ -44,6 +44,7 @@ module PgEasyReplicate
|
|
44
44
|
schema_name: options[:schema_name],
|
45
45
|
started_at: options[:started_at],
|
46
46
|
failed_at: options[:failed_at],
|
47
|
+
recreate_indices_post_copy: options[:recreate_indices_post_copy],
|
47
48
|
)
|
48
49
|
rescue => e
|
49
50
|
abort_with("Adding group entry failed: #{e.message}")
|
@@ -75,7 +75,7 @@ module PgEasyReplicate
|
|
75
75
|
|
76
76
|
def determine_tables(conn_string:, list: "", exclude_list: "", schema: nil)
|
77
77
|
schema ||= "public"
|
78
|
-
|
78
|
+
|
79
79
|
tables = convert_to_array(list)
|
80
80
|
exclude_tables = convert_to_array(exclude_list)
|
81
81
|
validate_table_lists(tables, exclude_tables, schema)
|
@@ -115,14 +115,25 @@ module PgEasyReplicate
|
|
115
115
|
exclude_table_list = convert_to_array(exclude_tables)
|
116
116
|
|
117
117
|
if !table_list.empty? && !exclude_table_list.empty?
|
118
|
-
abort_with(
|
118
|
+
abort_with(
|
119
|
+
"Options --tables(-t) and --exclude-tables(-e) cannot be used together.",
|
120
|
+
)
|
119
121
|
elsif !table_list.empty?
|
120
122
|
if table_list.size > 0 && (schema_name.nil? || schema_name == "")
|
121
123
|
abort_with("Schema name is required if tables are passed")
|
122
124
|
end
|
123
|
-
elsif exclude_table_list.size > 0 &&
|
125
|
+
elsif exclude_table_list.size > 0 &&
|
126
|
+
(schema_name.nil? || schema_name == "")
|
124
127
|
abort_with("Schema name is required if exclude tables are passed")
|
125
128
|
end
|
126
129
|
end
|
130
|
+
|
131
|
+
def restore_connections_on_source_db
|
132
|
+
logger.info("Restoring connections")
|
133
|
+
|
134
|
+
alter_sql =
|
135
|
+
"ALTER USER #{quote_ident(db_user(source_db_url))} set default_transaction_read_only = false"
|
136
|
+
Query.run(query: alter_sql, connection_url: source_db_url)
|
137
|
+
end
|
127
138
|
end
|
128
139
|
end
|
@@ -60,6 +60,7 @@ module PgEasyReplicate
|
|
60
60
|
schema: schema_name,
|
61
61
|
)
|
62
62
|
end
|
63
|
+
logger.info("Starting sync completed successfully")
|
63
64
|
rescue => e
|
64
65
|
stop_sync(group_name: options[:group_name])
|
65
66
|
if Group.find(options[:group_name])
|
@@ -166,6 +167,7 @@ module PgEasyReplicate
|
|
166
167
|
Query.run(
|
167
168
|
query: "DROP SUBSCRIPTION IF EXISTS #{subscription_name(group_name)}",
|
168
169
|
connection_url: target_conn_string,
|
170
|
+
user: db_user(target_conn_string),
|
169
171
|
transaction: false,
|
170
172
|
)
|
171
173
|
rescue => e
|
@@ -192,6 +194,7 @@ module PgEasyReplicate
|
|
192
194
|
group_name: group_name,
|
193
195
|
target_conn_string: target_conn_string || target_db_url,
|
194
196
|
)
|
197
|
+
logger.info("Stopping sync completed successfully")
|
195
198
|
rescue => e
|
196
199
|
abort_with("Unable to stop sync: #{e.message}")
|
197
200
|
end
|
@@ -236,6 +239,11 @@ module PgEasyReplicate
|
|
236
239
|
revoke_connections_on_source_db(group_name)
|
237
240
|
wait_for_remaining_catchup(group_name)
|
238
241
|
refresh_sequences(conn_string: target_conn, schema: group[:schema_name])
|
242
|
+
|
243
|
+
drop_subscription(
|
244
|
+
group_name: group_name,
|
245
|
+
target_conn_string: target_conn,
|
246
|
+
)
|
239
247
|
mark_switchover_complete(group_name)
|
240
248
|
|
241
249
|
unless skip_vacuum_analyze
|
@@ -245,13 +253,8 @@ module PgEasyReplicate
|
|
245
253
|
schema: group[:schema_name],
|
246
254
|
)
|
247
255
|
end
|
248
|
-
|
249
|
-
drop_subscription(
|
250
|
-
group_name: group_name,
|
251
|
-
target_conn_string: target_conn,
|
252
|
-
)
|
253
256
|
rescue => e
|
254
|
-
restore_connections_on_source_db
|
257
|
+
restore_connections_on_source_db
|
255
258
|
abort_with("Switchover failed: #{e.message}")
|
256
259
|
end
|
257
260
|
|
@@ -311,14 +314,6 @@ module PgEasyReplicate
|
|
311
314
|
raise "Unable to revoke connections on source db: #{e.message}"
|
312
315
|
end
|
313
316
|
|
314
|
-
def restore_connections_on_source_db(group_name)
|
315
|
-
logger.info("Restoring connections")
|
316
|
-
|
317
|
-
alter_sql =
|
318
|
-
"ALTER USER #{quote_ident(db_user(source_db_url))} set default_transaction_read_only = false"
|
319
|
-
Query.run(query: alter_sql, connection_url: source_db_url)
|
320
|
-
end
|
321
|
-
|
322
317
|
def refresh_sequences(conn_string:, schema: nil)
|
323
318
|
logger.info("Refreshing sequences")
|
324
319
|
sql = <<~SQL
|
data/lib/pg_easy_replicate.rb
CHANGED
@@ -158,6 +158,7 @@ module PgEasyReplicate
|
|
158
158
|
|
159
159
|
logger.info("Setting up groups tables")
|
160
160
|
Group.setup
|
161
|
+
logger.info("Bootstrap completed successfully")
|
161
162
|
rescue => e
|
162
163
|
abort_with("Unable to bootstrap: #{e.message}")
|
163
164
|
end
|
@@ -212,6 +213,11 @@ module PgEasyReplicate
|
|
212
213
|
end
|
213
214
|
end
|
214
215
|
end,
|
216
|
+
-> do
|
217
|
+
if options[:restore_connection_on_source_db]
|
218
|
+
restore_connections_on_source_db
|
219
|
+
end
|
220
|
+
end,
|
215
221
|
]
|
216
222
|
|
217
223
|
cleanup_steps.each do |step|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pg_easy_replicate
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shayon Mukherjee
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-11-
|
11
|
+
date: 2024-11-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ougai
|
@@ -274,7 +274,6 @@ files:
|
|
274
274
|
- ".rspec"
|
275
275
|
- ".rubocop.yml"
|
276
276
|
- ".ruby-version"
|
277
|
-
- CHANGELOG.md
|
278
277
|
- CODE_OF_CONDUCT.md
|
279
278
|
- Dockerfile
|
280
279
|
- Gemfile
|
data/CHANGELOG.md
DELETED
@@ -1,112 +0,0 @@
|
|
1
|
-
## [0.3.2] - 2024-08-31
|
2
|
-
|
3
|
-
- DDL: Support table column rename - #157
|
4
|
-
|
5
|
-
## [0.3.0] - 2024-08-31
|
6
|
-
|
7
|
-
- Support DDL Tracking by - #155
|
8
|
-
- `recreate-indices-post-copy` now defaults to `false`
|
9
|
-
|
10
|
-
## [0.2.6] - 2024-06-04
|
11
|
-
|
12
|
-
- Quote table name in the VACUUM SQL - #118
|
13
|
-
- Exclude tables created by extensions - #120
|
14
|
-
- Use db user when adding tables to replication - #130
|
15
|
-
|
16
|
-
## [0.2.5] - 2024-04-14
|
17
|
-
|
18
|
-
- List only permanent tables - #113
|
19
|
-
|
20
|
-
## [0.2.4] - 2024-02-13
|
21
|
-
|
22
|
-
- Introduce PG_EASY_REPLICATE_STATEMENT_TIMEOUT env var
|
23
|
-
|
24
|
-
## [0.2.3] - 2024-01-21
|
25
|
-
|
26
|
-
- Fix tables check in config_check - #93
|
27
|
-
- add option to skip vacuum analyzing on switchover - #92
|
28
|
-
- Disable statement timeout and reset it before/after vacuum+analyze - #94
|
29
|
-
- Add spec for skip_vacuum_analyze - #95
|
30
|
-
|
31
|
-
Highlights
|
32
|
-
|
33
|
-
- You can now skip vacuum and analyze by passing `--skip-vacuum-analyze` to `switchover`. Thanks to @honzasterba
|
34
|
-
- Vacuum and Analyze won't run into timeouts. Thanks to the report from @TrueCarry
|
35
|
-
|
36
|
-
## [0.2.2] - 2024-01-21
|
37
|
-
|
38
|
-
- Extend config check to assert for REPLICA IDENTITY on tables and drop index bug - #88
|
39
|
-
|
40
|
-
## [0.2.1] - 2024-01-20
|
41
|
-
|
42
|
-
- Don't attempt to drop and recreate unique indices - #88
|
43
|
-
- Dependency updates
|
44
|
-
|
45
|
-
## [0.2.0] - 2023-12-29
|
46
|
-
|
47
|
-
- Recreate indices post COPY, once all tables are in replicating mode - #81
|
48
|
-
|
49
|
-
## [0.1.12] - 2023-12-13
|
50
|
-
|
51
|
-
- Bump rubocop-rspec from 2.24.1 to 2.25.0 - #65
|
52
|
-
- Quote indent DB name - #76
|
53
|
-
|
54
|
-
## [0.1.12] - 2023-12-13
|
55
|
-
|
56
|
-
- Drop existing user with privileges when bootstrapping - #75
|
57
|
-
|
58
|
-
## [0.1.10] - 2023-12-12
|
59
|
-
|
60
|
-
- Reference the passed in URL and use source db url - #74
|
61
|
-
|
62
|
-
## [0.1.9] - 2023-08-01
|
63
|
-
|
64
|
-
- Exclude views, temporary tables and foreign tables from #list_all_tables - #39
|
65
|
-
- Add quote_identifier helper for SQL identifiers. - #40
|
66
|
-
- Escape db user name in queries - #42
|
67
|
-
- Require english lib so that $CHILD_STATUS is loaded - #43
|
68
|
-
- Bump rubocop from 1.54.2 to 1.55.0 - #37
|
69
|
-
- Bump rubocop-rspec from 2.22.0 to 2.23.0 - #36
|
70
|
-
- Quote indent username, dbname and schema in all places - #44
|
71
|
-
|
72
|
-
## [0.1.8] - 2023-07-23
|
73
|
-
|
74
|
-
- Introduce --copy_schema via pg_dump - #35
|
75
|
-
|
76
|
-
## [0.1.7] - 2023-06-26
|
77
|
-
|
78
|
-
- Perform smoke test with retries in CI - #26
|
79
|
-
- Default schema to `public` #29
|
80
|
-
- Perform vacuum and analyze before and after switchover - #30
|
81
|
-
|
82
|
-
## [0.1.6] - 2023-06-24
|
83
|
-
|
84
|
-
- Bug fix: Support custom schema name
|
85
|
-
- New smoke spec in CI
|
86
|
-
|
87
|
-
## [0.1.5] - 2023-06-24
|
88
|
-
|
89
|
-
- Fix bug in `stop_sync`
|
90
|
-
|
91
|
-
## [0.1.4] - 2023-06-24
|
92
|
-
|
93
|
-
- Drop lockbox dependency
|
94
|
-
- Support password with special chars and test for url encoded URI
|
95
|
-
- Support AWS and GCP special user scenarios and introduce `--special-user-role`
|
96
|
-
|
97
|
-
## [0.1.3] - 2023-06-22
|
98
|
-
|
99
|
-
- Docker multi-platform image build support for linux/amd64 and linux/arm64 starting 0.1.3
|
100
|
-
|
101
|
-
## [0.1.2] - 2023-06-22
|
102
|
-
|
103
|
-
- Keep the internal username unique
|
104
|
-
|
105
|
-
## [0.1.1] - 2023-06-21
|
106
|
-
|
107
|
-
- Don't leak bin/console and bin/setup into `$PATH`
|
108
|
-
- Typo fixes
|
109
|
-
|
110
|
-
## [0.1.0] - 2023-06-19
|
111
|
-
|
112
|
-
- Initial release
|