irmin icon indicating copy to clipboard operation
irmin copied to clipboard

WIP: Lavyek backend

Open balat opened this issue 3 months ago • 6 comments

This is a first attempt to write a Lavyek backend for Irmin. I did that as an experiment and also to learn the code. I managed to make it work in the toplevel with the following example:

#require "eio_main"
#require "digestif.c"
#require "irmin-watcher"
#require "irmin-lavyek"
#require "irmin.unix"

module Store = Irmin_lavyek.KV.Make (Irmin.Contents.String)
module Info = Irmin_unix.Info (Store.Info)

let value = "pouette"

let () =
  Eio_main.run @@ fun env ->
  Irmin_watcher.run @@ fun () ->
  let config = Irmin_lavyek.config ~fs:env#fs ~root:"/tmp/irminlavyek" in
  let repo = Store.Repo.v config in
  let main_branch = Store.main repo in
  Store.set_exn main_branch [ "a"; "b"; "c" ] value
    ~info:(Info.v ~author:"Example" "my first commit");
  let x = Store.get main_branch [ "a"; "b"; "c" ] in
  if value = x then print_endline "ok" else print_endline "ko"

Many functions are still not implemented (and some are probably missing in Lavyek). Install:

opam pin add irmin-lavyek .

balat avatar Sep 22 '25 13:09 balat

I did some changes to the branch:

  • Added a proper configuration
  • Added an mli file for irmin_lavyek
  • Updated v function to allow fresh stores
  • Corrected set function
  • Added various logs
  • Added remove implementation
  • Removed locks, lavyek should support parrallel additions.

clecat avatar Oct 10 '25 10:10 clecat

A new example would be:

#require "eio_main"
#require "digestif.c"
#require "irmin-watcher"
#require "irmin-lavyek"
#require "irmin.unix"

module Store = Irmin_lavyek.KV.Make (Irmin.Contents.String)
module Info = Irmin_unix.Info (Store.Info)

let value = "pouette"

let () =
  Eio_main.run @@ fun env ->
  Eio.Switch.run @@ fun sw ->
  Irmin_watcher.run @@ fun () ->
  let fs = env#fs in
  let path = Eio.Path.(fs / "/tmp/irmin-lavyek") in
  let config = Irmin_lavyek.config ~sw ~fs path in
  let repo = Store.Repo.v config in
  let main_branch = Store.main repo in
  Store.set_exn main_branch [ "a"; "b"; "c" ] value
    ~info:(Info.v ~author:"Example" "my first commit");
  let x = Store.get main_branch [ "a"; "b"; "c" ] in
  if value = x then print_endline "ok" else print_endline "ko";
  Store.Repo.close repo

clecat avatar Oct 10 '25 11:10 clecat

Here are tasks that we might want to do (non-exhaustive):

  • Allow iteration (need to change lavyek)
  • Allow clear (need to change lavyek)
  • Stats, for benchmarking purposes (need to change lavyek)
  • Add tests, similarly to irmin-fs
  • Allow list (need to change lavyek ? Or maybe mimic it by adding a second lavyek store which stores the "path hierarchy", unsure)

clecat avatar Oct 10 '25 11:10 clecat

I added the irmin-test suite on the lavyek side, I'll put my changes when ready not on master but on a branch named irmin-lavyek, in order to keep the main branch clean until someone makes the changes in the optimal way (the key removal not being optimal).

clecat avatar Oct 13 '25 07:10 clecat

When testing changes on lavyek, I met a big issue with irmin-lavyek: Irmin creates 4 different lavyek stores, but if we do not separate them, they start corrupting each other. The last commit uses the different Maker interfaces and adds a suffix to the root of the different stores.

clecat avatar Oct 15 '25 15:10 clecat

I have rebased this PR over the eio branch now that the PR #2280 has been merged, however we will still have to make lavyek public to get the CI running.

clecat avatar Nov 17 '25 09:11 clecat