litestream 0.5.0-x86_64-linux → 0.5.1-x86_64-linux

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b76c2f2d900ef4acecee6dda18c2347262dc50b5017228f1f9a74a9f24e7acdf
4
- data.tar.gz: 3cce5e25ab5e461c9f1c7f1b721924ea7a60fd9fe7338ef212305fbf535aebf1
3
+ metadata.gz: 729b379a492cfd9b1105012eda88040a7c5442498c6ee83f3afac5c0d2e9b7d9
4
+ data.tar.gz: 30d4e5b071868893ff9ad0597b94fe2e0e32abd77fc928c736829e65b38913fa
5
5
  SHA512:
6
- metadata.gz: 82e4f3a3326df997d56086f5263d64d5be93a6779d1a10f3cbc5769b64637765c58acb87967a0553d7e4ed0738c59f604daa8656b5601825ef5d033eab52b3ea
7
- data.tar.gz: 92b1150f4c347fd1ff8bdce01105657e1baf88ae25b55c6badfd455bc2e8db974124a89132213bcbec5ac4c9b0185177a5c16da4cc383eff976789dcd8939326
6
+ metadata.gz: 8425ee62f03e72f3a4afdfefd2f05971ceb553f9b9e6bd0a97209357a457ea6c6c3b66dbaaa408af5d27f2912f8be66fc41be213dc5efc074d04ec14764d799f
7
+ data.tar.gz: 47916adf85f2f8ed40a1c10de77c43b800abaa10f8786c511810d30a950f6d96e4951d0251539f649b449102f6f2db476d3991614a6de2f1f84e259904a5a897
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`.
@@ -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
- def self.platform
18
- [:cpu, :os].map { |m| Gem::Platform.local.send(m) }.join("-")
19
- end
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
- def self.executable(exe_path: DEFAULT_DIR)
22
- litestream_install_dir = ENV["LITESTREAM_INSTALL_DIR"]
23
- if litestream_install_dir
24
- if File.directory?(litestream_install_dir)
25
- warn "NOTE: using LITESTREAM_INSTALL_DIR to find litestream executable: #{litestream_install_dir}"
26
- exe_path = litestream_install_dir
27
- exe_file = File.expand_path(File.join(litestream_install_dir, "litestream"))
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
- raise DirectoryNotFoundException, <<~MESSAGE
30
- LITESTREAM_INSTALL_DIR is set to #{litestream_install_dir}, but that directory does not exist.
31
- MESSAGE
32
- end
33
- else
34
- if Litestream::Upstream::NATIVE_PLATFORMS.keys.none? { |p| Gem::Platform.match_gem?(Gem::Platform.new(p), GEM_NAME) }
35
- raise UnsupportedPlatformException, <<~MESSAGE
36
- litestream-ruby does not support the #{platform} platform
37
- Please install litestream following instructions at https://litestream.io/install
38
- MESSAGE
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 = Dir.glob(File.expand_path(File.join(exe_path, "*", "litestream"))).find do |f|
42
- Gem::Platform.match_gem?(Gem::Platform.new(File.basename(File.dirname(f))), GEM_NAME)
43
- end
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
- if exe_file.nil? || !File.exist?(exe_file)
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
- If you're using bundler, please make sure you're on the latest bundler version:
56
+ gem install bundler
57
+ bundle update --bundler
51
58
 
52
- gem install bundler
53
- bundle update --bundler
59
+ Then make sure your lock file includes this platform by running:
54
60
 
55
- Then make sure your lock file includes this platform by running:
61
+ bundle lock --add-platform #{platform}
62
+ bundle install
56
63
 
57
- bundle lock --add-platform #{platform}
58
- bundle install
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
- See `bundle lock --help` output for details.
73
+ exe_file
74
+ end
61
75
 
62
- If you're still seeing this message after taking those steps, try running
63
- `bundle config` and ensure `force_ruby_platform` isn't set to `true`. See
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
- exe_file
70
- end
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
- def self.replicate(argv = {})
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
- args = {
80
- "--config" => Rails.root.join("config", "litestream.yml").to_s
81
- }.merge(argv).to_a.flatten.compact
95
+ def databases(argv = {})
96
+ execute("databases", argv)
97
+ end
82
98
 
83
- command = [executable, "replicate", *args]
84
- puts command.inspect
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
- # To release the resources of the Ruby process, just fork and exit.
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
- def self.restore(database, argv = {})
94
- if Litestream.configuration
95
- ENV["LITESTREAM_REPLICA_BUCKET"] ||= Litestream.configuration.replica_bucket
96
- ENV["LITESTREAM_ACCESS_KEY_ID"] ||= Litestream.configuration.replica_key_id
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
- dir, file = File.split(database)
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
- args = {
106
- "--config" => Rails.root.join("config", "litestream.yml").to_s,
107
- "-o" => File.join(dir, "#{base}-#{now}#{ext}")
108
- }.merge(argv).to_a.flatten.compact
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
- command = [executable, "restore", *args, database]
111
- puts command.inspect
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
- # To release the resources of the Ruby process, just fork and exit.
114
- # The forked process executes litestream and replaces itself.
115
- if fork.nil?
116
- exec(*command)
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
@@ -1,3 +1,3 @@
1
1
  module Litestream
2
- VERSION = "0.5.0"
2
+ VERSION = "0.5.1"
3
3
  end
@@ -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
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: litestream
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.5.1
5
5
  platform: x86_64-linux
6
6
  authors:
7
7
  - Stephen Margheim