We've launched strokedb.com

Posted by yrashk

First version of StrokeDB’s site has been launched: http://strokedb.com/

StrokeDB's experimental composite metas syntax

Posted by yrashk

I was playing with this idea in my mind for a week or so and finally decided to put it into the code. The basic idea is that since any document can have multiple metas, why not improving API for this? Before latest commits, you needed to do things like:

 
u = User.new :name => "Yurii" 
u.metas << Buyer
u.metas << Seller
u.save!
 

It isn’t really nice. So what I have done just a couple of minutes ago is a special syntax for composite metas. You can simply use Meta#+ to add meta to meta:


User = Meta.new
    # ==> User
Buyer = Meta.new
    # ==> Buyer
Seller = Meta.new
    # ==> Seller
(User+Buyer+Seller).create! :name => "Yurii" 
    # ==> #<User,Buyer,Seller __version__: 5bf2..., name: "Yurii",  uuid: "32ae72c8-a1da-4ead-8bfb-d2aa65e727f3">

where created document will have actually three metas:

_[:__meta__]
    # ==> [#<StrokeDB::Meta __version__: b6a0..., name: "User", uuid:  "292b3226-8c69-4d21-bb2c-d4d8cd924bf2">, #<StrokeDB::Meta __version__:  d223..., name: "Buyer", uuid: "89d4c62a-b935-42c6-b680-78e1de0b7d9e">,  #<StrokeDB::Meta __version__: 2291..., name: "Seller", uuid: "52babc48-5bda-4ea1-a4c3-1c931185c290">]

Also (User+Buyer+Seller).find will work just as expected:


    # ==> [#<User,Buyer,Seller __version__: 5bf2..., name: "Yurii",  uuid: "32ae72c8-a1da-4ead-8bfb-d2aa65e727f3">]

(please note that composition order is important, not only in #find but it also defines a way how combined meta document will look like [Document#meta]).

Please note that this stuff is not fully complete yet, but as always, it is already funny to play with it.

StrokeDB's early implementation of inter-store sync

Posted by yrashk

This morning I’ve finalized an early implementation of inter-store synchronization. Please not that it is definitely not mature, API and details might change over time.

So, what is this for? Synchronization is a way to replicate document between stores back and forth, while preserving whole history of document changes.

Here you are an example:


# Main store is default store
store = StrokeDB.default_store
# Let's create another store
another_store = StrokeDB::Config.build(:base_path =>  'tmp_db').stores[:default]

# Here we're creating some document in another_store
doc = Document.create!(another_store, :hello => 'world')
# Updating it
doc.test = 'passed'
doc.save!

# Syncing it to store
# doc.__versions__.all.reverse is basically pass all versions of doc in reverse order (after this reversion latest version will be at the  end of list). Order is important
store.sync!(doc.__versions__.all.reverse,another_store.timestamp)

# updating document at store
doc_at_store = store.find(doc.uuid)
doc_at_store.ok = true
doc_at_store.save!

# Syncing it back to another_store
another_store.sync! 
(doc_at_store.__versions__.all.reverse,store.timestamp)

# Now, let's reload document at another store:
doc.reload
# ==> #<Doc __previous_version__: fe9e..., __version__: bdf6...,  hello: "world", ok: true, test: "passed", uuid:  "e70aca78-69d3-4e2c-920c-813f2c17be75">
# as you can see, it got 'ok' slot with value of true

Voila!

Synchronization will work just fine if you have a fast-forward situation and will raise ConflictCondition if you have a conflict. Oleg is working on merge3 algorithm to let it be one of the scenarios to resolve ConflictConditions; I am also thinking about 1-2 simple scenarios for conflict resolving.

Anyway, as I’ve said above, its API/way to work isn’t mature yet, so things might change.

Poor man's web application with StrokeDB and Merb

Posted by yrashk

Yesterday I’ve finally got to playing with StrokeDB as a database “server” for a web application (currently using Merb, but basically the following scenario should work for any Ruby-based framework)

So, while we’re going to create a nice realtime replication subsystem that will allow to build really largely scalable applications with StrokeDB, there is definitely a need to play with StrokeDB-powered web applications right away, even if it will not be that scalable and fast as we want it to be. That’s why I’ve tried to create something like simplistic way to use StrokeDB from few Merb application instances.

The basic idea is that all processes that want to access StrokeDB database need to access the only one “server” store over network connection. That’s why I’ve created RemoteStore concept that allows to access stores over DRb (more protocols could be added later). Since stores (SkiplistStore to be specific) aren’t really thread-safe, RemoteStore server is actually serving one client at a time. Unless you’re going to invoke long-running operations, it should be fast enough to play with this stuff.

So, here we go. Lets assume you have a Merb skeleton application (I am using merb-0.5.3 at the moment). All you need to do is:

  • Update your config/merb_init.rb to contain something like
 
puts "Loading StrokeDB..." 
$:.unshift File.dirname(__FILE__) + '/../../strokedb-ruby/' # replace with your StrokeDB path
require 'strokedb'

StrokeDB.use_global_default_config!

print "Configuring StrokeDB..." 
if ARGV.include?('--strokedb-server')
  print 'configuring server store...'
  StrokeDB::Config.build :base_path => File.dirname(__FILE__) + "/../db", :default => true
  STROKEDB_THREAD = StrokeDB.default_store.remote_server('druby://localhost:9999').start
else
  StrokeDB.default_store = StrokeDB::RemoteStore::DRb::Client.new('druby://localhost:9999')
end
puts "done." 
 
  • define some metas in app/models, like app/models/user.rb:

User = Meta.new

  • run StrokeDB server:

$ merb -r "STROKEDB_THREAD.join" --strokedb-server

  • enjoy StrokeDB-powered application!

For example, you can use it in your controllers, or simply play within merb console (merb -i)

Of course, this method is definitely poor man’s one and we’re working on a better ways to build StrokeDB-powered applications, but something is more than nothing :)

If you’ll have any problems with the above scenario, let me know.

StrokeDB's first validation

Posted by yrashk

Folks,

this morning I’ve crafted first validation primitive for StrokeDB— validates_presence_of

Here you are few examples of it:


User = StrokeDB::Meta.new do
        validates_presence_of :login
end
    # ==> User
User.create! rescue $!.message
    # ==> "User's login should be present on save" 


User = StrokeDB::Meta.new do
    validates_presence_of :login, :on => :create # or :save or :update
end


User = StrokeDB::Meta.new do
        validates_presence_of :login, :message => '#{meta} should always have #{slotname} to be able to log in'
end
    # ==> User
User.create! rescue $!.message
    # ==> "User should always have login to be able to log in" 

More validations to appear soon.

Enjoy!