litestream 0.5.3-arm64-darwin → 0.5.4-arm64-darwin
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +46 -5
- data/lib/litestream/commands.rb +40 -25
- data/lib/litestream/version.rb +1 -1
- data/lib/litestream.rb +1 -1
- data/lib/tasks/litestream_tasks.rake +16 -6
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fea17404f07d31435edecb439529500b8beecb4b89726de3eaa1d7cf865c075e
|
4
|
+
data.tar.gz: 2abba49dd1dfb0cfdf95ae60e9df0cd85f8ae06b711a832d11fc50914b35a064
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 24cc852dd7b4d1cf19d6f72006b3c26cd1e9770ed3a06b5cfd0aad14d5a72311c1ecf410adb83e4cdfefefac641ab014376244e49995b5f4434e96ddd2657c03
|
7
|
+
data.tar.gz: 0d7c51ccb9e53a30ee0fb803aa11d4e62d96d923639b61710cb0dfd7dfecb08bf0732e51010093a9600f88840882414b960c60e0e5cff48027ef3e8b79759cfc
|
data/README.md
CHANGED
@@ -53,9 +53,11 @@ The gem streamlines the configuration process by providing a default configurati
|
|
53
53
|
|
54
54
|
```yaml
|
55
55
|
dbs:
|
56
|
-
- path:
|
56
|
+
- path: storage/production.sqlite3
|
57
57
|
replicas:
|
58
|
-
-
|
58
|
+
- type: s3
|
59
|
+
bucket: $LITESTREAM_REPLICA_BUCKET
|
60
|
+
path: storage/production.sqlite3
|
59
61
|
access-key-id: $LITESTREAM_ACCESS_KEY_ID
|
60
62
|
secret-access-key: $LITESTREAM_SECRET_ACCESS_KEY
|
61
63
|
```
|
@@ -65,7 +67,6 @@ The gem also provides a default initializer file at `config/initializers/litestr
|
|
65
67
|
```ruby
|
66
68
|
litestream_credentials = Rails.application.credentials.litestream
|
67
69
|
Litestream.configure do |config|
|
68
|
-
config.database_path = ActiveRecord::Base.connection_db_config.database
|
69
70
|
config.replica_bucket = litestream_credentials.replica_bucket
|
70
71
|
config.replica_key_id = litestream_credentials.replica_key_id
|
71
72
|
config.replica_access_key = litestream_credentials.replica_access_key
|
@@ -240,7 +241,48 @@ replica generation index size created
|
|
240
241
|
s3 a295b16a796689f3 1 4645465 2024-04-17T00:01:19Z
|
241
242
|
```
|
242
243
|
|
243
|
-
###
|
244
|
+
### Running commands from Ruby
|
245
|
+
|
246
|
+
In addition to the provided rake tasks, you can also run Litestream commands directly from Ruby. The gem provides a `Litestream::Commands` module that wraps the Litestream CLI commands. This is particularly useful for the introspection commands, as you can use the output in your Ruby code.
|
247
|
+
|
248
|
+
The `Litestream::Commands.databases` method returns an array of hashes with the "path" and "replicas" keys for each database:
|
249
|
+
|
250
|
+
```ruby
|
251
|
+
Litestream::Commands.databases
|
252
|
+
# => [{"path"=>"/Users/you/Code/your-app/storage/production.sqlite3", "replicas"=>"s3"}]
|
253
|
+
```
|
254
|
+
|
255
|
+
The `Litestream::Commands.generations` method returns an array of hashes with the "name", "generation", "lag", "start", and "end" keys for each generation:
|
256
|
+
|
257
|
+
```ruby
|
258
|
+
Litestream::Commands.generations('storage/production.sqlite3')
|
259
|
+
# => [{"name"=>"s3", "generation"=>"5f4341bc3d22d615", "lag"=>"3s", "start"=>"2024-04-17T19:48:09Z", "end"=>"2024-04-17T19:48:09Z"}]
|
260
|
+
```
|
261
|
+
|
262
|
+
The `Litestream::Commands.snapshots` method returns an array of hashes with the "replica", "generation", "index", "size", and "created" keys for each snapshot:
|
263
|
+
|
264
|
+
```ruby
|
265
|
+
Litestream::Commands.snapshots('storage/production.sqlite3')
|
266
|
+
# => [{"replica"=>"s3", "generation"=>"5f4341bc3d22d615", "index"=>"0", "size"=>"4645465", "created"=>"2024-04-17T19:48:09Z"}]
|
267
|
+
```
|
268
|
+
|
269
|
+
You can also restore a database programatically using the `Litestream::Commands.restore` method, which returns the path to the restored database:
|
270
|
+
|
271
|
+
```ruby
|
272
|
+
Litestream::Commands.restore('storage/production.sqlite3')
|
273
|
+
# => "storage/production-20240418090048.sqlite3"
|
274
|
+
```
|
275
|
+
|
276
|
+
Finally, you can verify the integrity of a restored database using the `Litestream::Commands.verify` method, which returns a hash with the "size" and "tables" keys for the original and restored databases:
|
277
|
+
|
278
|
+
```ruby
|
279
|
+
Litestream::Commands.verify('storage/production.sqlite3')
|
280
|
+
# => {"size"=>{"original"=>21688320, "restored"=>21688320}, "tables"=>{"original"=>9, "restored"=>9}}
|
281
|
+
```
|
282
|
+
|
283
|
+
You _can_ start the replication process using the `Litestream::Commands.replicate` method, but this is not recommended. The replication process should be managed by Litestream itself, and you should not need to manually start it.
|
284
|
+
|
285
|
+
### Running commands from CLI
|
244
286
|
|
245
287
|
The rake tasks are the recommended way to interact with the Litestream utility in your Rails application or Ruby project. But, you _can_ work directly with the Litestream CLI. Since the gem installs the native executable via Bundler, the `litestream` command will be available in your `PATH`.
|
246
288
|
|
@@ -272,7 +314,6 @@ Once you have a MinIO server running, you can create a bucket for Litestream to
|
|
272
314
|
|
273
315
|
```ruby
|
274
316
|
Litestream.configure do |config|
|
275
|
-
config.database_path = ActiveRecord::Base.connection_db_config.database
|
276
317
|
config.replica_bucket = "s3://mybkt.localhost:9000/"
|
277
318
|
config.replica_key_id = "minioadmin"
|
278
319
|
config.replica_access_key = "minioadmin"
|
data/lib/litestream/commands.rb
CHANGED
@@ -76,11 +76,11 @@ module Litestream
|
|
76
76
|
exe_file
|
77
77
|
end
|
78
78
|
|
79
|
-
def replicate(async:
|
80
|
-
execute("replicate", argv, async: async)
|
79
|
+
def replicate(async: false, **argv)
|
80
|
+
execute("replicate", argv, async: async, hashify: false)
|
81
81
|
end
|
82
82
|
|
83
|
-
def restore(database, async:
|
83
|
+
def restore(database, async: false, **argv)
|
84
84
|
raise DatabaseRequiredException, "database argument is required for restore command, e.g. litestream:restore -- --database=path/to/database.sqlite" if database.nil?
|
85
85
|
|
86
86
|
dir, file = File.split(database)
|
@@ -93,28 +93,12 @@ module Litestream
|
|
93
93
|
"-o" => backup
|
94
94
|
}.merge(argv)
|
95
95
|
|
96
|
-
execute("restore", args, database, async: async)
|
96
|
+
execute("restore", args, database, async: async, hashify: false)
|
97
97
|
|
98
98
|
backup
|
99
99
|
end
|
100
100
|
|
101
|
-
def
|
102
|
-
execute("databases", argv, async: async)
|
103
|
-
end
|
104
|
-
|
105
|
-
def generations(database, async: true, **argv)
|
106
|
-
raise DatabaseRequiredException, "database argument is required for generations command, e.g. litestream:generations -- --database=path/to/database.sqlite" if database.nil?
|
107
|
-
|
108
|
-
execute("generations", argv, database, async: async)
|
109
|
-
end
|
110
|
-
|
111
|
-
def snapshots(database, async: true, **argv)
|
112
|
-
raise DatabaseRequiredException, "database argument is required for snapshots command, e.g. litestream:snapshots -- --database=path/to/database.sqlite" if database.nil?
|
113
|
-
|
114
|
-
execute("snapshots", argv, database, async: async)
|
115
|
-
end
|
116
|
-
|
117
|
-
def verify(database, async: true, **argv)
|
101
|
+
def verify(database, async: false, **argv)
|
118
102
|
raise DatabaseRequiredException, "database argument is required for verify command, e.g. litestream:verify -- --database=path/to/database.sqlite" if database.nil? || !File.exist?(database)
|
119
103
|
|
120
104
|
backup = restore(database, async: false, **argv)
|
@@ -129,14 +113,35 @@ module Litestream
|
|
129
113
|
Dir.glob(backup + "*").each { |file| File.delete(file) }
|
130
114
|
|
131
115
|
{
|
132
|
-
size
|
133
|
-
tables
|
116
|
+
"size" => {"original" => original_size, "restored" => restored_size},
|
117
|
+
"tables" => {"original" => original_tables_count, "restored" => restored_tables_count}
|
134
118
|
}
|
135
119
|
end
|
136
120
|
|
121
|
+
def databases(async: false, **argv)
|
122
|
+
execute("databases", argv, async: async, hashify: true)
|
123
|
+
end
|
124
|
+
|
125
|
+
def generations(database, async: false, **argv)
|
126
|
+
raise DatabaseRequiredException, "database argument is required for generations command, e.g. litestream:generations -- --database=path/to/database.sqlite" if database.nil?
|
127
|
+
|
128
|
+
execute("generations", argv, database, async: async, hashify: true)
|
129
|
+
end
|
130
|
+
|
131
|
+
def snapshots(database, async: false, **argv)
|
132
|
+
raise DatabaseRequiredException, "database argument is required for snapshots command, e.g. litestream:snapshots -- --database=path/to/database.sqlite" if database.nil?
|
133
|
+
|
134
|
+
execute("snapshots", argv, database, async: async, hashify: true)
|
135
|
+
end
|
136
|
+
|
137
137
|
private
|
138
138
|
|
139
|
-
def execute(command, argv = {}, database = nil, async:
|
139
|
+
def execute(command, argv = {}, database = nil, async: false, hashify: false)
|
140
|
+
cmd = prepare(command, argv, database)
|
141
|
+
run(cmd, async: async, hashify: hashify)
|
142
|
+
end
|
143
|
+
|
144
|
+
def prepare(command, argv = {}, database = nil)
|
140
145
|
if Litestream.configuration
|
141
146
|
ENV["LITESTREAM_REPLICA_BUCKET"] ||= Litestream.configuration.replica_bucket
|
142
147
|
ENV["LITESTREAM_ACCESS_KEY_ID"] ||= Litestream.configuration.replica_key_id
|
@@ -149,14 +154,24 @@ module Litestream
|
|
149
154
|
cmd = [executable, command, *args, database].compact
|
150
155
|
puts cmd.inspect if ENV["DEBUG"]
|
151
156
|
|
157
|
+
cmd
|
158
|
+
end
|
159
|
+
|
160
|
+
def run(cmd, async: false, hashify: false)
|
152
161
|
if async
|
153
162
|
# To release the resources of the Ruby process, just fork and exit.
|
154
163
|
# The forked process executes litestream and replaces itself.
|
155
164
|
exec(*cmd) if fork.nil?
|
156
165
|
else
|
157
|
-
|
166
|
+
out = `#{cmd.join(" ")}`
|
167
|
+
text_table_to_hashes(out) if hashify
|
158
168
|
end
|
159
169
|
end
|
170
|
+
|
171
|
+
def text_table_to_hashes(string)
|
172
|
+
keys, *rows = string.split("\n").map { _1.split(/\s+/) }
|
173
|
+
rows.map { keys.zip(_1).to_h }
|
174
|
+
end
|
160
175
|
end
|
161
176
|
end
|
162
177
|
end
|
data/lib/litestream/version.rb
CHANGED
data/lib/litestream.rb
CHANGED
@@ -21,8 +21,9 @@ namespace :litestream do
|
|
21
21
|
.map { |pair| pair.split("=") }
|
22
22
|
.each { |opt| options[opt[0]] = opt[1] || nil }
|
23
23
|
end
|
24
|
+
options.symbolize_keys!
|
24
25
|
|
25
|
-
Litestream::Commands.replicate(**options)
|
26
|
+
Litestream::Commands.replicate(async: true, **options)
|
26
27
|
end
|
27
28
|
|
28
29
|
desc "Restore a SQLite database from a Litestream replica, e.g. rake litestream:restore -- -database=storage/production.sqlite3"
|
@@ -33,8 +34,10 @@ namespace :litestream do
|
|
33
34
|
.map { |pair| pair.split("=") }
|
34
35
|
.each { |opt| options[opt[0]] = opt[1] || nil }
|
35
36
|
end
|
37
|
+
database = options.delete("--database") || options.delete("-database")
|
38
|
+
options.symbolize_keys!
|
36
39
|
|
37
|
-
Litestream::Commands.restore(
|
40
|
+
Litestream::Commands.restore(database, async: true, **options)
|
38
41
|
end
|
39
42
|
|
40
43
|
desc "List all databases and associated replicas in the config file, e.g. rake litestream:databases -- -no-expand-env"
|
@@ -45,8 +48,9 @@ namespace :litestream do
|
|
45
48
|
.map { |pair| pair.split("=") }
|
46
49
|
.each { |opt| options[opt[0]] = opt[1] || nil }
|
47
50
|
end
|
51
|
+
options.symbolize_keys!
|
48
52
|
|
49
|
-
Litestream::Commands.databases(**options)
|
53
|
+
Litestream::Commands.databases(async: true, **options)
|
50
54
|
end
|
51
55
|
|
52
56
|
desc "List all generations for a database or replica, e.g. rake litestream:generations -- -database=storage/production.sqlite3"
|
@@ -57,8 +61,10 @@ namespace :litestream do
|
|
57
61
|
.map { |pair| pair.split("=") }
|
58
62
|
.each { |opt| options[opt[0]] = opt[1] || nil }
|
59
63
|
end
|
64
|
+
database = options.delete("--database") || options.delete("-database")
|
65
|
+
options.symbolize_keys!
|
60
66
|
|
61
|
-
Litestream::Commands.generations(
|
67
|
+
Litestream::Commands.generations(database, async: true, **options)
|
62
68
|
end
|
63
69
|
|
64
70
|
desc "List all snapshots for a database or replica, e.g. rake litestream:snapshots -- -database=storage/production.sqlite3"
|
@@ -69,8 +75,10 @@ namespace :litestream do
|
|
69
75
|
.map { |pair| pair.split("=") }
|
70
76
|
.each { |opt| options[opt[0]] = opt[1] || nil }
|
71
77
|
end
|
78
|
+
database = options.delete("--database") || options.delete("-database")
|
79
|
+
options.symbolize_keys!
|
72
80
|
|
73
|
-
Litestream::Commands.snapshots(
|
81
|
+
Litestream::Commands.snapshots(database, async: true, **options)
|
74
82
|
end
|
75
83
|
|
76
84
|
desc "verify backup of SQLite database from a Litestream replica, e.g. rake litestream:verify -- -database=storage/production.sqlite3"
|
@@ -81,8 +89,10 @@ namespace :litestream do
|
|
81
89
|
.map { |pair| pair.split("=") }
|
82
90
|
.each { |opt| options[opt[0]] = opt[1] || nil }
|
83
91
|
end
|
92
|
+
database = options.delete("--database") || options.delete("-database")
|
93
|
+
options.symbolize_keys!
|
84
94
|
|
85
|
-
result = Litestream::Commands.verify(
|
95
|
+
result = Litestream::Commands.verify(database, async: true, **options)
|
86
96
|
|
87
97
|
puts <<~TXT if result
|
88
98
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: litestream
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.4
|
5
5
|
platform: arm64-darwin
|
6
6
|
authors:
|
7
7
|
- Stephen Margheim
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-04-
|
11
|
+
date: 2024-04-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rubyzip
|