litestream 0.5.3-arm64-darwin → 0.5.5-arm64-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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3e62818c3cd5758ff7ff63831ff5e9196ba6734cd8bdbbbf828b1593dce48ac6
4
- data.tar.gz: f0fc37c1a8f1723b880500307ba0b1ec79f620971be1dc7eadd888e5787ec247
3
+ metadata.gz: f4a5c5ae7fdeb51f926aa3d7e75310dac1f3b8cc9d4fb462d37cbb0135e1ad05
4
+ data.tar.gz: e12caf009c5915e769b185638d4b3dae3a52ea7922711512f1203b984b1424fb
5
5
  SHA512:
6
- metadata.gz: 7b8bb348df79657ff336e98733185ee7cc9dab56957890a27eb0fe257b6bf6b09300fa40f9264c384277a63310e3f91dc53990df190da719303d91b7ab92b2ab
7
- data.tar.gz: c97a8ac25384e8993733bfd9abfd6b9b6658bfaa35fb0aaf081eda3473c7a2425ac9c35f6aae56d0c2a3afad58d3526a0321246b1f9f2dfa49d5c804b301f612
6
+ metadata.gz: d415cd48549eb62928c83fcfbb845fc4ef248fd5f23b2ed98afed2b0a84bfa61a8a3766146c4965b6188a06d197242c45dac370644a466927c961113a36b680d
7
+ data.tar.gz: 8f02d3d01c8cc5e703238dc2c8c8ba7a881b42daae13da13f540a21961ce0ecc45756981ee9739b8f12e2313bccc92559c6d5de31f9a3e84719fb52e54b80948
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: $LITESTREAM_DATABASE_PATH
56
+ - path: storage/production.sqlite3
57
57
  replicas:
58
- - url: $LITESTREAM_REPLICA_BUCKET
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
- ### Additional commands
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"
@@ -76,11 +76,11 @@ module Litestream
76
76
  exe_file
77
77
  end
78
78
 
79
- def replicate(async: true, **argv)
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: true, **argv)
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 databases(async: true, **argv)
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: {original: original_size, restored: restored_size},
133
- tables: {original: original_tables_count, restored: restored_tables_count}
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: true)
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
@@ -145,18 +150,28 @@ module Litestream
145
150
 
146
151
  args = {
147
152
  "--config" => Rails.root.join("config", "litestream.yml").to_s
148
- }.merge(argv).to_a.flatten.compact
153
+ }.merge(argv.stringify_keys).to_a.flatten.compact
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
- system(*cmd)
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
@@ -1,3 +1,3 @@
1
1
  module Litestream
2
- VERSION = "0.5.3"
2
+ VERSION = "0.5.5"
3
3
  end
data/lib/litestream.rb CHANGED
@@ -11,7 +11,7 @@ module Litestream
11
11
  end
12
12
 
13
13
  class Configuration
14
- attr_accessor :database_path, :replica_bucket, :replica_key_id, :replica_access_key
14
+ attr_accessor :replica_bucket, :replica_key_id, :replica_access_key
15
15
 
16
16
  def initialize
17
17
  end
@@ -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(options.delete("--database") || options.delete("-database"), **options)
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(options.delete("--database") || options.delete("-database"), **options)
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(options.delete("--database") || options.delete("-database"), **options)
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(options.delete("--database") || options.delete("-database"), **options)
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.3
4
+ version: 0.5.5
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-17 00:00:00.000000000 Z
11
+ date: 2024-04-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubyzip