FoundationDB Protocol Buffer Layer for Ruby
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
benchmark
ext/java/third_party
lib
spec
tasks
.gitignore
.ruby-gemset
.ruby-version
.travis.yml
Gemfile
LICENSE
README.md
Rakefile
fdb_proto.gemspec

README.md

FdbProto

FoundationDB Protocol Buffer Layer for Ruby.

This is the beginning of a Protocol Buffer backed entity layer for FoundationDB.

Note the prototype status of this layer - the API is messy, and the implementation is slow, this should be used for demonstration purposes only. Configuration is especially messy and unsafe, some choices were made for benchmarking purposes only. We plan to have a production-quality Java layer released in the future.

Relies on caching in JRuby for some easy but hacky performance gains. All cache sizes are controlled in lib/fdb_proto/caches.rb, but not directly configurable.

Most type checking has been completely turned off for speed. Originally, almost everything was typed checked when turned on but this caused at 36% performance penalty in benchmarking.

Supports the following Protocol Buffer libraries:

Example

Given the following protocol buffer messages:

package test;

enum Foo {
  ONE = 1;
  TWO = 2;
  THREE = 3;
}

message Bar {
  optional string string_1 = 1;
}

message EntityOne {
  optional string id = 1;

  optional string string_2 = 2;
  optional int64 int64_3 = 3;
  optional bytes bytes_4 = 4;
  optional Bar bar_5 = 5;
  repeated Bar repeated_bar_6 = 6;
  optional Foo foo_7 = 7;
}

message NestedId {
  optional string value = 1; 
}

message EntityTwo {
  optional NestedId nested_id = 1;

  optional string string_2 = 2;
  optional int32 int32_3 = 3;
}

Set up FdbProto as follows:

require 'fdb_proto'

FDB.api_version(200)
FdbProto.set_protobuf_library(:jprotobuf)       # required, valid options are :jprotobuf, :protocol_buffers
FdbProto.set_entity_class_to_entity_id_fully_qualified_tag(
  Test::EntityOne => FdbProto::FullyQualifiedTag.create(Test::EntityOne, 1),
  Test::EntityTwo => FdbProto::FullyQualifiedTag.create(Test::EntityTwo, 1, 1)
)                                               # required
FdbProto.set_entity_class_to_entity_class_id(
  Test::EntityOne => "1",
  Test::EntityTwo => "2"
)                                               # required, can never change, this is done for shorter keys
FdbProto.set_namespace_to_namespace_id(
  "test_namespace" => "1"
)                                               # required, can never change, this is done for shorter keys
FdbProto.set_location_cache_size(1 << 20)       # optional

Then use the client:

client = FdbProto::Client.new(
  "test_namespace",
  :debug => true
)                                               # debug is optional, exposes counts for number of calls to FDB
db = FdbProto.db("/path/to/fdb.cluster")        # if no cluster file specified, uses the default cluster file

db.transact do |tr|
  entity_one = Test::EntityOne.create(
    :id => "id1",
    :string_2 => "hello",
    :int64_3 => 1234,
    :bar_5 => Test::Bar.create(
      :string_1 => "bar"
    )
  )
  entity_two = Test::EntityTwo.create(
    :id => Test::NestedId.create(
      :value => "id2"
    ),
    :int32_3 => 5678
  )

  client.create(tr, [entity_one, entity_two])

  entity_two = Test::EntityTwo.create(
    :id => Test::NestedId.create(
      :value => "id2"
    ),
    :int32_3 => 8765
  )

  client.update(tr, [entity_two]) 

  entity_id_to_entity = client.get(
    tr,
    Test::EntityOne => "id1",
    Test::EntityTwo => "id2"
  )                                             # { "id1" => entity_one, "id2" => entity_two }
  entity_field_value_to_entity = client.get(
    tr,
    Test::EntityOne,
    FdbProto::FullyQualifiedTag.create(Test::EntityOne, 2),
    "hello, goodbye"
  )                                             # { "hello" => [entity_one] }
end

db.transact do |tr|
  client.get_all_entity_ids(tr, Test::EntityOne)        # ["id1"]
  client.exists(tr, Test::EntityOne => ["id1", "id2"])  # { "id1" => true, "id2" => false }
end

db.transact do |tr|
  client.delete(tr, Test::EntityTwo => ["id2"])
end

Written for Locality
http://www.locality.com

Authors

Peter Edge
peter@locality.com
http://github.com/peter-edge

License

MIT