oria 0.0.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.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Flip Sasser
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,133 @@
1
+ Oria
2
+ ===
3
+
4
+ Oria (oh-rye-uh) is an in-memory, Ruby-based Key-Value Store. It's designed to handle moderate amounts of data quickly
5
+ and easily without causing deployment issues or server headaches. It uses EventMachine to provide a networked interface
6
+ to a semi-persistent KVS and asynchronously writes the in-memory data to YAML files.
7
+
8
+ Installation
9
+ -
10
+
11
+ Oria is a provided as a Gem. Use the following command to install it:
12
+
13
+ gem install oria --source http://gemcutter.org
14
+
15
+ That's it! You're ready to start storing basic data in memory. Now add
16
+
17
+ require "oria"
18
+
19
+ so's you can access Oria.
20
+
21
+ Command Line
22
+ -
23
+
24
+ The recommended pattern for starting and stopping Oria is using the Oria command line application, like so:
25
+
26
+ $ oria start|stop|restart
27
+
28
+ That's it! Oria will run in-memory, and you can always shut it down using `oria stop`.
29
+
30
+ Auto-Start and Daeomonizing
31
+ -
32
+
33
+ Yes, I recommend you use the command line. But on _[certain platforms](http://heroku.com)_, you don't have access to the
34
+ command line. And since Oria was built to be simple to use and to deploy, it also supports auto-starting and stopping. It
35
+ will detect a downed server and boot itself up in a separate thread. I should warn you, however: this functionality means
36
+ Oria requires a *nix environment - sorry, IronRuby users!
37
+
38
+ Oria auto-starts transparently, so just use it normally to take advantage of this feature. **Note:** this feature is currently
39
+ untested, so please test it heavily before deploying, and _report any issues you may have!_
40
+
41
+ Usage
42
+ -
43
+
44
+ Okay, now for the fun part. Oria behaves (mostly) like a Hash - you could say that it responds to 2/3 of @wycats' Moneta
45
+ plugin. Specifically, it responds to the following Hash methods:
46
+
47
+ []=(value) Set a key to ... something.
48
+
49
+ [] Retrieve a key
50
+
51
+ delete(key) Delete and return a key's value
52
+
53
+ key?(key) Returns a boolean value for whether or not that key exists
54
+
55
+ has_key?(key) Same as key
56
+
57
+ clear Clears all keys and values from Oria
58
+
59
+ In addition to those methods, Oria also supports a cool option inspired by some other KVS's:
60
+
61
+ stash(value) Stash a value in Oria. Returns the randomly generated key it stored the value under. This
62
+ is useful for when you need to store something temporarily, e.g. stash it, pass the key
63
+ in a URL, and retrieve / delete it.
64
+
65
+ So let's play:
66
+
67
+ Oria[:foo] = 'bar' #=> "bar"
68
+ Oria[:foo] #=> "bar"
69
+ Oria.key?(:foo) #=> true
70
+ Oria.delete(:foo) #=> foo
71
+ Oria[:foo] #=> nil
72
+ Oria.stash("baz") #=> "wZ"
73
+
74
+ Nothing exciting? Try shutting your app down and booting it back up.
75
+
76
+ Oria[:wZ] #=> "baz"
77
+
78
+ Bam. A relatively fast KVS with no configuration or special server setup.
79
+
80
+ But wait, I stored a <Ruby-specific object>! WTF?
81
+ -
82
+
83
+ Ah yes. You've found Oria's Achilles heel. Oria speaks JSON, so everything you give it must be capable of JSON'ing.
84
+ That means `Oria[:user] = User.find(1)` ain't working any time soon. Likewise, and perhaps more unfortunately, things like
85
+ `Oria[:my_cool_hash] = {:key => "Key!!!!!1", :value => "valyooooo"}` are going to return `{"key" => "Key", etc...}` so
86
+ your hashes are going to respond to string keys and not symbols once they've been through Oria.
87
+
88
+ It's a bummer, I know. But this is an in-memory KVS, and not Rails sessions where we're marshaling and un-marshaling everything
89
+ every request. I realize that it'll most likely only ever speak to Ruby clients (specifically this one), but this is where
90
+ it is. Sorry.
91
+
92
+ Configuration
93
+ -
94
+
95
+ Oria is built the be configuration-less out of the box, but if you really need to, you can tell it to do lots of
96
+ things. It's built on top of EventMachine, so networking is an option - but if you're networking your KVS, you should
97
+ think about upgrading to something like Redis or Memcached. Oria is meant to be used in situations where a database OR
98
+ a high-powered KVS would be overkill. But then again, you can use Oria to decentralize some of your tasks over a network,
99
+ which is fun. Observe:
100
+
101
+ Oria.connect(server, port) Connect to a server / port. Defaults to localhost and 6851
102
+
103
+ Oria.disconnect Kills the running server... maybe (see command line vs auto-start above)
104
+
105
+ Oria.app_key = value Oria supports "splitting" your apps, much like how Resque supports named queues. Specifying an
106
+ app key will effectively change the hash you are working with. It defaults to "default," cause
107
+ I'm original like that.
108
+
109
+ Let's try it out:
110
+
111
+ Oria.app_key = "my_app_1"
112
+ Oria[:foo] = "bar"
113
+ Oria[:foo] #=> "bar"
114
+
115
+ Oria.app_key = "my_app_2"
116
+ Oria[:foo] #=> nil
117
+ Oria.app_key = "my_app_1"
118
+ Oria[:foo] #=> "bar"
119
+
120
+ Dependencies
121
+ -
122
+
123
+ Oria speaks JSON, so it relies on the JSON gem. It depends on the newest stable version (1.2.0), so be sure to add the right version
124
+ checking code to your legacy apps before using Oria!
125
+
126
+ It also needs [EventMachine](http://github.com/eventmachine/eventmachine) to do everything. Yes, I could have used Drb or straight
127
+ UDP sockets, and spent a lifetime on this. But EventMachine is seriously, seriously, seriously awesome, and works very well
128
+ without me writing an insane amount of code I couldn't write very well anyway. Check it out and see for yourself.
129
+
130
+ That's it! I hope you enjoy Oria, and please let me know if you find any issues or have any trouble. As you will no doubt see from
131
+ the current version information, it's a very young project, and any contribution is welcome.
132
+
133
+ Copyright (c) 2009 Flip Sasser, released under the MIT license
data/Rakefile ADDED
@@ -0,0 +1,38 @@
1
+ require 'rake'
2
+
3
+ begin
4
+ require 'spec/rake/spectask'
5
+
6
+ desc "Run all examples"
7
+ Spec::Rake::SpecTask.new('spec') do |t|
8
+ t.spec_files = FileList['spec/**/*.rb']
9
+ end
10
+
11
+ desc "Run all examples with RCov"
12
+ Spec::Rake::SpecTask.new('spec:rcov') do |t|
13
+ t.spec_files = FileList['spec/**/*.rb']
14
+ t.rcov = true
15
+ t.rcov_opts = ['--exclude', 'spec,gem']
16
+ end
17
+ rescue LoadError
18
+ puts "Could not load Rspec. To run tests, use `gem install rspec`"
19
+ end
20
+
21
+ begin
22
+ require 'jeweler'
23
+ Jeweler::Tasks.new do |gemspec|
24
+ gemspec.name = "oria"
25
+ gemspec.summary = "A Ruby-based, in-memory KVS with one half of the peristence you want"
26
+ gemspec.description = %{
27
+ Oria (oh-rye-uh) is an in-memory, Ruby-based Key-Value store. It's designed to handle moderate amounts of data quickly
28
+ and easily without causing deployment issues or server headaches. It uses EventMachine to provide a networked interface
29
+ to a semi-persistent KVS and asynchronously writes the in-memory data to YAML files.
30
+ }
31
+ gemspec.email = "flip@x451.com"
32
+ gemspec.homepage = "http://github.com/flipsasser/oria"
33
+ gemspec.authors = ["Flip Sasser"]
34
+ gemspec.add_dependency('eventmachine', '>= 0.12.10')
35
+ gemspec.add_dependency('json', '>= 1.2.0')
36
+ end
37
+ rescue LoadError
38
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
data/bin/oria ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ # require 'oria'
3
+
4
+ # Oria.run!
@@ -0,0 +1,19 @@
1
+ module Oria
2
+ class Client < EventMachine::Connection
3
+ attr_reader :response
4
+
5
+ def connection_completed
6
+ @connected = true
7
+ end
8
+
9
+ def receive_data(data)
10
+ @response = JSON.parse(data)
11
+ close_connection
12
+ end
13
+
14
+ def unbind
15
+ raise Oria::ConnectionError.new("Could not connect to the Oria server") unless @connected
16
+ EventMachine.stop_event_loop
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,4 @@
1
+ module Oria
2
+ class ConnectionError < StandardError
3
+ end
4
+ end
@@ -0,0 +1,111 @@
1
+ require 'yaml'
2
+ require 'tmpdir'
3
+ module Oria
4
+ class Server < EventMachine::Connection
5
+ class << self
6
+ def debug?
7
+ @@debug
8
+ end
9
+
10
+ def logger
11
+ require 'logger'
12
+ @@logger ||= Logger.new(log_file, 0, 100 * 1024 * 1024)
13
+ end
14
+
15
+ def start(server, port, app_key = nil, debug = false)
16
+ @@pid = Process.pid
17
+ app_key ||= 'default'
18
+ @@servers ||= if File.exists?(yaml_store)
19
+ YAML.load_file(yaml_store)
20
+ else
21
+ {}
22
+ end
23
+ @@debug = !!debug
24
+ @@servers[app_key] ||= {}
25
+ EventMachine.run do
26
+ EventMachine.start_server server, port, Oria::Server
27
+ end
28
+ end
29
+
30
+ def stop
31
+ Process.kill('HUP', @@pid) if defined?(@@pid)
32
+ end
33
+
34
+ def write_hash
35
+ @@write_hash ||= proc do
36
+ File.open(yaml_store, 'w') do |store|
37
+ store.puts YAML.dump(@@servers)
38
+ end
39
+ end
40
+ end
41
+
42
+ protected
43
+ def log_file
44
+ @@log_file ||= File.join(Dir.tmpdir, 'oria.log')
45
+ end
46
+
47
+ def yaml_store
48
+ @@yaml_store ||= File.join(Dir.tmpdir, 'oria.yml')
49
+ end
50
+ end
51
+
52
+ def post_init
53
+ log "Client connected"
54
+ end
55
+
56
+ def receive_data(data)
57
+ log "Responding to #{data}"
58
+ data = data.split(' ')
59
+ method = data.shift
60
+ data = JSON.parse(data.join(' '))
61
+ @app_key = data.delete('app_key')
62
+ case method
63
+ when 'GET'
64
+ response = hash[data['key']]
65
+ when 'DELETE'
66
+ if data.empty?
67
+ hash.clear
68
+ else
69
+ response = hash.delete(data['key'])
70
+ end
71
+ when 'PUT'
72
+ if data.key?('key')
73
+ hash[data['key']] = data['value']
74
+ response = data['value']
75
+ elsif data.key?('value')
76
+ response = random_key
77
+ hash[response] = data['value']
78
+ end
79
+ end
80
+ if defined?(response)
81
+ response = JSON.generate({:response => response})
82
+ log "Sending response: #{response}"
83
+ send_data response
84
+ end
85
+ EventMachine.defer(Oria::Server.write_hash)
86
+ end
87
+
88
+ def unbind
89
+ end
90
+
91
+ private
92
+ def hash
93
+ @hash ||= @@servers[@app_key || 'default'] ||= {}
94
+ end
95
+
96
+ def log(value)
97
+ if Oria::Server.debug?
98
+ Oria::Server.logger.debug(value)
99
+ end
100
+ end
101
+
102
+ def random_key
103
+ chars = ['a'..'z', 'A'..'Z', 0..9].map(&:to_a).flatten
104
+ max = [hash.length, 2].max
105
+ while hash.key?(key = (1..max).map{|i| chars[rand(chars.length)]}.join)
106
+ key = (1..max).map{|i| chars[rand(chars.length)]}.join
107
+ end
108
+ key
109
+ end
110
+ end
111
+ end
data/lib/oria.rb ADDED
@@ -0,0 +1,96 @@
1
+ $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__))
2
+ require 'rubygems'
3
+ require 'eventmachine'
4
+ require 'json'
5
+ require 'oria/errors'
6
+
7
+ module Oria
8
+ autoload(:Client, 'oria/client')
9
+ autoload(:Server, 'oria/server')
10
+
11
+ def self.[](key)
12
+ store(:get, :key => key)
13
+ end
14
+
15
+ def self.[]=(key, value)
16
+ store(:put, :key => key, :value => value)
17
+ value
18
+ end
19
+
20
+ def self.app_key
21
+ @@app_key ||= nil
22
+ end
23
+
24
+ def self.app_key=(key)
25
+ @@app_key = key.to_s
26
+ end
27
+
28
+ def self.auto_start
29
+ @@pid = fork do
30
+ Oria::Server.start(Oria.server, Oria.port, Oria.app_key)
31
+ end
32
+ Process.detach(@@pid)
33
+ at_exit {
34
+ Process.kill("HUP", @@pid)
35
+ }
36
+ sleep 1
37
+ end
38
+
39
+ def self.clear
40
+ store(:delete)
41
+ end
42
+
43
+ def self.connect(server, port = nil, options = {})
44
+ @@server = server
45
+ @@port = port.to_i unless port.to_i == 0
46
+ end
47
+
48
+ def self.delete(key)
49
+ store(:delete, :key => key)
50
+ end
51
+
52
+ def self.disconnect
53
+ Oria::Server.stop
54
+ end
55
+
56
+ def self.has_key?(key)
57
+ key?(key)
58
+ end
59
+
60
+ def self.key?(key)
61
+ !self.[](key).nil?
62
+ end
63
+
64
+ def self.port
65
+ @@port ||= "Oria is easily the coolest in-memory, super-simple KVS. Cool people use it.".split("").inject(0) {|total, char| total += char[0]}
66
+ end
67
+
68
+ def self.server
69
+ @@server ||= '0.0.0.0'
70
+ end
71
+
72
+ def self.stash(value)
73
+ store(:put, :value => value)
74
+ end
75
+
76
+ private
77
+ def self.do_store(method, args)
78
+ client = nil
79
+ EventMachine.run do
80
+ client = EventMachine.connect(Oria.server, Oria.port, Oria::Client)
81
+ client.send_data("#{method.to_s.upcase}#{" #{args}" if args}")
82
+ end
83
+ if client.response
84
+ client.response['response']
85
+ end
86
+ end
87
+
88
+ def self.store(method, args = {})
89
+ args.merge!(:app_key => Oria.app_key)
90
+ args = JSON.generate(args)
91
+ do_store(method, args)
92
+ rescue Oria::ConnectionError
93
+ auto_start
94
+ do_store(method, args)
95
+ end
96
+ end
data/spec/oria_spec.rb ADDED
@@ -0,0 +1,155 @@
1
+ require "spec_helper"
2
+ require "oria"
3
+
4
+ describe Oria do
5
+ describe "Moneta methods" do
6
+ it "should include []" do
7
+ Oria.should respond_to(:[])
8
+ end
9
+
10
+ it "should include []=" do
11
+ Oria.should respond_to(:[]=)
12
+ end
13
+
14
+ it "should include clear" do
15
+ Oria.should respond_to(:clear)
16
+ end
17
+
18
+ it "should include delete" do
19
+ Oria.should respond_to(:delete)
20
+ end
21
+
22
+ it "should include has_key?" do
23
+ Oria.should respond_to(:has_key?)
24
+ end
25
+
26
+ it "should include key?" do
27
+ Oria.should respond_to(:key?)
28
+ end
29
+ end
30
+
31
+ it "should provide a connect method" do
32
+ Oria.should respond_to(:connect)
33
+ end
34
+
35
+ it "should support per-app keys" do
36
+ Oria.should respond_to(:app_key)
37
+ Oria.should respond_to(:app_key=)
38
+ end
39
+
40
+ it "should support custom connections" do
41
+ Oria.connect("127.0.0.1", 4567)
42
+ Oria.server.should == "127.0.0.1"
43
+ Oria.port.should == 4567
44
+ end
45
+
46
+ it "should automatically boot a server" do
47
+ # Oria.should_receive(:auto_start)
48
+ # Oria["foo"] = "bar"
49
+ # Oria.disconnect
50
+ end
51
+
52
+ describe "app_key" do
53
+ # it "should default to nil" do
54
+ # # This is bleeding over from the last example below. Frankly,
55
+ # # I don't know how to fix it.
56
+ # Oria.app_key.should be_nil
57
+ # end
58
+
59
+ it "should be configurable" do
60
+ Oria.app_key = "test_app"
61
+ Oria.app_key.should == "test_app"
62
+ end
63
+ end
64
+
65
+ it "should be possible to disconnect" do
66
+ Oria::Server.should_receive(:stop)
67
+ Oria["foo"] = "bar"
68
+ Oria.disconnect
69
+ end
70
+
71
+ describe "setting values" do
72
+ describe "with a booted server" do
73
+ before :all do
74
+ @pid = fork do
75
+ Oria::Server.start(Oria.server, Oria.port, nil, true)
76
+ end
77
+ Process.detach(@pid)
78
+ sleep 0.5
79
+ end
80
+
81
+ after :all do
82
+ Oria.clear
83
+ Oria::Server.stop
84
+ Process.kill("HUP", @pid)
85
+ end
86
+
87
+ it "should set string values" do
88
+ Oria["foo"] = "bar"
89
+ Oria["foo"].should == "bar"
90
+ end
91
+
92
+ it "should set integer values" do
93
+ Oria["foo"] = 12
94
+ Oria["foo"].should == 12
95
+ end
96
+
97
+ it "should support Hashes" do
98
+ Oria["foo"] = {"Flip" => "Sasser"}
99
+ Oria["foo"].should == {"Flip" => "Sasser"}
100
+ end
101
+
102
+ it "should support Arrays" do
103
+ Oria["foo"] = ["Foo", "Bar", "Baz"]
104
+ Oria["foo"].should == ["Foo", "Bar", "Baz"]
105
+ end
106
+
107
+ it "should support Booleans" do
108
+ Oria["true"] = false
109
+ Oria["true"].should == false
110
+ end
111
+
112
+ it "should support deleting values" do
113
+ Oria["memoria"] = "foobar"
114
+ Oria["dont_delete"] = "please"
115
+ Oria.delete("memoria").should == "foobar"
116
+ Oria["memora"].should be_nil
117
+ Oria["dont_delete"].should == "please"
118
+ end
119
+
120
+ it "should support complete clearing" do
121
+ Oria["a"] = "c"
122
+ Oria["b"] = "d"
123
+ Oria["a"].should == "c"
124
+ Oria["b"].should == "d"
125
+ Oria.clear
126
+ Oria["a"].should be_nil
127
+ Oria["b"].should be_nil
128
+ end
129
+
130
+ it "should support key-checking" do
131
+ Oria["key_check"] = "check-a-key"
132
+ Oria.key?("key_check").should be_true
133
+ Oria.key?("key_check_broken").should be_false
134
+ Oria.has_key?("key_check").should be_true
135
+ Oria.has_key?("key_check_broken").should be_false
136
+ end
137
+
138
+ it "should support stashing" do
139
+ key = Oria.stash("foobar")
140
+ key.should_not be_nil
141
+ Oria[key].should == "foobar"
142
+ end
143
+
144
+ it "should support different app_keys" do
145
+ Oria.app_key = "test_app_1"
146
+ Oria["test_app_1"] = "bar"
147
+ Oria["test_app_1"].should == "bar"
148
+ Oria.app_key = "test_app_2"
149
+ Oria["test_app_2"] = "baz"
150
+ Oria["test_app_1"].should be_nil
151
+ Oria["test_app_2"].should == "baz"
152
+ end
153
+ end
154
+ end
155
+ end
data/spec/rcov.opts ADDED
@@ -0,0 +1 @@
1
+ --exclude "spec/*,gems/*"
data/spec/spec.opts ADDED
@@ -0,0 +1,4 @@
1
+ --colour
2
+ --format progress
3
+ --loadby mtime
4
+ --reverse
@@ -0,0 +1,2 @@
1
+ $LOAD_PATH.unshift File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+
metadata ADDED
@@ -0,0 +1,88 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: oria
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Flip Sasser
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-11-22 00:00:00 -05:00
13
+ default_executable: oria
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: eventmachine
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 0.12.10
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: json
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 1.2.0
34
+ version:
35
+ description: "\n Oria (oh-rye-uh) is an in-memory, Ruby-based Key-Value store. It's designed to handle moderate amounts of data quickly\n and easily without causing deployment issues or server headaches. It uses EventMachine to provide a networked interface\n to a semi-persistent KVS and asynchronously writes the in-memory data to YAML files.\n "
36
+ email: flip@x451.com
37
+ executables:
38
+ - oria
39
+ extensions: []
40
+
41
+ extra_rdoc_files:
42
+ - LICENSE
43
+ - README.markdown
44
+ files:
45
+ - LICENSE
46
+ - README.markdown
47
+ - Rakefile
48
+ - VERSION
49
+ - bin/oria
50
+ - lib/oria.rb
51
+ - lib/oria/client.rb
52
+ - lib/oria/errors.rb
53
+ - lib/oria/server.rb
54
+ - spec/oria_spec.rb
55
+ - spec/rcov.opts
56
+ - spec/spec.opts
57
+ - spec/spec_helper.rb
58
+ has_rdoc: true
59
+ homepage: http://github.com/flipsasser/oria
60
+ licenses: []
61
+
62
+ post_install_message:
63
+ rdoc_options:
64
+ - --charset=UTF-8
65
+ require_paths:
66
+ - lib
67
+ required_ruby_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: "0"
72
+ version:
73
+ required_rubygems_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: "0"
78
+ version:
79
+ requirements: []
80
+
81
+ rubyforge_project:
82
+ rubygems_version: 1.3.5
83
+ signing_key:
84
+ specification_version: 3
85
+ summary: A Ruby-based, in-memory KVS with one half of the peristence you want
86
+ test_files:
87
+ - spec/oria_spec.rb
88
+ - spec/spec_helper.rb