Note: We changed the name of the database in May 2012. AvocadoDB is now called ArangoDB.

Introduction

One of the design goals of AvocadoDB is:

Use AvocadoDB as an application server and fuse your application and database together for maximal throughput

In order to act as application server, AvocadoDB has a build in language, currently JavaScript. As mruby became publically available a few hours ago, I started to see if can be viable alternative. This blog post summarizes my finding.

Status Quo

AvocadoDB acts as HTTP server. Each request is parsed, routed, and passed to a small piece of JavaScript, which generates an appropriate response. This can be as simple as

Note that no database access is involved in the above example. A more complex example

also accesses the database.

Using JavaScript for Actions and Transaction has the advantage that one can use one language from Front-End to the Storage-Engine. For example, JavaScript in Chrome together with jQuery for the browser, JavaScript in NODE.JS and express for the Web-Server, and JavaScript in the storage engine & app-server AvocadoDB. This is an option we already support.

However, there are also drawbacks:

  • JavaScript is a “complicated” language: not necessarily for the programmer but for the JavaScript engines like V8.
  • V8 itself is quite complex: dealing with isolates, contexts, handle scopes can lead to some amount of C++ code. Making it even hard to understand the V8 C++ code.
  • This makes it hard to use V8 in a multi-threaded environment. Presumable one of the reasons, why NODE.JS decided to stay single-threaded. AvocadoDB assume that it is not just a storage engine, but also needs to execute code to implement business logic. Next to the data, avoiding any network traffic. As a consequence it is multi-threaded.

Because of these complications I started looking for alternatives. Fortunately, just a few hours ago (2012-04-20 04:00) a first version of mruby was released. While the goals was to bring Ruby to mobile devices, mruby IMHO has some unique features that also make to very suitable for the above task – if anyone with deeper knowledge spots any mistakes, please let me know:

  • mruby is plain and simple C code
  • documentation is still sparse, but the C code itself is well-structured, so that it is easy to feel “at home”
  • in V8 it is very hard to create JavaScript wrappers for C++ objects. It seems that one of the design goals of mruby is to make this as easy as possible
  • mruby does not support threads – and yes, for me that is an advantage. I need to synchronize the executed code and the database access. Therefore have a language which does not support threads is very helpful

Minimalistic Ruby

When mruby come out a few hours ago, I decided to try a proof of concept. I wanted to implement at least the following features modeled after the JavaScript interface:

  • create a variable holding the current database “$db”
  • create a method “_collection” for the database to access a named collection
  • create a method “document” for the collection to access a document

The similar task in V8 took me quite some time to implement, with mruby it was much faster.

DataMapper / ActiveRecords

Note that this proof of concept is different from the idea of AvocadoDB API (aka adapter) currently discussed at Ashikawa. I’m not planning to implemented something similar to the DataMapper or ActiveRecords. The idea here is to implement the basics. It might be possible and useful to work with these basics to build a full ODM – or it might not.

Crossing the bridge between C and mruby

(1) Download the Source

Download the code from github: https://github.com/mruby/mruby

(2) Compile

Compile everything: I’ve tried the current version under Linux and MacOS

(3) REP

Create a basic read-eval-print loop

Note that “compile.h” does not live in “include”. This code gives you a very simple shell – you must enter the program as one-line-program 🙂

(4) Wrap C classes

Wrap the internal database variable into a mruby class. There was a post by Yukihiro Matsumoto on how to do it. So, you need a pointer to class you want to store. Easy in my case, the pointer lives in “_vocbase”. You need a structure describing what to do, when the variable is garbage collected (yes, compared to V8 it is THAT easy). In my case also trivial, because “_vocbase” points to singleton.

You also need a class. So I looked at the code to find the following example to create a class

Testing the code give:

So, I got my variable “$db” holding my database instance. The new should produce a singleton, but that is for later.

(5) Unwrap

Create a method returning a collection

Unwrapping the pointer uses the macro “mrb_object”. Extracting the arguments to function, uses “mrb_get_args”. That finishes my proof of concept. Accessing a document is identical to accessing a collection.

Open Todos

  • try proper error handling
  • check if the GC works as expected
  • find out how to implement a real console

Conclusion

It is much easier to implement the basic functionality with mruby as compared to V8. So, I will continue my experiments. mruby is still in an early phase and change quickly – but it already seems usable.