Project

xitdb

0.0
The project is in a healthy, maintained state
Transactional collections, portable xitdb storage, and an explicit Ruby value profile.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Runtime

>= 3.3
 Project Readme

xitdb for Ruby

xitdb provides transactional collections in one file, implemented in Ruby. It requires MRI 3.3 or later. It requires no compiler or database service. Runtime dependencies are date and bigdecimal.

This is a Ruby implementation of xitdb, a binary format for immutable database structures. The repository is named xitdb-ruby; the gem and require path are xitdb.

The portable profile reads and writes upstream xitdb structures. The Ruby profile adds typed keys, ordered maps, and Ruby values. Both profiles use the same storage core. Requiring the Ruby extension does not change portable behavior.

Install

Add the gem to your application's bundle:

bundle add xitdb

Or install it directly:

gem install xitdb

Quick start

Use String keys and portable values to share files with other xitdb implementations:

require "xitdb"

XitDB.open("shared.xit") do |db|
  db.transaction { |root| root["profile"] = { "name" => "Ada", "visits" => 0 } }
  before = db.snapshot
  db.transaction { |root| root["profile"]["visits"] += 1 }
  p before.dig("profile", "visits")       # 0
  p db.snapshot.dig("profile", "visits")  # 1
end

Use the Ruby profile for Symbol keys, booleans, arbitrary-size integers, and other Ruby values:

require "xitdb/ruby"

XitDB::Ruby.memory do |db|
  db.transaction do |root|
    root[:enabled] = true
    root[:large] = 2**200
  end
  p db.snapshot[:enabled] # true
end

Choose a profile

Entry point Values and keys File identifier
XitDB.open, XitDB.memory Portable integers, floats, bytes, collections, and String keys sha1 by default; hash: :sha256 selects sha2
XitDB::Ruby.open, XitDB::Ruby.memory Ruby scalar values, typed keys, and ordered maps and sets rb01
XitDB::Core::Database Raw slots, every upstream collection, and arbitrary roots Explicit storage configuration

Opening never converts a profile. Public entry points reject a mismatched profile and pre-existing zero-byte files. Missing paths are created. Block forms close the handle; callers close handles returned without a block.

Transactions and limits

Write through db.transaction. Normal block completion commits; an exception aborts the transaction. Snapshots retain their committed values through later writes and remain usable until the database handle closes. Transaction views expire when their block ends. Use to_ruby to obtain independent Ruby containers.

Writers serialize across cooperating threads and processes. Lock timeout raises XitDB::BusyError before the transaction block runs. File commits synchronize data and root publication. A XitDB::CommitError reports whether publication failed, succeeded, or has an unknown outcome. See locking and durability before implementing retries.

Portable maps and sets require String keys or members; portable values exclude booleans and Symbols. The Ruby profile supports these types and preserves insertion order in ordinary maps and sets. Profile conversion is explicit. Conversion can duplicate shared data across histories; see measurements and costs.

Version 0.1.0 is the initial release. The public API can change before 1.0.

Documentation

Start with Learn xitdb for a beginner's explanation of values, transactions, snapshots, profiles, and storage. Ruby source includes YARD API comments. With YARD available, run yard doc and open doc/index.html.

Read the portable guide, Ruby guide, and core guide. The Ruby wire contract defines cross-language interpretation of rb01. Other languages can preserve Ruby-profile bytes without decoding their logical values.

Run the workflows

  1. Run ruby examples/portable.rb for nested updates, snapshots, history, streams, compaction, and replication.
  2. Run ruby examples/ruby.rb for native values, codecs, cross-file copying, and explicit conversion.
  3. Run ruby examples/indexed_users.rb for atomic record/index updates and sorted pagination.

Examples require the installed package and write temporary files only. Each emits one JSON object. From a checkout, run them with bundle exec ruby -Ilib examples/portable.rb, substituting the example filename.

Verify a checkout

Run bundle install to install the locked development dependencies. Run bundle exec ruby script/ci.rb to check the checkout. It checks Ruby style, library types, and Change Risk Anti-Patterns (CRAP), then inspects the locally built package. The tests execute packaged examples from temporary storage and inspect package contents. The package check uses an isolated application bundle and local gem resolution. It does not install dependencies from the network.

bundle exec rake runs the same checks using the locked development dependencies. Plain rake also works when those versions are installed on Ruby's gem paths. RuboCop loads the Minitest, Performance, and Rake plugins. Individual checks are available:

Command Check
bundle exec rake rubocop Project style rules, with size metrics exempted
bundle exec rake types Steep diagnostics and 100% typed calls in every library file
bundle exec rake crap Fast tests with fresh SimpleCov coverage, then a CRAP limit of 10
bundle exec rake test Fast tests without the analysis tools

RBS signatures ship in sig/. Custom codec results have an unknown type until callers validate their class. Type coverage measures checked method calls. It does not prove that arbitrary codec output meets an application's domain constraints.

The workflow defines separate reference and linux-memory jobs alongside Linux MRI 3.3, 3.4, and 4.0 and macOS jobs. Configure every job as a required branch check. Workflow definitions alone do not enable repository branch protection. Reference tools are mandatory for ruby script/interop.rb --all; unavailable tools fail that gate. The measurement guide records bounded-memory evidence and conversion costs.

Releases

See CHANGELOG.md for release changes and the release guide for the publishing procedure.

License

The package preserves the MIT license notice. Upstream xitdb references remain pinned in test/interop/manifest.json.