redispot 0.1.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 12690e01651c34511666f3c387adb439ab9a94b4
4
+ data.tar.gz: 95aefdff7ef71d1a1aa328551682713c39866f89
5
+ SHA512:
6
+ metadata.gz: bc071d7b16ee721be78b43524041abeb1b3a39e8a5869d0d36abfc3553bcba00a99f8ec164b457a4fbda11fe3fe6e5caa45434590c3ade05847adf61605f931a
7
+ data.tar.gz: 6a3c599ef734e319b635b5d1dd772c5e1b2e3bc486bf7f825036d8d7f820169ec3cb8d49e8aa711888fb574738e03ba9c570e04d516d3440e806237c4e8b67a0
data/.gitignore ADDED
@@ -0,0 +1,7 @@
1
+ /.bundle/
2
+ /.yardoc/
3
+ /Gemfile.lock
4
+ /doc/
5
+ /pkg/
6
+ /vendor/
7
+ *.sw[a-z]
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.6
4
+ - 2.2.2
5
+ before_install: gem install bundler -v 1.10.5
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'http://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in test-redis_server.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 hatyuki
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,104 @@
1
+ # Redispot
2
+ [![Gem Version](https://badge.fury.io/rb/redispot.svg)](http://badge.fury.io/rb/redispot)
3
+ [![Build Status](https://travis-ci.org/hatyuki/redispot-rb.svg?branch=master)](https://travis-ci.org/hatyuki/redispot-rb)
4
+ [![Code Climate](https://codeclimate.com/github/hatyuki/redispot-rb/badges/gpa.svg)](https://codeclimate.com/github/hatyuki/redispot-rb)
5
+
6
+ Launching the redis-server instance which is available only within a block.
7
+ It is useful when you want to test your code.
8
+ It is a Ruby clone of [Test::RedisServer](https://github.com/typester/Test-RedisServer).
9
+
10
+
11
+ ## Synopsis
12
+ ```ruby
13
+ require 'redis'
14
+ require 'redispot'
15
+
16
+ Redispot::Server.new do |connect_info|
17
+ redis = Redis.new(connect_info)
18
+ redis.ping # => "PONG"
19
+ end
20
+ ```
21
+
22
+
23
+ ## Methods
24
+ ### Redispot::Server.new(options)
25
+ Create a new instance, and start redis-server if block given.
26
+
27
+ ```ruby
28
+ redis_server = Redispot::Server.new(options)
29
+
30
+ # or
31
+
32
+ Redispot::Server.new(options) do |connect_info|
33
+ redis = Redis.new(connect_info)
34
+ # ...
35
+ end
36
+ ```
37
+
38
+ Available options are:
39
+
40
+ - [Hash] config
41
+
42
+ This is a `redis.conf` key value pair. You can use any key-value pair(s) that redis-server supports.
43
+
44
+ If you want to use this redis.conf:
45
+
46
+ ```
47
+ port 9999
48
+ databases 16
49
+ save 900 1
50
+ ```
51
+
52
+ Your conf parameter will be:
53
+
54
+ ```ruby
55
+ Redispot::Server.new(config: {
56
+ port: 9999,
57
+ databases: 16,
58
+ save: '900 1',
59
+ })
60
+ ```
61
+
62
+ - [Fixnum] timeout (Default: 3)
63
+
64
+ Timeout seconds for detecting if redis-server is awake or not.
65
+
66
+ - [String] tmpdir
67
+
68
+ Temporal directory, where redis config will be stored.
69
+
70
+
71
+ ### Redispot::Server#start
72
+ Start redis-server instance manually.
73
+
74
+ ```ruby
75
+ server = Redispot::Server.new
76
+ server.start do |connect_info|
77
+ redis = Redis.new(connect_info)
78
+ redis.ping # => "PONG"
79
+ end
80
+ ```
81
+
82
+
83
+ ## Installation
84
+ Add this line to your application's Gemfile:
85
+
86
+ ```ruby
87
+ gem 'redispot'
88
+ ```
89
+
90
+ And then execute:
91
+
92
+ $ bundle
93
+
94
+ Or install it yourself as:
95
+
96
+ $ gem install redispot
97
+
98
+
99
+ ## Contributing
100
+ Bug reports and pull requests are welcome on GitHub at https://github.com/hatyuki/redispot-rb.
101
+
102
+
103
+ ## License
104
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << 'test'
6
+ t.libs << 'lib'
7
+ t.test_files = FileList['test/**/*_test.rb']
8
+ end
9
+
10
+ task :default => :test
data/bin/console ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+ require 'bundler/setup'
3
+ require 'redispot'
4
+
5
+ # You can add fixtures and/or initialization code here to make experimenting
6
+ # with your gem easier. You can also use a different console, if you like.
7
+
8
+ require 'pry'
9
+ Pry.start
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,170 @@
1
+ require 'fileutils'
2
+ require 'timeout'
3
+ require 'tmpdir'
4
+
5
+ module Redispot
6
+ class Server
7
+
8
+ # Destractor
9
+ #
10
+ # @private
11
+ def self.destroy (pid, owner_pid, timeout)
12
+ Proc.new do
13
+ return if pid.nil? || owner_pid != Process.pid
14
+
15
+ signals = [:TERM, :INT, :KILL]
16
+
17
+ begin
18
+ Process.kill(signals.shift, pid)
19
+ Timeout.timeout(timeout) { Process.waitpid(pid) }
20
+ rescue Timeout::Error
21
+ retry
22
+ end
23
+ end
24
+ end
25
+
26
+ # Create a new instance, and start redis-server if block given.
27
+ #
28
+ # @example
29
+ # Redispot::Server.new do |connect_info|
30
+ # redis = Redis.new(connect_info)
31
+ # assert_equal('PONG', redis.ping)
32
+ # end
33
+ #
34
+ # @param config [Hash] This is a `redis.conf` key value pair. You can use any key-value pair(s) that redis-server supports.
35
+ # @param timeout [Fixnum] Timeout seconds for detecting if redis-server is awake or not.
36
+ # @param tmpdir [String] Temporal directory, where redis config will be stored.
37
+ # @yield [connect_info] Connection info for client library to connect this redis-server instance.
38
+ # @yieldparam connect_info [String] This parameter is designed to pass directly to Redis module.
39
+ def initialize (config: { }, timeout: 3, tmpdir: nil, &block)
40
+ @executable = 'redis-server'
41
+ @owner_pid = Process.pid
42
+ @pid = nil
43
+ @workdir = nil
44
+ @config = config
45
+ @timeout = timeout
46
+ @tmpdir = tmpdir.nil? ? nil : File.expand_path(tmpdir)
47
+
48
+ if @config[:loglevel].to_s == 'warning'
49
+ $stderr.puts 'Redispot::Server does not support "loglevel warning", using "notice" instead.'
50
+ @config[:loglevel] = 'notice'
51
+ end
52
+
53
+ start(&block) if block
54
+ end
55
+
56
+ # Start redis-server instance within a given block.
57
+ #
58
+ # @example
59
+ # redis_server = Redispot::Server.new
60
+ # redis_server.start do |connect_info|
61
+ # redis = Redis.new(connect_info)
62
+ # assert_equal('PONG', redis.ping)
63
+ # end
64
+ #
65
+ # @yield [connect_info] Connection info for client library to connect this redis-server instance.
66
+ # @yieldparam connect_info [Hash] This parameter is designed to pass directly to Redis module.
67
+ def start
68
+ Dir.mktmpdir(nil, @tmpdir) do |workdir|
69
+ @workdir = workdir
70
+ yield start_redis_server
71
+ stop
72
+ end
73
+ end
74
+
75
+ private
76
+ def start_redis_server
77
+ @pid = fork_process
78
+
79
+ Timeout.timeout(@timeout) do
80
+ loop do
81
+ if !Process.waitpid(@pid, Process::WNOHANG).nil?
82
+ @pid = nil
83
+ raise RuntimeError, "failed to launch redis-server\n#{File.read(logfile)}"
84
+ else
85
+ if File.read(logfile) =~ /The server is now ready to accept connections/
86
+ ObjectSpace.define_finalizer(self, proc { stop })
87
+ return connect_info
88
+ end
89
+ end
90
+
91
+ sleep 0.1
92
+ end
93
+ end
94
+ rescue Timeout::Error
95
+ stop if @pid
96
+ raise RuntimeError, "failed to launch redis-server\n#{File.read(logfile)}"
97
+ end
98
+
99
+ def fork_process
100
+ File.open(logfile, 'w') do |fh|
101
+ Process.fork do
102
+ begin
103
+ exec @executable, config_file, out: fh, err: fh
104
+ rescue => error
105
+ $stderr.puts "exec failed: #{error}"
106
+ exit error.errno
107
+ end
108
+ end
109
+ end
110
+ end
111
+
112
+ def connect_info
113
+ return unless @pid
114
+
115
+ host = config[:bind].nil? ? '0.0.0.0' : config[:bind]
116
+ port = config[:port]
117
+
118
+ if port.is_a?(Fixnum) && port > 0
119
+ { url: "redis://#{host}:#{port}/" }
120
+ else
121
+ { path: config[:unixsocket] }
122
+ end
123
+ end
124
+
125
+ def stop
126
+ return if @pid.nil? || @owner_pid != Process.pid
127
+
128
+ signals = [:TERM, :INT, :KILL]
129
+
130
+ begin
131
+ Process.kill(signals.shift, @pid)
132
+ Timeout.timeout(@timeout) { Process.waitpid(@pid) }
133
+ rescue Timeout::Error
134
+ retry
135
+ end
136
+
137
+ @pid = nil
138
+ @workdir = nil
139
+
140
+ ObjectSpace.undefine_finalizer(self)
141
+ end
142
+
143
+ def logfile
144
+ "#{@workdir}/redis.log"
145
+ end
146
+
147
+ def config_file
148
+ config_string = config.inject('') do |memo, (key, value)|
149
+ next if value.to_s.empty?
150
+ memo += "#{key} #{value}\n"
151
+ end
152
+
153
+ "#{@workdir}/redis.conf".tap do |config_path|
154
+ File.write(config_path, config_string)
155
+ end
156
+ end
157
+
158
+ def config
159
+ default_config.merge(@config)
160
+ end
161
+
162
+ def default_config
163
+ {
164
+ unixsocket: "#{@workdir}/redis.sock",
165
+ dir: "#{@workdir}/"
166
+ }
167
+ end
168
+
169
+ end
170
+ end
@@ -0,0 +1,3 @@
1
+ module Redispot
2
+ VERSION = '0.1.1'
3
+ end
data/lib/redispot.rb ADDED
@@ -0,0 +1,2 @@
1
+ require 'redispot/server'
2
+ require 'redispot/version.rb'
data/redispot.gemspec ADDED
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'redispot/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'redispot'
8
+ spec.version = Redispot::VERSION
9
+ spec.authors = ['hatyuki']
10
+ spec.email = ['hatyuki29@gmail.com']
11
+ spec.summary = 'Launching the redis-server instance which is available only within a block.'
12
+ spec.description = 'Launching the redis-server instance which is available only within a block.'
13
+ spec.homepage = 'https://github.com/hatyuki/redispot-rb'
14
+ spec.license = 'MIT'
15
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^test/}) }
16
+ spec.bindir = 'exe'
17
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
18
+ spec.require_paths = ['lib']
19
+
20
+ spec.required_ruby_version = '>= 2.0.0'
21
+
22
+ spec.add_development_dependency 'bundler', '~> 1.10'
23
+ spec.add_development_dependency 'rake', '~> 10.0'
24
+ spec.add_development_dependency 'pry'
25
+ spec.add_development_dependency 'redis'
26
+ spec.add_development_dependency 'test-unit'
27
+ spec.add_development_dependency 'yard'
28
+ end
metadata ADDED
@@ -0,0 +1,142 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: redispot
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - hatyuki
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2015-07-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.10'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.10'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pry
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: redis
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: test-unit
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: yard
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: Launching the redis-server instance which is available only within a
98
+ block.
99
+ email:
100
+ - hatyuki29@gmail.com
101
+ executables: []
102
+ extensions: []
103
+ extra_rdoc_files: []
104
+ files:
105
+ - ".gitignore"
106
+ - ".travis.yml"
107
+ - Gemfile
108
+ - LICENSE.txt
109
+ - README.md
110
+ - Rakefile
111
+ - bin/console
112
+ - bin/setup
113
+ - lib/redispot.rb
114
+ - lib/redispot/server.rb
115
+ - lib/redispot/version.rb
116
+ - redispot.gemspec
117
+ homepage: https://github.com/hatyuki/redispot-rb
118
+ licenses:
119
+ - MIT
120
+ metadata: {}
121
+ post_install_message:
122
+ rdoc_options: []
123
+ require_paths:
124
+ - lib
125
+ required_ruby_version: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - ">="
128
+ - !ruby/object:Gem::Version
129
+ version: 2.0.0
130
+ required_rubygems_version: !ruby/object:Gem::Requirement
131
+ requirements:
132
+ - - ">="
133
+ - !ruby/object:Gem::Version
134
+ version: '0'
135
+ requirements: []
136
+ rubyforge_project:
137
+ rubygems_version: 2.4.8
138
+ signing_key:
139
+ specification_version: 4
140
+ summary: Launching the redis-server instance which is available only within a block.
141
+ test_files: []
142
+ has_rdoc: