stash 1.0.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,92 +0,0 @@
1
- Stash
2
- =====
3
-
4
- *"The sloping companion I cast down the ash, yanked on my tunic and dangled my stash"*
5
-
6
- Stash provides Ruby-like classes for interacting with data structures servers.
7
- Presently the only such server supported is Redis, however support is planned
8
- for Membase, Memcache, and possibly Kestrel.
9
-
10
- Initializing Stash
11
- ------------------
12
-
13
- Stash supports multiple connections which are initialized through the
14
- stash Stash.setup command. Stash operates primarily through the default
15
- connection:
16
-
17
- Stash.setup :default, :adapter => :redis, :host => 'localhost'
18
-
19
- This will connect to the Redis server listening on localhost. Stash.setup
20
- takes an options hash with the following parameters:
21
-
22
- - **adapter**: must be "redis" (*mandatory*)
23
- - **host**: hostname or IP address of the Redis server (*mandatory*)
24
- - **port**: port of the Redis server (*optional, default 6379*)
25
- - **namespace**: Redis namspace to use (*optional, default global namespace*)
26
- - **password**: password to the Redis server (*optional*)
27
-
28
- Strings
29
- -------
30
-
31
- The core type exposed by Stash is a string. You can store a string in the
32
- default Stash using:
33
-
34
- Stash[:foobar] = "mystring"
35
-
36
- This string can be retrieved as easily as:
37
-
38
- Stash[:foobar]
39
-
40
- And deleted with:
41
-
42
- Stash.delete :foobar
43
-
44
- Lists
45
- -----
46
-
47
- Stash supports a mostly ordered list type. You can retrieve a list with:
48
-
49
- Stash::List[:baz]
50
-
51
- Stash Lists support most of the methods you'd expect on the Ruby Array type.
52
- They are enumerable and support all of Ruby's Enumerable methods.
53
-
54
- You can push elements onto the list with:
55
-
56
- Stash::List[:baz] << 'asdf'
57
-
58
- And pop them with:
59
-
60
- Stash::List[:baz].pop
61
-
62
- Lists can be converted to arrays with:
63
-
64
- Stash::List[:baz].to_a
65
-
66
- Or iterated with:
67
-
68
- Stash::List[:baz].each { |elem| ... }
69
-
70
- Stash asks you to think of lists as being somewhat loosely ordered. This
71
- means that Stash will make its best effort to give you a list in order,
72
- however that order may shift around depending on how the backend storage
73
- system is implemented. Distributed systems may be interesting properties.
74
-
75
- Hashes
76
- ------
77
-
78
- Stash hashes work like Ruby hashes. You can retrieve a Stash::Hash with:
79
-
80
- Stash::Hash[:qux]
81
-
82
- You can set members of a Stash::Hash with:
83
-
84
- Stash::Hash[:qux][:omgwtf] == "bbq"
85
-
86
- or retrieve them with:
87
-
88
- Stash::Hash[:qux][:omgwtf]
89
-
90
- You can convert a Stash::Hash to a Ruby hash with:
91
-
92
- Stash::Hash[:qux].to_hash
data/Rakefile DELETED
@@ -1,46 +0,0 @@
1
- require 'rubygems'
2
- require 'rake'
3
-
4
- begin
5
- require 'jeweler'
6
- Jeweler::Tasks.new do |gem|
7
- gem.name = "stash"
8
- gem.summary = "Abstract interface to data structures servers"
9
- gem.description = "Stash maps the facilities provided by data structures servers onto classes which mimic Ruby's built-in types"
10
- gem.email = "tony@medioh.com"
11
- gem.homepage = "http://github.com/tarcieri/stash"
12
- gem.authors = ["Tony Arcieri"]
13
- gem.add_dependency "redis", "~> 2.1.0"
14
- gem.add_dependency "redis-namespace", "~> 0.10.0"
15
- gem.add_development_dependency "rspec", ">= 2.2.0"
16
- # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
17
- end
18
- Jeweler::GemcutterTasks.new
19
- rescue LoadError
20
- puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
21
- end
22
-
23
- require 'rspec/core/rake_task'
24
- RSpec::Core::RakeTask.new(:rspec) do |rspec|
25
- rspec.rspec_opts = %w[-fs -c -b]
26
- end
27
-
28
- RSpec::Core::RakeTask.new(:rcov) do |rspec|
29
- rspec.rspec_opts = %w[-fs -c -b]
30
- rspec.rcov = true
31
- end
32
-
33
- task :rspec => :check_dependencies
34
- task :spec => :rspec
35
-
36
- task :default => :rspec
37
-
38
- require 'rake/rdoctask'
39
- Rake::RDocTask.new do |rdoc|
40
- version = File.exist?('VERSION') ? File.read('VERSION') : ""
41
-
42
- rdoc.rdoc_dir = 'rdoc'
43
- rdoc.title = "stash #{version}"
44
- rdoc.rdoc_files.include('README*')
45
- rdoc.rdoc_files.include('lib/**/*.rb')
46
- end
data/VERSION DELETED
@@ -1 +0,0 @@
1
- 1.0.0
@@ -1,59 +0,0 @@
1
- class Stash
2
- # Configuration error
3
- class ConfigError < StandardError; end
4
-
5
- module ClassMethods
6
- def [](key)
7
- default[key]
8
- end
9
-
10
- def []=(key, value)
11
- default[key] = value
12
- end
13
-
14
- # Add a configuration entry to Stash
15
- def setup(label, configuration)
16
- @configurations ||= {}
17
- @configurations[label.to_sym] = configuration
18
-
19
- if label == :default
20
- @default = nil
21
- default
22
- end
23
- end
24
-
25
- # Retrieve the default Stash configuration
26
- def default
27
- @default ||= begin
28
- raise ConfigError, "please configure me with Stash.setup" unless @configurations
29
- raise ConfigError, "no default configuration" unless @configurations[:default]
30
- new(@configurations[:default])
31
- end
32
- end
33
-
34
- # Retrieve a particular Stash configuration
35
- def configuration(key)
36
- @configurations[key.to_sym]
37
- end
38
-
39
- # Delete a key from the Stash
40
- def delete(key)
41
- default.delete(key)
42
- true
43
- end
44
-
45
- # Obtain the class for a given adapter name
46
- def adapter_class(name)
47
- adapter_name = name.to_s.split('_').map { |s| s.capitalize }.join
48
- adapter_name << "Adapter"
49
-
50
- begin
51
- Stash.const_get adapter_name
52
- rescue NameError
53
- raise ArgumentError, "unknown adapter: #{name}"
54
- end
55
- end
56
- end
57
-
58
- extend ClassMethods
59
- end
@@ -1,62 +0,0 @@
1
- # Stash::Hashes are remotely located lookup tables
2
- class Stash::Hash
3
- include Enumerable
4
-
5
- def self.[](key)
6
- new(key)
7
- end
8
-
9
- def initialize(key, adapter = Stash.default.adapter)
10
- @name, @adapter = key.to_s, adapter
11
- end
12
-
13
- # Retrieve the value associated with a given key
14
- def [](key)
15
- @adapter.hash_get @name, key.to_s
16
- end
17
-
18
- # Set a value in the hash
19
- def []=(key, value)
20
- @adapter.hash_set @name, key.to_s, value.to_s
21
- end
22
-
23
- # Clear all elements from the hash
24
- def clear
25
- @adapter.delete @name
26
- self
27
- end
28
-
29
- # Delete a value from the hash
30
- def delete(key)
31
- @adapter.hash_delete @name, key.to_s
32
- end
33
-
34
- # Return the length of a hash
35
- def length
36
- @adapter.hash_length @name
37
- end
38
-
39
- # Is this hash empty?
40
- def empty?
41
- length == 0
42
- end
43
-
44
- # Cast to a Ruby hash
45
- def to_hash
46
- @adapter.hash_value @name
47
- end
48
-
49
- # Enumerate hashes
50
- def each(&block)
51
- to_hash.each(&block)
52
- self
53
- end
54
-
55
- # Inspect a hash
56
- def inspect
57
- "#<Stash::Hash[:#{@name}]: #{to_hash.inspect}>"
58
- end
59
-
60
- # Create a string representation of a hash
61
- alias_method :to_s, :inspect
62
- end
@@ -1,91 +0,0 @@
1
- # Stash::Lists are (mostly) ordered lists stored remotely on the server
2
- class Stash::List
3
- include Enumerable
4
-
5
- def self.[](key)
6
- new(key)
7
- end
8
-
9
- def initialize(key, adapter = Stash.default.adapter)
10
- @key, @adapter = key.to_s, adapter
11
- end
12
-
13
- # Cast to an array
14
- def to_ary
15
- @adapter.list_range @key, 0, length
16
- end
17
- alias_method :to_a, :to_ary
18
-
19
- # Get the length of a list
20
- def length
21
- @adapter.list_length(@key)
22
- end
23
-
24
- # Is this list empty?
25
- def empty?
26
- length == 0
27
- end
28
-
29
- # Clear all elements from the list
30
- def clear
31
- @adapter.delete @key
32
- self
33
- end
34
-
35
- # Push an element onto the list (i.e. right push)
36
- def push(elem)
37
- @adapter.list_push @key, elem.to_s, :right
38
- self
39
- end
40
- alias_method :<<, :push
41
- alias_method :rpush, :push
42
-
43
- # Unshift an element onto the list (i.e. left push)
44
- def unshift(elem)
45
- @adapter.list_push @key, elem.to_s, :left
46
- end
47
- alias_method :lpush, :unshift
48
-
49
- # Pop from a list (i.e. right pop)
50
- def pop
51
- @adapter.list_pop @key, :right
52
- end
53
- alias_method :rpop, :pop
54
-
55
- # Shift from a list (i.e. left pop)
56
- def shift
57
- @adapter.list_pop @key, :left
58
- end
59
- alias_method :lpop, :shift
60
-
61
- # Blocking shift: wait for a message to be pushed (with an optional timeout)
62
- def bshift(timeout = nil)
63
- @adapter.list_blocking_pop @key, :left, timeout
64
- end
65
- alias_method :blpop, :bshift
66
-
67
- # Blocking pop: wait for a message to be unshifted (with an optional timeout)
68
- def bpop(timeout = nil)
69
- @adapter.list_blocking_pop @key, :right, timeout
70
- end
71
- alias_method :brpop, :bpop
72
-
73
- # Iterate the list
74
- def each(&block)
75
- to_ary.each(&block)
76
- self
77
- end
78
-
79
- # Obtain the last element in a list
80
- def last
81
- to_ary[-1]
82
- end
83
-
84
- # Inspect a list
85
- def inspect
86
- "#<Stash::List[:#{@key}]: #{to_ary.inspect}>"
87
- end
88
-
89
- # Create a string representation of a list
90
- alias_method :to_s, :inspect
91
- end
@@ -1,152 +0,0 @@
1
- require 'redis'
2
- require 'redis-namespace'
3
-
4
- class Stash
5
- # Adapter for the Redis data structures server.
6
- # See http://code.google.com/p/redis/
7
- class RedisAdapter
8
- def initialize(config)
9
- # Convert config keys to symbols
10
- config = symbolize_config(config)
11
-
12
- raise ArgumentError, "missing 'host' key" unless config[:host]
13
- config[:port] ||= 6379 # Default Redis port
14
-
15
- @config = config
16
- end
17
-
18
- # Obtain a connection to Redis
19
- def connection
20
- redis = Redis.new @config
21
- redis = Redis::Namespace.new @config[:namespace], :redis => redis if @config[:namespace]
22
-
23
- begin
24
- yield redis
25
- ensure
26
- redis.quit
27
- end
28
- end
29
-
30
- # Set a given key within Redis
31
- def []=(key, value)
32
- connection { |redis| redis.set key.to_s, value.to_s }
33
- end
34
-
35
- # Retrieve a given key from Redis
36
- def [](key)
37
- case type(key)
38
- when "none" then nil
39
- when "string" then Stash::String.new key, self
40
- when "list" then Stash::List.new key, self
41
- else raise "unknown Redis key type: #{key}"
42
- end
43
- end
44
-
45
- # Retrieve the type for a given key
46
- def type(key)
47
- connection { |redis| redis.type key.to_s }
48
- end
49
-
50
- # Retrieve a key as a string
51
- def get(key)
52
- connection { |redis| redis.get key.to_s }
53
- end
54
-
55
- # Delete a key
56
- def delete(key)
57
- connection { |redis| redis.del key.to_s }
58
- end
59
-
60
- # Push an element onto a list
61
- def list_push(name, value, side)
62
- connection do |redis|
63
- case side
64
- when :right
65
- redis.rpush name.to_s, value.to_s
66
- when :left
67
- redis.lpush name.to_s, value.to_s
68
- else raise ArgumentError, "left or right plztks"
69
- end
70
- end
71
- end
72
-
73
- # Pop from a list
74
- def list_pop(name, side)
75
- connection do |redis|
76
- case side
77
- when :right
78
- redis.rpop name.to_s
79
- when :left
80
- redis.lpop name.to_s
81
- else raise ArgumentError, "left or right plztks"
82
- end
83
- end
84
- end
85
-
86
- # Blocking pop from a list
87
- def list_blocking_pop(name, side, timeout = nil)
88
- connection do |redis|
89
- timeout ||= 0
90
- res = case side
91
- when :left
92
- redis.blpop name, timeout
93
- when :right
94
- redis.brpop name, timeout
95
- else raise ArgumentError, "left or right plztks"
96
- end
97
-
98
- return res[1] if res
99
- raise Stash::TimeoutError, "request timed out"
100
- end
101
- end
102
-
103
- # Retrieve the length of a list
104
- def list_length(name)
105
- connection { |redis| redis.llen name.to_s }
106
- end
107
-
108
- # Retrieve the given range from a list
109
- def list_range(name, from, to)
110
- connection { |redis| redis.lrange name.to_s, from, to }
111
- end
112
-
113
- # Retrieve a value from a hash
114
- def hash_get(name, key)
115
- res = connection { |redis| redis.hget name.to_s, key.to_s }
116
- return if res == ""
117
- res
118
- end
119
-
120
- # Store a value in a hash
121
- def hash_set(name, key, value)
122
- connection { |redis| redis.hset name.to_s, key.to_s, value.to_s }
123
- end
124
-
125
- # Retrieve the contents of a hash as a Ruby hash
126
- def hash_value(name)
127
- connection { |redis| redis.hgetall name.to_s }
128
- end
129
-
130
- # Delete an entry from a hash
131
- def hash_delete(name, key)
132
- connection { |redis| redis.hdel name.to_s, key.to_s }
133
- end
134
-
135
- # Return the length of a hash
136
- def hash_length(name)
137
- connection { |redis| redis.hlen name.to_s }
138
- end
139
-
140
- #######
141
- private
142
- #######
143
-
144
- def symbolize_config(config)
145
- new_config = {}
146
- config.each do |k, v|
147
- new_config[k.to_sym] = v
148
- end
149
- new_config
150
- end
151
- end
152
- end