prize 0.1.1 → 0.3.0

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: 82411ca26768e8b46a215ffd04d3d91e4948718ccb65aa676ff4191ae8c3366f
4
- data.tar.gz: b5bde5e58dbf8237ce8d781747e55093e63f2001f4548980eab2c5140c982596
3
+ metadata.gz: e5d5d94d02356ee18c3dad96ac30d013a3cc20e26d0aa64614bf11935c927524
4
+ data.tar.gz: abccbe946f44b040a02c85df0b5a1c9decceabed42455f6953bba5d5304afbf7
5
5
  SHA512:
6
- metadata.gz: 0d47a4757e58984d192145a0cc10f0904c6d385e0913be728f2dd637f742f06a708772366fca2e4ed52babb745431734c8dfed8c61f5ee92ba906065499c55a5
7
- data.tar.gz: 8c250766efaca424210ebb3be2e09eb00c64e61d9aecb407538d2f6a30dc53a63647a47aacc0b74de0e422ad7428c0869a67845c1bff21cbedd6fe3c94a394de
6
+ metadata.gz: 0d4dc34770bec250fa5fbf281ca6c6512585b2a7dc938e63a495e9ca6724a2bfdd8c6db5cda05f677add58255319d25c7aadc9536fe491b1f4ed261696dbc073
7
+ data.tar.gz: 81d5e92ae7c568501f31e8f7ffb62d0110252e1b8a6c5e37ef51141509be3d527b692130f0a7d22089af6ecc7ff9fd1fed92bc07dc0fc0ebd4c5cb2e43d82f3e
data/.gitignore CHANGED
@@ -6,6 +6,3 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
-
10
- # rspec failure tracking
11
- .rspec_status
@@ -68,7 +68,7 @@ members of the project's leadership.
68
68
  ## Attribution
69
69
 
70
70
  This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
- available at [http://contributor-covenant.org/version/1/4][version]
71
+ available at [https://contributor-covenant.org/version/1/4][version]
72
72
 
73
- [homepage]: http://contributor-covenant.org
74
- [version]: http://contributor-covenant.org/version/1/4/
73
+ [homepage]: https://contributor-covenant.org
74
+ [version]: https://contributor-covenant.org/version/1/4/
data/Gemfile CHANGED
@@ -1,6 +1,6 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
-
5
3
  # Specify your gem's dependencies in prize.gemspec
6
4
  gemspec
5
+
6
+ gem "rake", "~> 12.0"
@@ -1,60 +1,62 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- prize (0.1.1)
5
- activesupport
6
- hiredis (>= 0.6.0)
7
- pry (>= 0.12.0)
8
- redis (>= 4.0.0)
4
+ prize (0.3.0)
5
+ activesupport (~> 6.0.3)
6
+ hiredis (~> 0.6.0)
7
+ net-ssh-gateway (~> 2.0.0)
8
+ pry (~> 0.13.1)
9
+ pry-byebug (~> 3.9.0)
10
+ pry-doc (~> 1.1.0)
11
+ rainbow (~> 3.0.0)
12
+ redis (~> 4.0.0)
9
13
  thor (~> 0.20.0)
10
14
 
11
15
  GEM
12
16
  remote: https://rubygems.org/
13
17
  specs:
14
- activesupport (5.2.3)
18
+ activesupport (6.0.3.2)
15
19
  concurrent-ruby (~> 1.0, >= 1.0.2)
16
20
  i18n (>= 0.7, < 2)
17
21
  minitest (~> 5.1)
18
22
  tzinfo (~> 1.1)
19
- coderay (1.1.2)
20
- concurrent-ruby (1.1.5)
21
- diff-lcs (1.3)
23
+ zeitwerk (~> 2.2, >= 2.2.2)
24
+ byebug (11.1.3)
25
+ coderay (1.1.3)
26
+ concurrent-ruby (1.1.7)
22
27
  hiredis (0.6.3)
23
- i18n (1.6.0)
28
+ i18n (1.8.5)
24
29
  concurrent-ruby (~> 1.0)
25
- method_source (0.9.2)
26
- minitest (5.11.3)
27
- pry (0.12.2)
28
- coderay (~> 1.1.0)
29
- method_source (~> 0.9.0)
30
- rake (10.5.0)
31
- redis (4.1.2)
32
- rspec (3.8.0)
33
- rspec-core (~> 3.8.0)
34
- rspec-expectations (~> 3.8.0)
35
- rspec-mocks (~> 3.8.0)
36
- rspec-core (3.8.2)
37
- rspec-support (~> 3.8.0)
38
- rspec-expectations (3.8.4)
39
- diff-lcs (>= 1.2.0, < 2.0)
40
- rspec-support (~> 3.8.0)
41
- rspec-mocks (3.8.1)
42
- diff-lcs (>= 1.2.0, < 2.0)
43
- rspec-support (~> 3.8.0)
44
- rspec-support (3.8.2)
30
+ method_source (1.0.0)
31
+ minitest (5.14.1)
32
+ net-ssh (6.1.0)
33
+ net-ssh-gateway (2.0.0)
34
+ net-ssh (>= 4.0.0)
35
+ pry (0.13.1)
36
+ coderay (~> 1.1)
37
+ method_source (~> 1.0)
38
+ pry-byebug (3.9.0)
39
+ byebug (~> 11.0)
40
+ pry (~> 0.13.0)
41
+ pry-doc (1.1.0)
42
+ pry (~> 0.11)
43
+ yard (~> 0.9.11)
44
+ rainbow (3.0.0)
45
+ rake (12.3.3)
46
+ redis (4.0.3)
45
47
  thor (0.20.3)
46
48
  thread_safe (0.3.6)
47
- tzinfo (1.2.5)
49
+ tzinfo (1.2.7)
48
50
  thread_safe (~> 0.1)
51
+ yard (0.9.25)
52
+ zeitwerk (2.4.0)
49
53
 
50
54
  PLATFORMS
51
55
  ruby
52
56
 
53
57
  DEPENDENCIES
54
- bundler (~> 1.17)
55
58
  prize!
56
- rake (~> 10.0)
57
- rspec (~> 3.0)
59
+ rake (~> 12.0)
58
60
 
59
61
  BUNDLED WITH
60
- 1.17.2
62
+ 2.1.2
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2019 Liu Xiang
3
+ Copyright (c) 2020 Liu Xiang
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -1,28 +1,37 @@
1
- # prize
1
+ # Prize
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/prize`. To experiment with that code, run `bin/console` for an interactive prompt.
4
-
5
- TODO: Delete this and the text above, and describe your gem
3
+ Simple Redis CLI client with pry loaded
6
4
 
7
5
  ## Installation
8
6
 
9
- Add this line to your application's Gemfile:
10
7
 
11
- ```ruby
12
- gem 'prize'
13
- ```
8
+ Install it yourself as:
14
9
 
15
- And then execute:
10
+ $ gem install prize
16
11
 
17
- $ bundle
12
+ Or:
18
13
 
19
- Or install it yourself as:
20
-
21
- $ gem install prize
14
+ $ sudo gem install prize
22
15
 
23
16
  ## Usage
24
17
 
25
- TODO: Write usage instructions here
18
+ ```
19
+ Commands:
20
+ prize # Simple Redis CLI client with Pry loaded
21
+ prize help [COMMAND] # Describe available commands or one specific command
22
+
23
+ Options:
24
+ -u, [--url=URL] # Server URL, for a TCP connection: `redis://:[password]@[hostname]:[port]/[db]` (password, port and database are optional), for a unix socket connection: `unix://[path to Redis socket]`. This overrides all other options.
25
+ -h, [--host=HOST] # Server hostname (default: 127.0.0.1)
26
+ -p, [--port=N] # Server port (default: 6379)
27
+ -s, --socket, [--path=PATH] # Server socket (overrides hostname and port)
28
+ [--timeout=N] # Timeout in seconds (default: 5.0)
29
+ [--connect-timeout=N] # Timeout for initial connect in seconds (default: same as timeout)
30
+ -a, [--password=PASSWORD] # Password to authenticate against server
31
+ -n, [--db=N] # Database number (default: 0)
32
+ [--replica], [--no-replica] # Whether to use readonly replica nodes in Redis Cluster or not
33
+ [--cluster=CLUSTER] # List of cluster nodes to contact, format: URL1,URL2,URL3...
34
+ ```
26
35
 
27
36
  ## Development
28
37
 
data/Rakefile CHANGED
@@ -1,6 +1,2 @@
1
1
  require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
3
-
4
- RSpec::Core::RakeTask.new(:spec)
5
-
6
2
  task :default => :spec
data/exe/prize CHANGED
@@ -1,5 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'prize'
3
+ PrizeSetsidWrrapper = File.dirname(File.absolute_path(__FILE__)) + '/prize_setsid_wrapper'
4
+
5
+ require "prize"
4
6
 
5
7
  Prize::Cli.start
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ Process.setsid
4
+
5
+ exec(*ARGV)
@@ -1,2 +1,10 @@
1
1
  require "prize/version"
2
+ require 'prize/id'
3
+ require 'prize/ext'
4
+ require "prize/repl"
5
+ require "prize/ssh_proxy"
6
+ require "prize/app"
2
7
  require "prize/cli"
8
+
9
+ module Prize
10
+ end
@@ -0,0 +1,72 @@
1
+ require 'net/ssh/gateway'
2
+ require 'redis'
3
+
4
+ module Prize
5
+ class App
6
+
7
+ class << self
8
+ attr_accessor :options, :redis, :redis_client
9
+ end
10
+
11
+ def initialize(options)
12
+ require 'active_support/all'
13
+ @options = options
14
+ load_initializer!
15
+ @redis = Redis.new(connect_options)
16
+ App.options = @options
17
+ App.redis = @redis
18
+ App.redis_client = @redis.instance_variable_get('@client')
19
+ end
20
+
21
+ def connect_options
22
+ opts = @options.to_h.slice(:url, :host, :port, :path, :db, :password, :timeout,
23
+ :connect_timeout, :replica, :cluster)
24
+ if @options.ssh_host
25
+ proxy = start_ssh_proxy!
26
+ opts.merge!(proxy)
27
+ end
28
+ opts
29
+ end
30
+
31
+ def load_initializer!
32
+ if File.exists?(File.expand_path('~/.prizerc'))
33
+ load(File.expand_path('~/.prizerc'))
34
+ end
35
+ end
36
+
37
+ def start_ssh_proxy!
38
+ ssh_config = {
39
+ host: @options.ssh_host,
40
+ forward_host: @options.host || '127.0.0.1',
41
+ forward_port: @options.port || 6379
42
+ }
43
+ @options.ssh_user.try { |e| ssh_config.merge!(user: e) }
44
+ @options.ssh_port.try { |e| ssh_config.merge!(port: e) }
45
+ @options.ssh_password.try { |e| ssh_config.merge!(password: e) }
46
+ @options.ssh_local_port.try { |e| ssh_config.merge!(local_port: e) }
47
+ local_ssh_proxy_port = Prize::SSHProxy.connect(ssh_config)
48
+ {
49
+ host: '127.0.0.1',
50
+ port: local_ssh_proxy_port
51
+ }
52
+ end
53
+
54
+ def run!
55
+ if @options.code.present?
56
+ @redis.instance_eval(@options.code)
57
+ elsif @options.args.present?
58
+ @options.args.each do |rb|
59
+ @redis.instance_eval(IO.read(rb))
60
+ end
61
+ elsif STDIN.isatty
62
+ run_repl!
63
+ else
64
+ @redis.instance_eval(STDIN.read)
65
+ end
66
+ end
67
+
68
+ def run_repl!
69
+ Repl.new
70
+ end
71
+ end
72
+ end
@@ -1,55 +1,100 @@
1
- require 'thor'
2
- require 'redis'
3
- require 'hiredis'
4
- require 'pry'
1
+ require 'optparse'
2
+ require 'ostruct'
5
3
 
6
4
  module Prize
7
- class Cli < ::Thor
8
-
9
- default_command :main
10
-
11
- desc '', 'Simple Redis CLI client with Pry loaded'
12
- class_option :url, type: :string, aliases: ['-u'], required: false, desc: 'Server URL, for a TCP connection: `redis://:[password]@[hostname]:[port]/[db]` (password, port and database are optional), for a unix socket connection: `unix://[path to Redis socket]`. This overrides all other options.'
13
- class_option :host, type: :string, aliases: ['-h'], required: false, desc: 'Server hostname (default: 127.0.0.1)'
14
- class_option :port, type: :numeric, aliases: ['-p'], required: false, desc: 'Server port (default: 6379)'
15
- class_option :path, type: :string, aliases: ['-s', '--socket'], required: false, desc: 'Server socket (overrides hostname and port)'
16
- class_option :timeout, type: :numeric, required: false, desc: 'Timeout in seconds (default: 5.0)'
17
- class_option :connect_timeout, type: :numeric, required: false, desc: 'Timeout for initial connect in seconds (default: same as timeout)'
18
- class_option :password, type: :string, aliases: ['-a'], required: false, desc: 'Password to authenticate against server'
19
- class_option :db, type: :numeric, aliases: ['-n'], required: false, desc: 'Database number (default: 0)'
20
- class_option :replica, type: :boolean, required: false, desc: 'Whether to use readonly replica nodes in Redis Cluster or not'
21
- class_option :cluster, type: :string, required: false, desc: 'List of cluster nodes to contact, format: URL1,URL2,URL3...'
22
- def main
23
- redis = Redis.new(build_options)
24
- Pry.config.prompt = build_prompt(redis)
25
- Pry.start(redis)
26
- end
27
-
28
- no_commands do
29
- def build_options
30
- opts = options.to_h.merge(driver: :hiredis)
31
- opts['cluster'] = opts['cluster'].split(',') if opts['cluster']
32
- opts
5
+ class Cli
6
+ class << self
7
+ def start
8
+ parse_options!
9
+ App.new(@options).run!
33
10
  end
34
11
 
35
- def build_prompt(redis)
36
- opts = redis.instance_variable_get('@client').options
37
- host = opts[:url] || opts[:path] || "#{opts[:host]}:#{opts[:port]}/#{opts[:db]}"
38
- prompt_fn = proc do |obj, nest_level, _|
39
- p = ""
40
- p += if obj == redis
41
- "Redis<#{host}>:"
42
- else
43
- "#{obj}:"
44
- end
45
- p += "#{nest_level}> "
46
- end
47
-
48
- [prompt_fn,
49
- proc do |obj, nest_level, other|
50
- "*#{prompt_fn.call obj, nest_level, other}"
51
- end
52
- ]
12
+ def parse_options!
13
+ @options = OpenStruct.new
14
+
15
+
16
+ OptionParser.new do |opts|
17
+ opts.banner = <<~EOF
18
+ Usage: prize [options]
19
+ EOF
20
+
21
+ opts.on('-uURL', '--url=URL', 'Server URL, for a TCP connection: `redis://:[password]@[hostname]:[port]/[db]` (password, port and database are optional), for a unix socket connection: `unix://[path to Redis socket]`. This overrides all other options.') do |url|
22
+ @options.url = url
23
+ end
24
+
25
+ opts.on('-hHOST', '--host=HOST', 'Server hostname (default: 127.0.0.1)') do |host|
26
+ @options.host = host
27
+ end
28
+
29
+ opts.on('-pPORT', '--port=PORT', 'Server port (default: 6379)') do |port|
30
+ @options.port = port.to_i
31
+ end
32
+
33
+ opts.on('-sPATH', '--sock=PATH', 'Server socket (overrides hostname and port)') do |path|
34
+ @options.path = path
35
+ end
36
+
37
+ opts.on('-dDB', '--db=DB', 'Specify database') do |db|
38
+ @options.db = db
39
+ end
40
+
41
+ opts.on('-PPASSWORD', '--password=PASSWORD', 'Specify password') do |password|
42
+ @options.password = password
43
+ end
44
+
45
+ opts.on('', '--timeout=TIMEOUT', 'Timeout in seconds (default: 5.0)') do |timeout|
46
+ @options.timeout = timeout.to_i
47
+ end
48
+
49
+ opts.on('', '--connect-timeout=TIMEOUT', 'Timeout for initial connect in seconds (default: same as timeout)') do |timeout|
50
+ @options.connect_timeout = timeout.to_i
51
+ end
52
+
53
+ opts.on('', '--replica', 'Whether to use readonly replica nodes in Redis Cluster or not') do
54
+ @options.replica = true
55
+ end
56
+
57
+ opts.on('', '--cluster=CLUSTER_URL', 'List of cluster nodes to contact, format: URL1,URL2,URL3...') do |cluster|
58
+ @options.cluster = cluster.split(',')
59
+ end
60
+
61
+ opts.on('-HSSH_HOST', '--ssh-host=SSH_HOST', 'Specify SSH host') do |ssh_host|
62
+ @options.ssh_host = ssh_host
63
+ end
64
+
65
+ opts.on('-OSSH_PORT', '--ssh-port=SSH_PORT', 'Specify SSH port') do |ssh_port|
66
+ @options.ssh_port = ssh_port.to_i
67
+ end
68
+
69
+ opts.on('-USSH_USER', '--ssh-user=SSH_USER', 'Specify SSH user') do |ssh_user|
70
+ @options.ssh_user = ssh_user
71
+ end
72
+
73
+ opts.on('-WSSH_PASSWORD', '--ssh-password=SSH_PASSWORD', 'Specify SSH password') do |ssh_password|
74
+ @options.ssh_password = ssh_password
75
+ end
76
+
77
+ opts.on('-LSSH_LOCAL_PORT', '--ssh-local-port=SSH_LOCAL_PORT', 'Specify local SSH proxy port') do |local_port|
78
+ @options.ssh_local_port = local_port.to_i
79
+ end
80
+
81
+ opts.on('-ECODE', '--eval=CODE', 'evaluate CODE') do |code|
82
+ @options.code = code
83
+ end
84
+
85
+ opts.on('-V', '--version', 'Prints version') do
86
+ puts "PRIZE #{Prize::VERSION}"
87
+ exit
88
+ end
89
+
90
+ opts.on('', '--help', 'Prints this help') do
91
+ puts opts
92
+ exit
93
+ end
94
+
95
+ end.parse!
96
+
97
+ @options.args = ARGV
53
98
  end
54
99
  end
55
100
  end
@@ -0,0 +1,5 @@
1
+ require 'prize/commands/info'
2
+ require 'prize/commands/reconnect'
3
+
4
+ module Prize::Commands
5
+ end
@@ -0,0 +1,48 @@
1
+ require 'rainbow'
2
+
3
+ module Prize::Commands
4
+ module Info
5
+ class << self
6
+ def db_info
7
+ <<~EOF
8
+
9
+ Redis Connection Information:
10
+
11
+ Active: #{color_boolean(Prize::App.redis_client.connected?)}
12
+ Host: #{Prize::App.options.host || '127.0.0.1'}
13
+ Port: #{Prize::App.options.port || 6379}
14
+ Password: #{(Prize::App.options.password || '').gsub(/./, '*')}
15
+ Database: #{Prize::App.options.db || 0}
16
+ EOF
17
+ end
18
+
19
+ def ssh_info
20
+ <<~EOF
21
+
22
+ SSH Connection Information:
23
+
24
+ Active: #{color_boolean(Prize::SSHProxy.active?)}
25
+ Host: #{Prize::App.options.ssh_host}
26
+ Port: #{Prize::App.options.ssh_port || ''}
27
+ Username: #{Prize::App.options.ssh_user}
28
+ Password: #{(Prize::App.options.ssh_password || '').gsub(/./, '*')}
29
+ Local Port: #{Prize::SSHProxy.local_ssh_proxy_port}
30
+ EOF
31
+ end
32
+
33
+ private
34
+ def color_boolean(bool)
35
+ if bool
36
+ Rainbow('TRUE').green
37
+ else
38
+ Rainbow('FALSE').red
39
+ end
40
+ end
41
+ end
42
+
43
+ Pry.commands.block_command 'inf' do
44
+ puts Info::db_info
45
+ puts Info::ssh_info if Prize::App.options.ssh_host.present?
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,23 @@
1
+ module Prize::Commands
2
+ module Reconnect
3
+ class << self
4
+ def reconnect
5
+ Prize::SSHProxy.reconnect if Prize::App.options.ssh_host.present?
6
+ Prize::App.redis_client.reconnect unless Prize::App.redis_client.connected?
7
+ end
8
+
9
+ def reconnect!
10
+ Prize::SSHProxy.reconnect! if Prize::App.options.ssh_host.present?
11
+ Prize::App.redis_client.reconnect
12
+ end
13
+ end
14
+
15
+ Pry.commands.block_command 'reconnect' do
16
+ Reconnect.reconnect
17
+ end
18
+
19
+ Pry.commands.block_command 'reconnect!' do
20
+ Reconnect.reconnect!
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,3 @@
1
+ require 'prize/ext/object'
2
+ require 'prize/ext/time'
3
+ require 'prize/ext/string'
@@ -0,0 +1,18 @@
1
+ class Object
2
+
3
+ def j
4
+ to_json
5
+ end
6
+
7
+ def jj
8
+ JSON.pretty_generate(JSON.parse(to_json))
9
+ end
10
+
11
+ def jp
12
+ puts j
13
+ end
14
+
15
+ def jjp
16
+ puts jj
17
+ end
18
+ end
@@ -0,0 +1,5 @@
1
+ class String
2
+ def p
3
+ puts self
4
+ end
5
+ end
@@ -0,0 +1,15 @@
1
+ require 'active_support/core_ext/time/conversions'
2
+ require 'active_support/core_ext/object/json'
3
+
4
+ class Time
5
+ DATE_FORMATS ||= {}
6
+ DATE_FORMATS[:default] = '%Y-%m-%d %H:%M:%S'
7
+
8
+ def inspect
9
+ to_s
10
+ end
11
+
12
+ def as_json(*args)
13
+ to_s
14
+ end
15
+ end
@@ -0,0 +1,59 @@
1
+ module Prize
2
+ class ID
3
+ @worker_id_bits = 5
4
+ @data_center_id_bits = 5
5
+ @max_worker_id = -1 ^ (-1 << @worker_id_bits)
6
+ @max_data_center_id = -1 ^ (-1 << @data_center_id_bits)
7
+
8
+ @sequence_bits = 12
9
+ @worker_id_shift = @sequence_bits
10
+ @data_center_id_shift = @sequence_bits + @worker_id_shift
11
+ @timestamp_left_shift = @sequence_bits + @worker_id_bits + @data_center_id_bits
12
+ @sequence_mask = -1 ^ (-1 << @sequence_bits)
13
+
14
+ @id_epoch = (Time.new(2018, 1, 1, 0, 0, 0).to_f * 1000).to_i
15
+ @worker_id = 0
16
+ @data_center_id = 0
17
+ @sequence = 0
18
+
19
+ @last_timestamp = -1
20
+
21
+ class << self
22
+ def long
23
+ ts = (Time.now.to_f * 1000).to_i
24
+ if ts < @last_timestamp
25
+ raise 'Clock moved backwards.'
26
+ end
27
+
28
+ if ts == @last_timestamp
29
+ @sequence = (@sequence + 1) & @sequence_mask
30
+ if (@sequence == 0)
31
+ ts = til_next_millis(@last_timestamp)
32
+ end
33
+ else
34
+ @sequence = 0
35
+ end
36
+ @last_timestamp = ts
37
+
38
+ ((ts - @id_epoch) << @timestamp_left_shift) | (@data_center_id << @data_center_id_shift) | (@worker_id << @worker_id_shift) | @sequence
39
+ end
40
+
41
+ def uuid
42
+ require 'securerandom'
43
+ SecureRandom.uuid.gsub('-', '')
44
+ end
45
+
46
+ private
47
+
48
+ def til_next_millis(last_timestamp)
49
+ ts = (Time.now.to_f * 1000).to_i
50
+ while ts <= last_timestamp
51
+ ts = (Time.now.to_f * 1000).to_i
52
+ end
53
+ ts
54
+ end
55
+ end
56
+ end
57
+ end
58
+
59
+ ::ID = Prize::ID
@@ -0,0 +1,31 @@
1
+ require 'pry'
2
+ require 'pry-byebug'
3
+ require 'prize/commands'
4
+ require 'rainbow'
5
+
6
+ module Prize
7
+ class Repl
8
+ def initialize
9
+ @redis = App.redis
10
+ Pry.config.prompt = Pry::Prompt.new("", "", prompt)
11
+ Pry.start(@redis)
12
+ end
13
+
14
+ def prompt
15
+ opts = @redis.instance_variable_get('@client').options
16
+ if App.options.ssh_host
17
+ host = "#{App.options.ssh_host}:#{App.options.host || '127.0.0.1'}:#{App.options.port || 6379}/#{opts[:db]}"
18
+ else
19
+ host = opts[:url] || opts[:path] || "#{opts[:host]}:#{opts[:port]}/#{opts[:db]}"
20
+ end
21
+ [proc do |obj, nest_level, _|
22
+ if obj == @redis && nest_level == 0
23
+ nest_level_prompt = ''
24
+ else
25
+ nest_level_prompt = "(#{obj}:#{nest_level})"
26
+ end
27
+ "%s#{Rainbow('@').green}%s#{nest_level_prompt} %s " % [Rainbow('PRIZE').red, Rainbow(host).yellow, Rainbow('❯').green]
28
+ end]
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,31 @@
1
+ require 'net/ssh/gateway'
2
+ require 'prize/ssh_proxy_patch'
3
+
4
+ module Prize
5
+ class SSHProxy
6
+ class << self
7
+
8
+ attr_accessor :config, :ssh_gateway, :local_ssh_proxy_port
9
+
10
+ def connect(config)
11
+ @config = config
12
+ @ssh_gateway = Net::SSH::Gateway.new(config[:host], config[:user], config.slice(:port, :password).symbolize_keys.merge(keepalive: true, keepalive_interval: 30, loop_wait: 1))
13
+ @local_ssh_proxy_port = @ssh_gateway.open(config[:forward_host], config[:forward_port], config[:local_port])
14
+ end
15
+
16
+ def reconnect
17
+ reconnect! unless @ssh_gateway.active?
18
+ end
19
+
20
+ def reconnect!
21
+ @ssh_gateway.shutdown!
22
+ @ssh_gateway = Net::SSH::Gateway.new(@config[:host], @config[:user], @config.slice(:port, :password).symbolize_keys)
23
+ @ssh_gateway.open(config[:forward_host], config[:forward_port], @local_ssh_proxy_port)
24
+ end
25
+
26
+ def active?
27
+ @ssh_gateway.active?
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,88 @@
1
+ require 'net/ssh/proxy/command'
2
+
3
+ module Net
4
+ module SSH
5
+ module Proxy
6
+ class Command
7
+
8
+ # Return a new socket connected to the given host and port via the
9
+ # proxy that was requested when the socket factory was instantiated.
10
+ def open(host, port, connection_options = nil)
11
+ command_line = @command_line_template.gsub(/%(.)/) {
12
+ case $1
13
+ when 'h'
14
+ host
15
+ when 'p'
16
+ port.to_s
17
+ when 'r'
18
+ remote_user = connection_options && connection_options[:remote_user]
19
+ if remote_user
20
+ remote_user
21
+ else
22
+ raise ArgumentError, "remote user name not available"
23
+ end
24
+ when '%'
25
+ '%'
26
+ else
27
+ raise ArgumentError, "unknown key: #{$1}"
28
+ end
29
+ }
30
+ command_line = '%s %s' % [PrizeSetsidWrrapper, command_line]
31
+ begin
32
+ io = IO.popen(command_line, "r+")
33
+ begin
34
+ if result = IO.select([io], nil, [io], @timeout)
35
+ if result.last.any? || io.eof?
36
+ raise "command failed"
37
+ end
38
+ else
39
+ raise "command timed out"
40
+ end
41
+ rescue StandardError
42
+ close_on_error(io)
43
+ raise
44
+ end
45
+ rescue StandardError => e
46
+ raise ConnectError, "#{e}: #{command_line}"
47
+ end
48
+ @command_line = command_line
49
+ if Gem.win_platform?
50
+ # read_nonblock and write_nonblock are not available on Windows
51
+ # pipe. Use sysread and syswrite as a replacement works.
52
+ def io.send(data, flag)
53
+ syswrite(data)
54
+ end
55
+
56
+ def io.recv(size)
57
+ sysread(size)
58
+ end
59
+ else
60
+ def io.send(data, flag)
61
+ begin
62
+ result = write_nonblock(data)
63
+ rescue IO::WaitWritable, Errno::EINTR
64
+ IO.select(nil, [self])
65
+ retry
66
+ end
67
+ result
68
+ end
69
+
70
+ def io.recv(size)
71
+ begin
72
+ result = read_nonblock(size)
73
+ rescue IO::WaitReadable, Errno::EINTR
74
+ timeout_in_seconds = 20
75
+ if IO.select([self], nil, [self], timeout_in_seconds) == nil
76
+ raise "Unexpected spurious read wakeup"
77
+ end
78
+ retry
79
+ end
80
+ result
81
+ end
82
+ end
83
+ io
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -1,3 +1,3 @@
1
1
  module Prize
2
- VERSION = "0.1.1"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -1,7 +1,4 @@
1
-
2
- lib = File.expand_path("../lib", __FILE__)
3
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require "prize/version"
1
+ require_relative 'lib/prize/version'
5
2
 
6
3
  Gem::Specification.new do |spec|
7
4
  spec.name = "prize"
@@ -11,9 +8,9 @@ Gem::Specification.new do |spec|
11
8
 
12
9
  spec.summary = %{Simple Redis CLI client with pry loaded}
13
10
  spec.description = %{Simple Redis CLI client with pry loaded}
14
- spec.homepage = "https://github.com/lululau/ktct"
11
+ spec.homepage = "https://github.com/lululau/prize"
15
12
  spec.license = "MIT"
16
-
13
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
17
14
 
18
15
  # Specify which files should be added to the gem when it is released.
19
16
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
@@ -24,13 +21,13 @@ Gem::Specification.new do |spec|
24
21
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
25
22
  spec.require_paths = ["lib"]
26
23
 
27
- spec.add_dependency 'activesupport'
28
- spec.add_dependency 'redis', '>= 4.0.0'
29
- spec.add_dependency 'hiredis', '>= 0.6.0'
24
+ spec.add_dependency 'activesupport', '~> 6.0.3'
25
+ spec.add_dependency 'net-ssh-gateway', '~> 2.0.0'
26
+ spec.add_dependency 'pry', '~> 0.13.1'
27
+ spec.add_dependency 'pry-byebug', '~> 3.9.0'
28
+ spec.add_dependency 'pry-doc', '~> 1.1.0'
29
+ spec.add_dependency 'rainbow', '~> 3.0.0'
30
+ spec.add_dependency 'redis', '~> 4.0.0'
31
+ spec.add_dependency 'hiredis', '~> 0.6.0'
30
32
  spec.add_dependency 'thor', '~> 0.20.0'
31
- spec.add_dependency 'pry', '>= 0.12.0'
32
-
33
- spec.add_development_dependency "bundler", "~> 1.17"
34
- spec.add_development_dependency "rake", "~> 10.0"
35
- spec.add_development_dependency "rspec", "~> 3.0"
36
33
  end
metadata CHANGED
@@ -1,138 +1,151 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: prize
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Liu Xiang
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-08-13 00:00:00.000000000 Z
11
+ date: 2020-08-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: 6.0.3
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0'
26
+ version: 6.0.3
27
27
  - !ruby/object:Gem::Dependency
28
- name: redis
28
+ name: net-ssh-gateway
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 4.0.0
33
+ version: 2.0.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ">="
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 4.0.0
40
+ version: 2.0.0
41
41
  - !ruby/object:Gem::Dependency
42
- name: hiredis
42
+ name: pry
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ">="
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: 0.6.0
47
+ version: 0.13.1
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ">="
52
+ - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: 0.6.0
54
+ version: 0.13.1
55
55
  - !ruby/object:Gem::Dependency
56
- name: thor
56
+ name: pry-byebug
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 0.20.0
61
+ version: 3.9.0
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: 0.20.0
68
+ version: 3.9.0
69
69
  - !ruby/object:Gem::Dependency
70
- name: pry
70
+ name: pry-doc
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - ">="
73
+ - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: 0.12.0
75
+ version: 1.1.0
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - ">="
80
+ - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: 0.12.0
82
+ version: 1.1.0
83
83
  - !ruby/object:Gem::Dependency
84
- name: bundler
84
+ name: rainbow
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '1.17'
90
- type: :development
89
+ version: 3.0.0
90
+ type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '1.17'
96
+ version: 3.0.0
97
97
  - !ruby/object:Gem::Dependency
98
- name: rake
98
+ name: redis
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: '10.0'
104
- type: :development
103
+ version: 4.0.0
104
+ type: :runtime
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: '10.0'
110
+ version: 4.0.0
111
111
  - !ruby/object:Gem::Dependency
112
- name: rspec
112
+ name: hiredis
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
115
  - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: '3.0'
118
- type: :development
117
+ version: 0.6.0
118
+ type: :runtime
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
- version: '3.0'
124
+ version: 0.6.0
125
+ - !ruby/object:Gem::Dependency
126
+ name: thor
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: 0.20.0
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: 0.20.0
125
139
  description: Simple Redis CLI client with pry loaded
126
140
  email:
127
141
  - liuxiang921@gmail.com
128
142
  executables:
129
143
  - prize
144
+ - prize_setsid_wrapper
130
145
  extensions: []
131
146
  extra_rdoc_files: []
132
147
  files:
133
148
  - ".gitignore"
134
- - ".rspec"
135
- - ".travis.yml"
136
149
  - CODE_OF_CONDUCT.md
137
150
  - Gemfile
138
151
  - Gemfile.lock
@@ -142,15 +155,28 @@ files:
142
155
  - bin/console
143
156
  - bin/setup
144
157
  - exe/prize
158
+ - exe/prize_setsid_wrapper
145
159
  - lib/prize.rb
160
+ - lib/prize/app.rb
146
161
  - lib/prize/cli.rb
162
+ - lib/prize/commands.rb
163
+ - lib/prize/commands/info.rb
164
+ - lib/prize/commands/reconnect.rb
165
+ - lib/prize/ext.rb
166
+ - lib/prize/ext/object.rb
167
+ - lib/prize/ext/string.rb
168
+ - lib/prize/ext/time.rb
169
+ - lib/prize/id.rb
170
+ - lib/prize/repl.rb
171
+ - lib/prize/ssh_proxy.rb
172
+ - lib/prize/ssh_proxy_patch.rb
147
173
  - lib/prize/version.rb
148
174
  - prize.gemspec
149
- homepage: https://github.com/lululau/ktct
175
+ homepage: https://github.com/lululau/prize
150
176
  licenses:
151
177
  - MIT
152
178
  metadata: {}
153
- post_install_message:
179
+ post_install_message:
154
180
  rdoc_options: []
155
181
  require_paths:
156
182
  - lib
@@ -158,15 +184,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
158
184
  requirements:
159
185
  - - ">="
160
186
  - !ruby/object:Gem::Version
161
- version: '0'
187
+ version: 2.3.0
162
188
  required_rubygems_version: !ruby/object:Gem::Requirement
163
189
  requirements:
164
190
  - - ">="
165
191
  - !ruby/object:Gem::Version
166
192
  version: '0'
167
193
  requirements: []
168
- rubygems_version: 3.0.3
169
- signing_key:
194
+ rubygems_version: 3.1.2
195
+ signing_key:
170
196
  specification_version: 4
171
197
  summary: Simple Redis CLI client with pry loaded
172
198
  test_files: []
data/.rspec DELETED
@@ -1,3 +0,0 @@
1
- --format documentation
2
- --color
3
- --require spec_helper
@@ -1,7 +0,0 @@
1
- ---
2
- sudo: false
3
- language: ruby
4
- cache: bundler
5
- rvm:
6
- - 2.6.2
7
- before_install: gem install bundler -v 1.17.2