litestream 0.4.0-x86_64-darwin → 0.5.1-x86_64-darwin
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 +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
|