redis-copy 0.0.1 → 0.0.2
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.
- data/README.md +44 -9
- data/lib/redis-copy.rb +2 -3
- data/lib/redis-copy/cli.rb +12 -6
- data/lib/redis-copy/key-emitter.rb +19 -0
- data/lib/redis-copy/version.rb +1 -1
- data/redis-copy.gemspec +4 -0
- data/spec/redis-copy/key-emitter_spec.rb +1 -1
- metadata +4 -2
data/README.md
CHANGED
@@ -1,24 +1,59 @@
|
|
1
1
|
# Redis::Copy
|
2
2
|
|
3
|
-
|
3
|
+
This utility provides a way to move the contents of one redis DB to another
|
4
|
+
redis DB. It is inspired by the [redis-copy.rb script][original] included in
|
5
|
+
the redis source, but supports the following additional features:
|
6
|
+
|
7
|
+
- all known data types (original supported `set`, `list`, and `string`,
|
8
|
+
dropping the others without warning)
|
9
|
+
- if available on both dbs, will use `DUMP`/`RESTORE` commands (redis v2.6+)
|
10
|
+
- support for more than just db0
|
11
|
+
|
12
|
+
[original]: https://github.com/antirez/redis/commits/unstable/utils/redis-copy.rb
|
4
13
|
|
5
14
|
## Installation
|
6
15
|
|
7
|
-
|
16
|
+
$ gem install redis-copy
|
8
17
|
|
9
|
-
|
18
|
+
## Usage
|
10
19
|
|
11
|
-
|
20
|
+
The current options can be grabbed using the `--help` flag.
|
12
21
|
|
13
|
-
|
22
|
+
```
|
23
|
+
$ redis-copy --help
|
24
|
+
redis-copy v0.0.2
|
25
|
+
Usage: redis-copy [options] <source> <destination>
|
26
|
+
<source> and <destination> must be redis connection uris
|
27
|
+
like [redis://]<hostname>[:<port>][/<db>]
|
14
28
|
|
15
|
-
|
29
|
+
Specific options:
|
30
|
+
--strategy STRATEGY Select strategy (auto, new, classic) (default auto)
|
31
|
+
auto: uses new if available, otherwise fallback
|
32
|
+
new: use redis DUMP and RESTORE commands (faster)
|
33
|
+
classic: migrates via multiple type-specific commands
|
34
|
+
--[no-]dry-run Output configuration and exit
|
35
|
+
-d, --[no-]debug Write debug output
|
36
|
+
-t, --[no-]trace Enable backtrace on failure
|
37
|
+
-f, --[no-]fail-fast Abort on first failure
|
38
|
+
-y, --yes Automatically accept any prompts
|
39
|
+
--[no-]allow-nonempty Allow non-empty destination
|
16
40
|
|
17
|
-
|
41
|
+
```
|
18
42
|
|
19
|
-
##
|
43
|
+
## Example:
|
20
44
|
|
21
|
-
|
45
|
+
```
|
46
|
+
$ redis-copy --fail-fast --yes old.redis.host/9 new.redis.host:6380/3
|
47
|
+
Source: redis://old.redis.host:6379/9
|
48
|
+
Destination: redis://new.redis.host:6380/3 (empty)
|
49
|
+
Key Emitter: Default
|
50
|
+
Strategy: New
|
51
|
+
PROGRESS {:success=>1000, :attempt=>1000}
|
52
|
+
PROGRESS {:success=>2000, :attempt=>2000}
|
53
|
+
PROGRESS {:success=>3000, :attempt=>3000}
|
54
|
+
PROGRESS {:success=>4000, :attempt=>4000}
|
55
|
+
DONE: {:success=>4246, :attempt=>4246}
|
56
|
+
```
|
22
57
|
|
23
58
|
## Contributing
|
24
59
|
|
data/lib/redis-copy.rb
CHANGED
@@ -15,7 +15,6 @@ module RedisCopy
|
|
15
15
|
# @param destination [String]
|
16
16
|
# @options options [Hash<Symbol,Object>]
|
17
17
|
def copy(source, destination, options = {})
|
18
|
-
puts options.inspect
|
19
18
|
ui = UI.load(options)
|
20
19
|
|
21
20
|
source = redis_from(source)
|
@@ -35,7 +34,7 @@ module RedisCopy
|
|
35
34
|
Strategy: #{strategem}
|
36
35
|
EODESC
|
37
36
|
|
38
|
-
ui.abort('Destination not empty!') unless dest_empty
|
37
|
+
ui.abort('Destination not empty!') unless dest_empty or options[:allow_nonempty]
|
39
38
|
|
40
39
|
key_emitter.keys.each_with_object(Hash.new {0}) do |key, stats|
|
41
40
|
success = strategem.copy(key)
|
@@ -46,7 +45,7 @@ module RedisCopy
|
|
46
45
|
ui.notify("FAIL: #{key.dump}")
|
47
46
|
ui.abort if options[:fail_fast]
|
48
47
|
end
|
49
|
-
ui.notify(stats.inspect) if (stats[:attempt] % 1000).zero?
|
48
|
+
ui.notify("PROGRESS: #{stats.inspect}") if (stats[:attempt] % 1000).zero?
|
50
49
|
end.tap do |stats|
|
51
50
|
ui.notify("DONE: #{stats.inspect}")
|
52
51
|
end
|
data/lib/redis-copy/cli.rb
CHANGED
@@ -7,11 +7,12 @@ module RedisCopy
|
|
7
7
|
class CLI
|
8
8
|
REDIS_URI = (/\A(?:redis:\/\/)?([a-z0-9\-.]+)(:[0-9]{1,5})?(\/(?:(?:1[0-5])|[0-9]))?\z/i).freeze
|
9
9
|
DEFAULTS = {
|
10
|
-
ui:
|
11
|
-
key_emitter:
|
12
|
-
strategy:
|
13
|
-
fail_fast:
|
14
|
-
yes:
|
10
|
+
ui: :command_line,
|
11
|
+
key_emitter: :default,
|
12
|
+
strategy: :auto,
|
13
|
+
fail_fast: false,
|
14
|
+
yes: false,
|
15
|
+
allow_nonempty: false,
|
15
16
|
}.freeze unless defined?(DEFAULTS)
|
16
17
|
|
17
18
|
def initialize(argv = ARGV)
|
@@ -19,8 +20,9 @@ module RedisCopy
|
|
19
20
|
options = {}
|
20
21
|
|
21
22
|
OptionParser.new do |opts|
|
22
|
-
opts.banner = "Usage: #{opts.program_name} [options] <source> <destination>"
|
23
23
|
opts.version = RedisCopy::VERSION
|
24
|
+
opts.banner = "#{opts.program_name} v#{opts.version}\n" +
|
25
|
+
"Usage: #{opts.program_name} [options] <source> <destination>"
|
24
26
|
|
25
27
|
indent_desc = proc do |desc|
|
26
28
|
desc.split("\n").join("\n#{opts.summary_indent}#{' '*opts.summary_width} ")
|
@@ -62,6 +64,10 @@ module RedisCopy
|
|
62
64
|
options[:yes] = true
|
63
65
|
end
|
64
66
|
|
67
|
+
opts.on('--[no-]allow-nonempty', 'Allow non-empty destination') do |allow_nonempty|
|
68
|
+
options[:allow_nonempty] = allow_nonempty
|
69
|
+
end
|
70
|
+
|
65
71
|
opts.parse!(argv)
|
66
72
|
unless argv.size == 2
|
67
73
|
opts.abort "Source and Destination must be specified\n\n" +
|
@@ -36,6 +36,25 @@ module RedisCopy
|
|
36
36
|
class Default
|
37
37
|
include KeyEmitter
|
38
38
|
|
39
|
+
def initialize(redis, ui, options = {})
|
40
|
+
ui.abort unless ui.confirm? <<-EOWARNING.strip_heredoc
|
41
|
+
WARNING: #{self} key emitter uses redis.keys('*') to
|
42
|
+
get its list of keys.
|
43
|
+
|
44
|
+
The redis keys command [reference](http://redis.io/commands/keys)
|
45
|
+
says this:
|
46
|
+
|
47
|
+
> Warning: consider KEYS as a command that should only be used
|
48
|
+
> in production environments with extreme care. It may ruin
|
49
|
+
> performance when it is executed against large databases.
|
50
|
+
> This command is intended for debugging and special operations,
|
51
|
+
> such as changing your keyspace layout. Don't use KEYS in your
|
52
|
+
> regular application code. If you're looking for a way to find
|
53
|
+
> keys in a subset of your keyspace, consider using sets.
|
54
|
+
EOWARNING
|
55
|
+
super
|
56
|
+
end
|
57
|
+
|
39
58
|
def keys
|
40
59
|
@ui.debug "REDIS: #{@redis.client.id} KEYS *"
|
41
60
|
@redis.keys('*').to_enum
|
data/lib/redis-copy/version.rb
CHANGED
data/redis-copy.gemspec
CHANGED
@@ -16,6 +16,10 @@ Gem::Specification.new do |spec|
|
|
16
16
|
spec.authors = authors_and_emails.map(&:first)
|
17
17
|
spec.email = authors_and_emails.map(&:last)
|
18
18
|
spec.summary = 'Copy the contents of one redis db to another'
|
19
|
+
spec.description = 'A command-line utility built for copying the ' +
|
20
|
+
'contents of one redis db to another over a ' +
|
21
|
+
'network. Supports all data types, persists ttls, ' +
|
22
|
+
'and attempts to be as efficient as possible.'
|
19
23
|
spec.homepage = 'https://github.com/yaauie/redis-copy'
|
20
24
|
spec.license = 'MIT'
|
21
25
|
|
@@ -3,7 +3,7 @@ require 'redis-copy'
|
|
3
3
|
|
4
4
|
describe RedisCopy::KeyEmitter::Default do
|
5
5
|
let(:redis) { double }
|
6
|
-
let(:ui) { double }
|
6
|
+
let(:ui) { double.as_null_object }
|
7
7
|
let(:instance) { RedisCopy::KeyEmitter::Default.new(redis, ui)}
|
8
8
|
let(:connection_uri) { 'redis://12.34.56.78:9000/15' }
|
9
9
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redis-copy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -91,7 +91,9 @@ dependencies:
|
|
91
91
|
- - ! '>='
|
92
92
|
- !ruby/object:Gem::Version
|
93
93
|
version: '0'
|
94
|
-
description:
|
94
|
+
description: A command-line utility built for copying the contents of one redis db
|
95
|
+
to another over a network. Supports all data types, persists ttls, and attempts
|
96
|
+
to be as efficient as possible.
|
95
97
|
email:
|
96
98
|
- ryan@yaauie.com
|
97
99
|
executables:
|