litestream 0.5.0-x86_64-darwin → 0.5.1-x86_64-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 +41 -0
- data/lib/litestream/commands.rb +89 -75
- data/lib/litestream/version.rb +1 -1
- data/lib/tasks/litestream_tasks.rake +36 -0
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 49adc00f53f6eed0427ea5a203c31bfc5e952b09315f1c6efdacaa063e039f0c
|
4
|
+
data.tar.gz: 462d08c90c1845f3dcb910c032859fef21c2cec4fc0320c3ef92035299dabeb3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 536cc43c37f5cd2ccf37a562b44f90ce5b639d0c709bc641bca26c3e96d68426756b8f3749394dbb0039728a8be5c37b52d4345184a1c9a29bf272dd1e82b872
|
7
|
+
data.tar.gz: 369f08b98c04530f3fb46951b79f88054f7a7c8dc6737b62231df685aed59d6a6eb106bdaae69d28cbc0082a727c0e1a0bf12df8308cd8e997340a9864b49447
|
data/README.md
CHANGED
@@ -165,6 +165,47 @@ You can forward arguments in whatever order you like, you simply need to ensure
|
|
165
165
|
Disables environment variable expansion in configuration file.
|
166
166
|
```
|
167
167
|
|
168
|
+
### Introspection
|
169
|
+
|
170
|
+
Litestream offers a handful of commands that allow you to introspect the state of your replication. The gem provides a few rake tasks that wrap these commands for you. For example, you can list the databases that Litestream is configured to replicate:
|
171
|
+
|
172
|
+
```shell
|
173
|
+
bin/rails litestream:databases
|
174
|
+
```
|
175
|
+
|
176
|
+
This will return a list of databases and their configured replicas:
|
177
|
+
|
178
|
+
```
|
179
|
+
path replicas
|
180
|
+
/Users/you/Code/your-app/storage/production.sqlite3 s3
|
181
|
+
```
|
182
|
+
|
183
|
+
You can also list the generations of a specific database:
|
184
|
+
|
185
|
+
```shell
|
186
|
+
bin/rails litestream:generations -- --database=storage/production.sqlite3
|
187
|
+
```
|
188
|
+
|
189
|
+
This will list all generations for the specified database, including stats about their lag behind the primary database and the time range they cover.
|
190
|
+
|
191
|
+
```
|
192
|
+
name generation lag start end
|
193
|
+
s3 a295b16a796689f3 -156ms 2024-04-17T00:01:19Z 2024-04-17T00:01:19Z
|
194
|
+
```
|
195
|
+
|
196
|
+
Finally, you can list the snapshots available for a database:
|
197
|
+
|
198
|
+
```shell
|
199
|
+
bin/rails litestream:snapshots -- --database=storage/production.sqlite3
|
200
|
+
```
|
201
|
+
|
202
|
+
This command lists snapshots available for that specified database:
|
203
|
+
|
204
|
+
```
|
205
|
+
replica generation index size created
|
206
|
+
s3 a295b16a796689f3 1 4645465 2024-04-17T00:01:19Z
|
207
|
+
```
|
208
|
+
|
168
209
|
### Additional commands
|
169
210
|
|
170
211
|
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`.
|
data/lib/litestream/commands.rb
CHANGED
@@ -14,106 +14,120 @@ module Litestream
|
|
14
14
|
# raised when LITESTREAM_INSTALL_DIR does not exist
|
15
15
|
DirectoryNotFoundException = Class.new(StandardError)
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
# raised when a litestream command requires a database argument but it isn't provided
|
18
|
+
DatabaseRequiredException = Class.new(StandardError)
|
19
|
+
|
20
|
+
class << self
|
21
|
+
def platform
|
22
|
+
[:cpu, :os].map { |m| Gem::Platform.local.send(m) }.join("-")
|
23
|
+
end
|
20
24
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
25
|
+
def executable(exe_path: DEFAULT_DIR)
|
26
|
+
litestream_install_dir = ENV["LITESTREAM_INSTALL_DIR"]
|
27
|
+
if litestream_install_dir
|
28
|
+
if File.directory?(litestream_install_dir)
|
29
|
+
warn "NOTE: using LITESTREAM_INSTALL_DIR to find litestream executable: #{litestream_install_dir}"
|
30
|
+
exe_path = litestream_install_dir
|
31
|
+
exe_file = File.expand_path(File.join(litestream_install_dir, "litestream"))
|
32
|
+
else
|
33
|
+
raise DirectoryNotFoundException, <<~MESSAGE
|
34
|
+
LITESTREAM_INSTALL_DIR is set to #{litestream_install_dir}, but that directory does not exist.
|
35
|
+
MESSAGE
|
36
|
+
end
|
28
37
|
else
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
38
|
+
if Litestream::Upstream::NATIVE_PLATFORMS.keys.none? { |p| Gem::Platform.match_gem?(Gem::Platform.new(p), GEM_NAME) }
|
39
|
+
raise UnsupportedPlatformException, <<~MESSAGE
|
40
|
+
litestream-ruby does not support the #{platform} platform
|
41
|
+
Please install litestream following instructions at https://litestream.io/install
|
42
|
+
MESSAGE
|
43
|
+
end
|
44
|
+
|
45
|
+
exe_file = Dir.glob(File.expand_path(File.join(exe_path, "*", "litestream"))).find do |f|
|
46
|
+
Gem::Platform.match_gem?(Gem::Platform.new(File.basename(File.dirname(f))), GEM_NAME)
|
47
|
+
end
|
39
48
|
end
|
40
49
|
|
41
|
-
exe_file
|
42
|
-
|
43
|
-
|
44
|
-
end
|
50
|
+
if exe_file.nil? || !File.exist?(exe_file)
|
51
|
+
raise ExecutableNotFoundException, <<~MESSAGE
|
52
|
+
Cannot find the litestream executable for #{platform} in #{exe_path}
|
45
53
|
|
46
|
-
|
47
|
-
raise ExecutableNotFoundException, <<~MESSAGE
|
48
|
-
Cannot find the litestream executable for #{platform} in #{exe_path}
|
54
|
+
If you're using bundler, please make sure you're on the latest bundler version:
|
49
55
|
|
50
|
-
|
56
|
+
gem install bundler
|
57
|
+
bundle update --bundler
|
51
58
|
|
52
|
-
|
53
|
-
bundle update --bundler
|
59
|
+
Then make sure your lock file includes this platform by running:
|
54
60
|
|
55
|
-
|
61
|
+
bundle lock --add-platform #{platform}
|
62
|
+
bundle install
|
56
63
|
|
57
|
-
|
58
|
-
|
64
|
+
See `bundle lock --help` output for details.
|
65
|
+
|
66
|
+
If you're still seeing this message after taking those steps, try running
|
67
|
+
`bundle config` and ensure `force_ruby_platform` isn't set to `true`. See
|
68
|
+
https://github.com/fractaledmind/litestream-ruby#check-bundle_force_ruby_platform
|
69
|
+
for more details.
|
70
|
+
MESSAGE
|
71
|
+
end
|
59
72
|
|
60
|
-
|
73
|
+
exe_file
|
74
|
+
end
|
61
75
|
|
62
|
-
|
63
|
-
|
64
|
-
https://github.com/fractaledmind/litestream-ruby#check-bundle_force_ruby_platform
|
65
|
-
for more details.
|
66
|
-
MESSAGE
|
76
|
+
def replicate(argv = {})
|
77
|
+
execute("replicate", argv)
|
67
78
|
end
|
68
79
|
|
69
|
-
|
70
|
-
|
80
|
+
def restore(database, argv = {})
|
81
|
+
raise DatabaseRequiredException, "database argument is required for restore command, e.g. litestream:restore -- --database=path/to/database.sqlite" if database.nil?
|
82
|
+
|
83
|
+
dir, file = File.split(database)
|
84
|
+
ext = File.extname(file)
|
85
|
+
base = File.basename(file, ext)
|
86
|
+
now = Time.now.utc.strftime("%Y%m%d%H%M%S")
|
87
|
+
|
88
|
+
args = {
|
89
|
+
"-o" => File.join(dir, "#{base}-#{now}#{ext}")
|
90
|
+
}.merge(argv)
|
71
91
|
|
72
|
-
|
73
|
-
if Litestream.configuration
|
74
|
-
ENV["LITESTREAM_REPLICA_BUCKET"] ||= Litestream.configuration.replica_bucket
|
75
|
-
ENV["LITESTREAM_ACCESS_KEY_ID"] ||= Litestream.configuration.replica_key_id
|
76
|
-
ENV["LITESTREAM_SECRET_ACCESS_KEY"] ||= Litestream.configuration.replica_access_key
|
92
|
+
execute("restore", args, database)
|
77
93
|
end
|
78
94
|
|
79
|
-
|
80
|
-
|
81
|
-
|
95
|
+
def databases(argv = {})
|
96
|
+
execute("databases", argv)
|
97
|
+
end
|
82
98
|
|
83
|
-
|
84
|
-
|
99
|
+
def generations(database, argv = {})
|
100
|
+
raise DatabaseRequiredException, "database argument is required for generations command, e.g. litestream:generations -- --database=path/to/database.sqlite" if database.nil?
|
85
101
|
|
86
|
-
|
87
|
-
# The forked process executes litestream and replaces itself.
|
88
|
-
if fork.nil?
|
89
|
-
exec(*command)
|
102
|
+
execute("generations", argv, database)
|
90
103
|
end
|
91
|
-
end
|
92
104
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
ENV["LITESTREAM_SECRET_ACCESS_KEY"] ||= Litestream.configuration.replica_access_key
|
105
|
+
def snapshots(database, argv = {})
|
106
|
+
raise DatabaseRequiredException, "database argument is required for snapshots command, e.g. litestream:snapshots -- --database=path/to/database.sqlite" if database.nil?
|
107
|
+
|
108
|
+
execute("snapshots", argv, database)
|
98
109
|
end
|
99
110
|
|
100
|
-
|
101
|
-
ext = File.extname(file)
|
102
|
-
base = File.basename(file, ext)
|
103
|
-
now = Time.now.utc.strftime("%Y%m%d%H%M%S")
|
111
|
+
private
|
104
112
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
113
|
+
def execute(command, argv = {}, database = nil)
|
114
|
+
if Litestream.configuration
|
115
|
+
ENV["LITESTREAM_REPLICA_BUCKET"] ||= Litestream.configuration.replica_bucket
|
116
|
+
ENV["LITESTREAM_ACCESS_KEY_ID"] ||= Litestream.configuration.replica_key_id
|
117
|
+
ENV["LITESTREAM_SECRET_ACCESS_KEY"] ||= Litestream.configuration.replica_access_key
|
118
|
+
end
|
109
119
|
|
110
|
-
|
111
|
-
|
120
|
+
args = {
|
121
|
+
"--config" => Rails.root.join("config", "litestream.yml").to_s
|
122
|
+
}.merge(argv).to_a.flatten.compact
|
123
|
+
cmd = [executable, command, *args, database].compact
|
112
124
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
125
|
+
# To release the resources of the Ruby process, just fork and exit.
|
126
|
+
# The forked process executes litestream and replaces itself.
|
127
|
+
if fork.nil?
|
128
|
+
puts cmd.inspect if ENV["DEBUG"]
|
129
|
+
exec(*cmd)
|
130
|
+
end
|
117
131
|
end
|
118
132
|
end
|
119
133
|
end
|
data/lib/litestream/version.rb
CHANGED
@@ -36,4 +36,40 @@ namespace :litestream do
|
|
36
36
|
|
37
37
|
Litestream::Commands.restore(options.delete("--database") || options.delete("-database"), options)
|
38
38
|
end
|
39
|
+
|
40
|
+
desc "List all databases and associated replicas in the config file, e.g. rake litestream:databases -- -no-expand-env"
|
41
|
+
task databases: :environment do
|
42
|
+
options = {}
|
43
|
+
if (separator_index = ARGV.index("--"))
|
44
|
+
ARGV.slice(separator_index + 1, ARGV.length)
|
45
|
+
.map { |pair| pair.split("=") }
|
46
|
+
.each { |opt| options[opt[0]] = opt[1] || nil }
|
47
|
+
end
|
48
|
+
|
49
|
+
Litestream::Commands.databases(options)
|
50
|
+
end
|
51
|
+
|
52
|
+
desc "List all generations for a database or replica, e.g. rake litestream:generations -- -database=storage/production.sqlite3"
|
53
|
+
task generations: :environment do
|
54
|
+
options = {}
|
55
|
+
if (separator_index = ARGV.index("--"))
|
56
|
+
ARGV.slice(separator_index + 1, ARGV.length)
|
57
|
+
.map { |pair| pair.split("=") }
|
58
|
+
.each { |opt| options[opt[0]] = opt[1] || nil }
|
59
|
+
end
|
60
|
+
|
61
|
+
Litestream::Commands.generations(options.delete("--database") || options.delete("-database"), options)
|
62
|
+
end
|
63
|
+
|
64
|
+
desc "List all snapshots for a database or replica, e.g. rake litestream:snapshots -- -database=storage/production.sqlite3"
|
65
|
+
task snapshots: :environment do
|
66
|
+
options = {}
|
67
|
+
if (separator_index = ARGV.index("--"))
|
68
|
+
ARGV.slice(separator_index + 1, ARGV.length)
|
69
|
+
.map { |pair| pair.split("=") }
|
70
|
+
.each { |opt| options[opt[0]] = opt[1] || nil }
|
71
|
+
end
|
72
|
+
|
73
|
+
Litestream::Commands.snapshots(options.delete("--database") || options.delete("-database"), options)
|
74
|
+
end
|
39
75
|
end
|