⑁ Campchair

A fast LevelDB object-persistence layer for Ruby

Build Status

This README is a wishlist. The thing doesn't entirely work yet!

Campchair provides some helpers for lazily materialized views, and gives you a choice of using ActiveRecord-like models or class-based, barebones data-structure access.

Persistence happens with LevelDB. Objects are serialized into documents using Ruby's Marshal class.

Update 2014-04

This project was born at Railscamp 11. Then I forgot about it, and in the interim learned a lot more about concurrent programming, to the point where I'd like to revive this project but would need to change nearly everything about it!

I'm sure you've been there...

Dependencies

  • Needs leveldb libraries brew install leveldb
  • Needs Ruby ;)

Current Limitations

  • This is not append-only and replication is not a feature.
  • There is no concurrent access.
  • There are no transactions.
  • There is no promise pipeline.

As a basic data structure store

For these examples we'll work with two documents.

fred = {
  :name       => 'Fred', :height => 1.748,
  :location   => 'Flinders St Station, Melbourne, Australia',
  :first_seen => Time.new(2012, 3, 6, 12, 10),
  :last_seen  => Time.new(2012, 3, 6, 12, 40)
}
jane = {
  :name       => 'Jane', :height => 1.634,
  :location   => 'Flinders St Station, Melbourne, Australia',
  :first_seen => Time.new(2012, 3, 6, 12, 20),
  :last_seen  => Time.new(2012, 3, 6, 12, 50)
}

Mixing in Campchair DB behavior to a class is as simple as...

class People
  include Campchair::Store
end

Now, use it like a Hash.

# Add a document to the db
key = People << fred

# Add another person
People << jane

# Rerieve a document from the db
fred = People[key]

# Delete the document from the db
People.delete(key)

# Update/create the document in the db using a key
fred[:last_seen] = Time.new(2012, 3, 6, 12, 40, 25)
doc[key] = fred

As an persisted object store

Sometimes you want persistence baked-in à la ActiveRecord.

class People
  include Campchair::Model
  # note: this includes Campchair::Store automagically
end

Then you get some extra methods:

# Add a person to the db
fred = People.new
fred.save
key = fred.key # think 'id'
# this key is generated
# but you can set one before saving if you like

# Rerieve a person from the db
fred = People.load(key) # think 'find'

# Delete the person!
fred.delete

# Reincarnate & persist
fred = Person.new
fred.save

# Attribtues get persisted
fred.attributes[:favourite_colour] = 'LSD'
fred.save

# as you can see with a Store-style query
People[fred.key] # => { :favourite_colour => 'LSD' }

Custom database path

By default, the folder for db files is 'cddb'. You can change this with:

Campchair.db_path = 'db/heavy_metrics'

You can also change the db on a per-class basis.

class Person
  include Campchair::LevelDB
  self.db_path = 'db/heavy_metrics/Person'
end

TODO

  • Transactions
  • Portable Promise Pipelines
  • Transforms
  • Cache invalidation / Bindings