redis-copy 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,24 +1,59 @@
1
1
  # Redis::Copy
2
2
 
3
- TODO: Write a gem description
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
- Add this line to your application's Gemfile:
16
+ $ gem install redis-copy
8
17
 
9
- gem 'redis-copy'
18
+ ## Usage
10
19
 
11
- And then execute:
20
+ The current options can be grabbed using the `--help` flag.
12
21
 
13
- $ bundle
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
- Or install it yourself as:
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
- $ gem install redis-copy
41
+ ```
18
42
 
19
- ## Usage
43
+ ## Example:
20
44
 
21
- TODO: Write usage instructions here
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
@@ -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: :command_line,
11
- key_emitter: :default,
12
- strategy: :auto,
13
- fail_fast: false,
14
- yes: false,
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
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module RedisCopy
4
- VERSION = '0.0.1'
4
+ VERSION = '0.0.2'
5
5
  end
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.1
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: