Open6

gitdb: Bare Gitリポジトリをデータベースとして使う(仕切り直し)

okuokuokuoku

開発環境の都合で一旦リセットして仕切り直し。。

GitリポジトリをDBとして使うための考察を1つのライブラリとして纏めたい計画。GitリポジトリにはJSONの形でデータを記録し、最初の段階ではその読み書きをライブラリ化する。

次の段階では今MongoDBを使っているポイントをSQLiteにしたい。検索用のインデックスや配付用のアーカイブとしての利用なら手元のDBの規模ならSQLiteでも行けるんではないか説。

prev

https://zenn.dev/okuoku/scraps/fa3e4aa1a4cc9c

okuokuokuoku

write側

元々の設計ではキューイングもライブラリ側で面倒見ようと思ったが、需要が無かったのでやめた。1つのリポジトリに複数スレッド/プロセスからアクセスしないことはユーザーが保証する必要がある。

https://github.com/okuoku/rs-gitdb-proto/commit/4d4bcdb97ee81aff717390d9533b25b6b7253451

難しいことはそんなに無いな。。使い方も簡単で、

https://github.com/okuoku/rs-gitdb-proto/blob/4d4bcdb97ee81aff717390d9533b25b6b7253451/_check.mjs#L4-L10

全てのメソッドがPromiseを返却するので await を忘れると酷いことになる。

node.jsで子プロセスを起動してstdinを供給する

ファイルをリポジトリに投入するためには、 echo "Data" | git hash-object -w --stdin のような感じに、標準入力経由でデータを渡す必要がある。これは .stdin.end(buf) で簡単にできる。

https://github.com/okuoku/rs-gitdb-proto/blob/4d4bcdb97ee81aff717390d9533b25b6b7253451/gitdb.mjs#L41-L42

stdoutを受け入れるには、 data イベントを処理すれば良い。Encodingを指定すると data イベントには文字列が来るようになる。

https://github.com/okuoku/rs-gitdb-proto/blob/4d4bcdb97ee81aff717390d9533b25b6b7253451/gitdb.mjs#L30-L39

Closeのタイミングでプロセスが完了したということになる。

okuokuokuoku

bulk set

巨大なblobを足すことを考えるとbulk updateできた方が便利ではある。Gitのオブジェクトは全てSHA1 + gzipされる都合、追加時のCPUコストが高い。ただし、indexの更新は代表スレッドが一括して行う必要がある。

https://github.com/okuoku/rs-gitdb-proto/commit/3bfb6369f21a182e02b92deb9dbad89bda282dbf

いちいちwrite-object呼ぶんじゃなくて、自前でSHA1 + deflateするのが最良だよね多分。。nodejsにはzlib最初から入ってるし。。

https://git-scm.com/book/ja/v2/Gitの内側-Gitオブジェクト

okuokuokuoku

hexpath

gitdbではオブジェクトのプライマリキーをファイルパスで表現する。このとき、パスの形式には様々なものがある。

hexpath0 および hexpath は、オブジェクトのSHAハッシュ文字列をプライマリキーとする。hexpathは必ず最初の16bitsをプレフィックスとして切り、残りを長いディレクトリまたはファイル名として使用する。

hexpath0 は、プレフィックスとして使用されたビットはパス名として再利用されない。このためファイルを移動するとプライマリキーが失われる。このフォーマットは .git/objects 以下で使用されているものとほぼ同様となる(ただし、gitは先頭8bitのみをプレフィックスにしている)。 hexpath は、プレフィックスとして使用されたビットもパス名として再利用する。これはgit-lfsで使用されているものと同じフォーマットとなる。

実際のhexpathは更に prefix と objname を組み合わせてファイルのパスとして使用される。例えば、hexpath objects/c5/25/c525e03a9e6237f3a0ed673876db542b069938c055a6c14b67d6c1a580212c13 は、

  • format = hexpath
  • prefix = "objects/"
  • objname = ""

となる。

https://github.com/okuoku/rs-gitdb-proto/commit/aff821a423c3748a1b27c8a54297ddc90e9020b9

okuokuokuoku

直接オブジェクトを生成する

さすがにプロセス生成コストがもったいない(主にmacやWindows)から直接投入することにしてみた。

https://github.com/okuoku/rs-gitdb-proto/commit/c616e9da0278a684561eee2c623cd6a0e35440d6

... いやまぁやればできるんだけど、巨大ファイルとか扱いたくなったらどうすんのか問題はあるな。。まぁそういうファイルはプロセス起動して普通にgit呼べば良いんだろうけど。