rediska 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/.gitignore +19 -0
- data/.rspec +3 -0
- data/.travis.yml +4 -0
- data/Gemfile +7 -0
- data/Gemfile.lock +70 -0
- data/LICENSE +20 -0
- data/README.md +95 -0
- data/Rakefile +7 -0
- data/lib/rediska/configuration.rb +11 -0
- data/lib/rediska/connection.rb +67 -0
- data/lib/rediska/databases/expiring.rb +87 -0
- data/lib/rediska/databases/memory.rb +21 -0
- data/lib/rediska/databases/pstore.rb +72 -0
- data/lib/rediska/driver.rb +910 -0
- data/lib/rediska/sorted_set_argument_handler.rb +54 -0
- data/lib/rediska/sorted_set_store.rb +80 -0
- data/lib/rediska/version.rb +3 -0
- data/lib/rediska/zset.rb +26 -0
- data/lib/rediska.rb +18 -0
- data/rediska.gemspec +26 -0
- data/spec/redis_spec.rb +64 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/support/compatibility.rb +7 -0
- data/spec/support/connection.rb +65 -0
- data/spec/support/hashes.rb +189 -0
- data/spec/support/keys.rb +261 -0
- data/spec/support/lists.rb +196 -0
- data/spec/support/server.rb +93 -0
- data/spec/support/sets.rb +175 -0
- data/spec/support/sorted_sets.rb +447 -0
- data/spec/support/strings.rb +240 -0
- data/spec/support/transactions.rb +11 -0
- data/spec/support/upcase_method_names.rb +9 -0
- metadata +174 -0
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
rediska (0.0.2)
|
5
|
+
redis (~> 3.0.0)
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: http://rubygems.org/
|
9
|
+
specs:
|
10
|
+
coderay (1.0.9)
|
11
|
+
columnize (0.3.6)
|
12
|
+
coveralls (0.7.0)
|
13
|
+
multi_json (~> 1.3)
|
14
|
+
rest-client
|
15
|
+
simplecov (>= 0.7)
|
16
|
+
term-ansicolor
|
17
|
+
thor
|
18
|
+
debugger (1.6.2)
|
19
|
+
columnize (>= 0.3.1)
|
20
|
+
debugger-linecache (~> 1.2.0)
|
21
|
+
debugger-ruby_core_source (~> 1.2.3)
|
22
|
+
debugger-linecache (1.2.0)
|
23
|
+
debugger-ruby_core_source (1.2.3)
|
24
|
+
diff-lcs (1.2.4)
|
25
|
+
json (1.8.1)
|
26
|
+
method_source (0.8.2)
|
27
|
+
mime-types (1.25)
|
28
|
+
multi_json (1.8.2)
|
29
|
+
pry (0.9.12.2)
|
30
|
+
coderay (~> 1.0.5)
|
31
|
+
method_source (~> 0.8)
|
32
|
+
slop (~> 3.4)
|
33
|
+
pry-debugger (0.2.2)
|
34
|
+
debugger (~> 1.3)
|
35
|
+
pry (~> 0.9.10)
|
36
|
+
rake (10.1.0)
|
37
|
+
rdoc (4.0.1)
|
38
|
+
json (~> 1.4)
|
39
|
+
redis (3.0.5)
|
40
|
+
rest-client (1.6.7)
|
41
|
+
mime-types (>= 1.16)
|
42
|
+
rspec (2.14.1)
|
43
|
+
rspec-core (~> 2.14.0)
|
44
|
+
rspec-expectations (~> 2.14.0)
|
45
|
+
rspec-mocks (~> 2.14.0)
|
46
|
+
rspec-core (2.14.6)
|
47
|
+
rspec-expectations (2.14.3)
|
48
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
49
|
+
rspec-mocks (2.14.4)
|
50
|
+
simplecov (0.7.1)
|
51
|
+
multi_json (~> 1.0)
|
52
|
+
simplecov-html (~> 0.7.1)
|
53
|
+
simplecov-html (0.7.1)
|
54
|
+
slop (3.4.6)
|
55
|
+
term-ansicolor (1.2.2)
|
56
|
+
tins (~> 0.8)
|
57
|
+
thor (0.18.1)
|
58
|
+
tins (0.11.0)
|
59
|
+
|
60
|
+
PLATFORMS
|
61
|
+
ruby
|
62
|
+
|
63
|
+
DEPENDENCIES
|
64
|
+
coveralls
|
65
|
+
pry
|
66
|
+
pry-debugger
|
67
|
+
rake
|
68
|
+
rdoc
|
69
|
+
rediska!
|
70
|
+
rspec (~> 2.14)
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2013 Leonid Beder
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
7
|
+
the Software without restriction, including without limitation the rights to
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
10
|
+
subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
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, FITNESS
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
# Rediska
|
2
|
+
|
3
|
+
[](http://badge.fury.io/rb/rediska)
|
4
|
+
[](https://travis-ci.org/lbeder/rediska)
|
5
|
+
[](https://gemnasium.com/lbeder/rediska)
|
6
|
+
[](https://coveralls.io/r/lbeder/rediska)
|
7
|
+
|
8
|
+
This is a light-weight implementation of a redis simulator, which is useful for local development and testing or for minimal environments (where a real redis server might not be available or even desired, while every worker matters).
|
9
|
+
|
10
|
+
Currently, rediska is currently only compliant with redis 3 and supports the following database strategies:
|
11
|
+
|
12
|
+
* Memory (default): the data is being stored entirely in the memory and is not persistent nor shared between different processed.
|
13
|
+
* Filesystem: the data is being backed by the filesystem and even though slower than the in-memory implementation, it does provides persistency (to some extent, as the data is being stored in a temporary folder) and can be accessed across the different processes.
|
14
|
+
|
15
|
+
## Setup
|
16
|
+
|
17
|
+
If you are using bundler add rediska to your Gemfile:
|
18
|
+
|
19
|
+
``` ruby
|
20
|
+
gem 'rediska'
|
21
|
+
```
|
22
|
+
|
23
|
+
Then run:
|
24
|
+
|
25
|
+
```bash
|
26
|
+
$ bundle install
|
27
|
+
```
|
28
|
+
|
29
|
+
Otherwise install the gem:
|
30
|
+
|
31
|
+
```bash
|
32
|
+
$ gem install rediska
|
33
|
+
```
|
34
|
+
|
35
|
+
## Usage
|
36
|
+
The gem will automatically add its fake driver to Redis::Connection.drivers, so not extra configuration is required, other than conditionally bundling the gem (for example, in Rails' "test", "development", "continuos_integration" groups, per-your requirements.
|
37
|
+
|
38
|
+
## Configuration
|
39
|
+
|
40
|
+
### Database type/strategy
|
41
|
+
Rediska supports the following database strategies:
|
42
|
+
|
43
|
+
* Memory (:memory): the data is being stored entirely in the memory and is not persistent nor shared between different processed.
|
44
|
+
* Filesystem (:filesystem): the data is being backed by the filesystem and even though slower than the in-memory implementation, it does provides persistency (to some extent, as the data is being stored in a temporary folder) and can be accessed across the different processes.
|
45
|
+
|
46
|
+
By default, rediska uses the in-memory strategy.
|
47
|
+
|
48
|
+
To override this behavior you can config the ```database``` option like so:
|
49
|
+
|
50
|
+
```ruby
|
51
|
+
Rediska.configure do |config|
|
52
|
+
config.database = :filesystem
|
53
|
+
end
|
54
|
+
```
|
55
|
+
|
56
|
+
### Adding namespace
|
57
|
+
|
58
|
+
If you choose to use the filesystem backed database, you can append an additional namespace in order to prevent conflicts like so:
|
59
|
+
|
60
|
+
```ruby
|
61
|
+
Rediska.configure do |config|
|
62
|
+
config.namespace = 'test'
|
63
|
+
end
|
64
|
+
```
|
65
|
+
|
66
|
+
## Credits and Contributors
|
67
|
+
|
68
|
+
This gem was inspired (and originally forked from) by the [fakeredis](https://github.com/guilleiguaran/fakeredis) gem.
|
69
|
+
|
70
|
+
## License
|
71
|
+
|
72
|
+
The MIT License (MIT)
|
73
|
+
|
74
|
+
Copyright (c) 2013
|
75
|
+
|
76
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
77
|
+
this software and associated documentation files (the "Software"), to deal in
|
78
|
+
the Software without restriction, including without limitation the rights to
|
79
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
80
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
81
|
+
subject to the following conditions:
|
82
|
+
|
83
|
+
The above copyright notice and this permission notice shall be included in all
|
84
|
+
copies or substantial portions of the Software.
|
85
|
+
|
86
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
87
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
88
|
+
FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
89
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
90
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
91
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
92
|
+
|
93
|
+
<div align="center">
|
94
|
+
<img alt='rediska' src="http://farm6.staticflickr.com/5189/5640624758_b6717935bf.jpg" />
|
95
|
+
</div>
|
data/Rakefile
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'rediska/databases/memory'
|
2
|
+
require 'rediska/databases/pstore'
|
3
|
+
require 'rediska/sorted_set_argument_handler'
|
4
|
+
require 'rediska/sorted_set_store'
|
5
|
+
require 'rediska/zset'
|
6
|
+
require 'rediska/driver'
|
7
|
+
|
8
|
+
module Rediska
|
9
|
+
class Connection
|
10
|
+
include Driver
|
11
|
+
|
12
|
+
class << self
|
13
|
+
def databases
|
14
|
+
@databases ||= Hash.new {|h,k| h[k] = [] }
|
15
|
+
end
|
16
|
+
|
17
|
+
def reset
|
18
|
+
if @databases
|
19
|
+
@databases.values do |db|
|
20
|
+
db.class.reset
|
21
|
+
db.each(&:clear)
|
22
|
+
end
|
23
|
+
|
24
|
+
@databases = nil
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def connect(options = {})
|
29
|
+
new(options)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def initialize(options = {})
|
34
|
+
@options = options
|
35
|
+
@database_id = 0
|
36
|
+
end
|
37
|
+
|
38
|
+
def database_instance_key
|
39
|
+
@database_instance_key ||= [@options[:host], @options[:port], Rediska.configuration.namespace].
|
40
|
+
compact.join(':')
|
41
|
+
end
|
42
|
+
|
43
|
+
def databases
|
44
|
+
self.class.databases[database_instance_key]
|
45
|
+
end
|
46
|
+
|
47
|
+
def find_database(id = database_id)
|
48
|
+
databases[id] ||= db_class.new(database_instance_key, id)
|
49
|
+
end
|
50
|
+
|
51
|
+
def data
|
52
|
+
find_database
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
def db_class
|
57
|
+
case Rediska.configuration.database
|
58
|
+
when :memory
|
59
|
+
Rediska::Databases::Memory
|
60
|
+
when :filesystem
|
61
|
+
Rediska::Databases::PStore
|
62
|
+
else
|
63
|
+
raise ArgumentError, "invalid database type: #{Rediska.configuration.database}"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module Rediska
|
2
|
+
module Databases
|
3
|
+
module Expiring
|
4
|
+
def self.included(base)
|
5
|
+
base.send(:include, InstanceMethods)
|
6
|
+
base.extend ClassMethods
|
7
|
+
|
8
|
+
attr_reader :expires
|
9
|
+
end
|
10
|
+
|
11
|
+
module InstanceMethods
|
12
|
+
def initialize
|
13
|
+
super
|
14
|
+
|
15
|
+
@expires = {}
|
16
|
+
end
|
17
|
+
|
18
|
+
def [](key)
|
19
|
+
key = normalize(key)
|
20
|
+
delete(key) if expired?(key)
|
21
|
+
|
22
|
+
super
|
23
|
+
end
|
24
|
+
|
25
|
+
def []=(key, val)
|
26
|
+
key = normalize(key)
|
27
|
+
expire(key)
|
28
|
+
|
29
|
+
super
|
30
|
+
end
|
31
|
+
|
32
|
+
def delete(key)
|
33
|
+
key = normalize(key)
|
34
|
+
expire(key)
|
35
|
+
|
36
|
+
super
|
37
|
+
end
|
38
|
+
|
39
|
+
def expire(key)
|
40
|
+
key = normalize(key)
|
41
|
+
expires.delete(key)
|
42
|
+
end
|
43
|
+
|
44
|
+
def expired?(key)
|
45
|
+
key = normalize(key)
|
46
|
+
expires.include?(key) && expires[key] < Time.now
|
47
|
+
end
|
48
|
+
|
49
|
+
def key?(key)
|
50
|
+
key = normalize(key)
|
51
|
+
delete(key) if expired?(key)
|
52
|
+
|
53
|
+
super
|
54
|
+
end
|
55
|
+
|
56
|
+
def values_at(*keys)
|
57
|
+
keys.each do |key|
|
58
|
+
key = normalize(key)
|
59
|
+
delete(key) if expired?(key)
|
60
|
+
end
|
61
|
+
|
62
|
+
super
|
63
|
+
end
|
64
|
+
|
65
|
+
def keys
|
66
|
+
super.select do |key|
|
67
|
+
key = normalize(key)
|
68
|
+
|
69
|
+
if expired?(key)
|
70
|
+
delete(key)
|
71
|
+
false
|
72
|
+
else
|
73
|
+
true
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def normalize(key)
|
79
|
+
key.to_s
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
module ClassMethods
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'rediska/databases/expiring'
|
2
|
+
|
3
|
+
module Rediska
|
4
|
+
module Databases
|
5
|
+
class Memory < Hash
|
6
|
+
include Expiring
|
7
|
+
|
8
|
+
def initialize(instance_key, id)
|
9
|
+
super()
|
10
|
+
end
|
11
|
+
|
12
|
+
class << self
|
13
|
+
def flushdb(instance_key, id)
|
14
|
+
end
|
15
|
+
|
16
|
+
def flushall(instance_key)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'pstore'
|
2
|
+
require 'tmpdir'
|
3
|
+
|
4
|
+
require 'rediska/databases/expiring'
|
5
|
+
|
6
|
+
module Rediska
|
7
|
+
module Utilities
|
8
|
+
class SyncedPStore < ::PStore
|
9
|
+
def initialize(file)
|
10
|
+
super(file, false)
|
11
|
+
end
|
12
|
+
|
13
|
+
def transaction(read_only = false, &block)
|
14
|
+
@flock ||= path + '.lock'
|
15
|
+
|
16
|
+
File.open(@flock, File::RDWR | File::CREAT) do
|
17
|
+
super
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
module Databases
|
24
|
+
class PStore
|
25
|
+
include Expiring
|
26
|
+
|
27
|
+
def initialize(instance_key, id)
|
28
|
+
@id = id
|
29
|
+
|
30
|
+
@store = self.class.pstore(instance_key)
|
31
|
+
@store.transaction do
|
32
|
+
@store[db_name] ||= {}
|
33
|
+
@db = @store[db_name]
|
34
|
+
end
|
35
|
+
|
36
|
+
super()
|
37
|
+
end
|
38
|
+
|
39
|
+
def method_missing(*args, &block)
|
40
|
+
@store.transaction do
|
41
|
+
hash = @db
|
42
|
+
hash.send(*args, &block)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class << self
|
47
|
+
def flushdb(instance_key, id)
|
48
|
+
store = pstore(instance_key)
|
49
|
+
store.transaction { store.delete(db_name(id)) }
|
50
|
+
end
|
51
|
+
|
52
|
+
def flushall(instance_key)
|
53
|
+
store = pstore(instance_key)
|
54
|
+
store.transaction { store.roots.each {|r| store.delete(r) } }
|
55
|
+
end
|
56
|
+
|
57
|
+
def pstore(instance_key)
|
58
|
+
Utilities::SyncedPStore.new(File.join(Dir.tmpdir, instance_key.to_s))
|
59
|
+
end
|
60
|
+
|
61
|
+
def db_name(id)
|
62
|
+
"redis-#{id}"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
def db_name
|
68
|
+
self.class.db_name(@id)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|