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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3131a24decfd36e4e367992b360c56cd6cf5d539abe16cfec180f4b9c706a2c4
4
- data.tar.gz: 557d0967cecab000d09d71be59d740c8dd8e07c7203c4c6fad460132856a57c0
3
+ metadata.gz: 49adc00f53f6eed0427ea5a203c31bfc5e952b09315f1c6efdacaa063e039f0c
4
+ data.tar.gz: 462d08c90c1845f3dcb910c032859fef21c2cec4fc0320c3ef92035299dabeb3
5
5
  SHA512:
6
- metadata.gz: e3d85c6c1779d4b51d788d076483b2f1d9fc225770134f8cff715e080431942db1dde4b39961dadb63d427f0e95c0dbda01c792b1c5be2fb2e89eaea80001b83
7
- data.tar.gz: 18bc9544186a5965350a28789107e8839fe58a02d82774137061ae508f981437a239cba6b67bb2bd66957e5fe05c5738ca67a760220f9a901896ced2ef79f404
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`.
@@ -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-darwin
6
6
  authors:
7
7
  - Stephen Margheim