Oria === Oria (oh-rye-uh) is an in-memory, Ruby-based Key-Value Store. It's designed to handle moderate amounts of data quickly and easily without causing deployment issues or server headaches. It uses EventMachine to provide a networked interface to a semi-persistent store and asynchronously writes the in-memory data to YAML files. Installation - Oria is provided as a Gem. Use the following command to install it: gem install oria --source http://gemcutter.org That's it! You're ready to start storing basic data in memory. Now add require "oria" so's you can access Oria. Command Line - The recommended pattern for starting and stopping Oria is using the Oria command line application, like so: $ oria start|stop|restart That's it! Oria will run in-memory, and you can always shut it down using `oria stop`. Auto-Start and Daeomonizing - Yes, I recommend you use the command line. But on _[certain platforms](http://heroku.com)_, you don't have access to the command line. And since Oria was built to be simple to use and to deploy, it also supports auto-starting and stopping. It will detect a downed server and boot itself up in a separate thread. I should warn you, however: this functionality means Oria requires a *nix environment - sorry, IronRuby users! Oria auto-starts transparently, so just use it normally to take advantage of this feature. **Note:** this feature is currently untested, so please test it heavily before deploying, and _report any issues you may have!_ Usage - Okay, now for the fun part. Oria behaves (mostly) like a Hash - you could say that it responds to 2/3 of [@wycats](http://github.com/wycats)' Moneta plugin. Specifically, it responds to the following Hash methods: []=(value) Set a key to ... something. [] Retrieve a key delete(key) Delete and return a key's value key?(key) Returns a boolean value for whether or not that key exists has_key?(key) Same as key clear Clears all keys and values from Oria In addition to those methods, Oria also supports a cool option inspired by some other KVS's: stash(value) Stash a value in Oria. Returns the randomly generated key it stored the value under. This is useful for when you need to store something temporarily, e.g. stash it, pass the key in a URL, and retrieve / delete it. So let's play: Oria[:foo] = 'bar' #=> "bar" Oria[:foo] #=> "bar" Oria.key?(:foo) #=> true Oria.delete(:foo) #=> foo Oria[:foo] #=> nil Oria.stash("baz") #=> "wZ" Nothing exciting? Try shutting your app down and booting it back up. Oria[:wZ] #=> "baz" Bam. A relatively fast KVS with no configuration or special server setup. But wait, I stored a ! WTF? - Ah yes. You've found Oria's Achilles heel. Oria speaks JSON, so everything you give it must be capable of JSON'ing. That means `Oria[:user] = User.find(1)` ain't working any time soon. Likewise, and perhaps more unfortunately, things like `Oria[:my_cool_hash] = {:key => "Key!!!!!1", :value => "valyooooo"}` are going to return `{"key" => "Key", etc...}` so your hashes are going to respond to string keys and not symbols once they've been through Oria. 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 every request. I realize that it'll most likely only ever speak to Ruby clients (specifically this one), but this is where it is. Sorry. Configuration - 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 things. It's built on top of EventMachine, so networking is an option - but if you're networking your KVS, you should think about upgrading to something like Redis or Memcached. Oria is meant to be used in situations where a database OR a high-powered KVS would be overkill. But then again, you can use Oria to decentralize some of your tasks over a network, which is fun. Observe: Oria.connect(server, port) Connect to a server / port. Defaults to localhost and 6851 Oria.disconnect Kills the running server... maybe (see command line vs auto-start above) Oria.app_key = value Oria supports "splitting" your apps, much like how Resque supports named queues. Specifying an app key will effectively change the hash you are working with. It defaults to "default," cause I'm original like that. Let's try it out: Oria.app_key = "my_app_1" Oria[:foo] = "bar" Oria[:foo] #=> "bar" Oria.app_key = "my_app_2" Oria[:foo] #=> nil Oria.app_key = "my_app_1" Oria[:foo] #=> "bar" 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 the current version information, it's a very young project, and any contribution is welcome. Dependencies - 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 checking code to your legacy apps before using Oria! It also needs [EventMachine](http://github.com/eventmachine/eventmachine) to do everything. Yes, I could have used Drb or straight UDP sockets, and spent a lifetime on this. But EventMachine is seriously, seriously, seriously awesome, and works very well without me writing an insane amount of code I couldn't write very well anyway. Check it out and see for yourself. Warnings - Oria is weak in a few places. First, it forks all over the place with no regard for the consequences. Someday I'm going to upgrade it to use Daemons, but not right now. In general, the forking is dangerous and clumsy. Also, Oria's auto-start feature relies on `sleep`. In fact, Oria relies on `sleep` in more than one place. _This is terrible_ and I want to fix it someday. But I also want to get the code out there so people can start breaking it and tell me where it breaks. Which means: **please report any problems you have using the [Github issue tracking](http://github.com/flipsasser/oria/issues)!** Benchmarks - I've run some benchmarks comparing Oria to Redis. It's not pretty: user system total real Redis (write): 0.050000 0.020000 0.070000 ( 0.115850) Oria (write): 0.140000 0.110000 0.250000 ( 1.267912) Redis (read): 0.070000 0.020000 0.090000 ( 0.145078) Oria (read): 0.150000 0.110000 0.260000 ( 1.247791) As you can see, Oria is about 10x slower than Redis on my development computer. Even worse, if you run the benchmark like so: ruby redis_v_oria.rb 10000 Oria's server will fail to fulfill all of those requests. Scary. Clearly, it needs some serious improvement. Oria will never be as performant as something like Redis - it's not meant to be (plus it's written in Ruby, not C). But it could use some reduction in overhead, and any help is welcome. But I knew Oria wouldn't compete with Redis. What about MySQL? user system total real MySQL (write): 0.270000 0.030000 0.300000 ( 0.445586) Oria (write): 0.170000 0.120000 0.290000 ( 1.676674) MySQL (read): 0.310000 0.020000 0.330000 ( 0.484944) Oria (read): 0.120000 0.120000 0.240000 ( 1.616851) Ew. Oria is consistently about 4x slower than MySQL. But check this out: I removed persistence, and here are the new benchmarks: user system total real Redis (write): 0.040000 0.020000 0.060000 ( 0.113882) Oria (write): 0.130000 0.100000 0.230000 ( 0.396776) Redis (read): 0.070000 0.020000 0.090000 ( 0.145068) Oria (read): 0.130000 0.100000 0.230000 ( 0.395410) That's getting competitive. How about MySQL? user system total real MySQL (write): 0.270000 0.030000 0.300000 ( 0.453413) Oria (write): 0.150000 0.110000 0.260000 ( 0.430725) MySQL (read): 0.320000 0.030000 0.350000 ( 0.484978) Oria (read): 0.100000 0.100000 0.200000 ( 0.373431) Oh snap! Oria outperforms MySQL when persistence is disabled. So I'll have to refactor the code. Copyright (c) 2009 Flip Sasser, released under the MIT license