STORJ DCSでLitestreamチュートリアル

# はじめに
ブロックチェーンを使った[STORJ DCS](https://www.storj.io/)というオブジェクトストレージがあります。S3より格段に安価[^1]でお手軽。今回はこれで[Litestreamのチュートリアル](https://litestream.io/getting-started/)をやってみました。

# 作業内容
## バケットの作成
![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2650925/e8587cca-edf6-910c-2a54-ab3137927043.png)
途中で生成されるパスフレーズを忘れずに控えること。

## S3 Credentialの生成
LitestreamはS3互換オブジェクトストレージを使うため、STORJ DCSが備える[S3互換ゲートウェイ](https://docs.storj.io/dcs/api-reference/s3-compatible-gateway/)を使用します。

![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2650925/57b58b36-5ee9-258e-6c1f-65ee53000467.png)

![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2650925/5333bdc7-0ce0-2939-65ae-c2abeed2877d.png)


PermissionはAllにする。

![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2650925/6a0eeab6-9f98-4866-c0bb-5fe117597064.png)
キーは再表示できないので注意。

## litestreamのビルド
オブジェクトストレージのエンドポイント指定が出来るのは現状 [e6f7c6052d84b7265fd54d3a3ab33208948e126b](https://github.com/benbjohnson/litestream/commit/e6f7c6052d84b7265fd54d3a3ab33208948e126b) 以降に含まれるのでビルドします。
簡単にするためDockerfileを参考にコンテナ内で作業。

```bash
$ docker run -it golang:1.17 bash
root@737141c5681f:/go# git clone https://github.com/benbjohnson/litestream.git
Cloning into 'litestream'...
remote: Enumerating objects: 2663, done.
remote: Counting objects: 100% (50/50), done.
remote: Compressing objects: 100% (37/37), done.
remote: Total 2663 (delta 16), reused 32 (delta 10), pack-reused 2613
Receiving objects: 100% (2663/2663), 930.59 KiB | 7.21 MiB/s, done.
Resolving deltas: 100% (1414/1414), done.
root@737141c5681f:/go# cd litestream/
root@737141c5681f:/go/litestream# git checkout e6f7c6052d84b7265fd54d3a3ab33208948e126b
Note: switching to 'e6f7c6052d84b7265fd54d3a3ab33208948e126b'.
(snip)
root@737141c5681f:/go/litestream# go build -ldflags "-s -w -X 'main.Version=latest' -extldflags '-static'" -tags osusergo,netgo,sqlite_omit_load_extension -o /usr/local/bin/litestream ./cmd/litestream
(snip)
root@737141c5681f:/go/litestream# which litestream
/usr/local/bin/litestream
root@737141c5681f:/go/litestream# 
```

## チュートリアルをやってみる
### データベース作成
```bash
root@737141c5681f:/go/litestream# apt update && apt install -y sqlite3
(snip)
root@737141c5681f:/go/litestream# sqlite3 fruits.db
SQLite version 3.34.1 2021-01-20 14:10:07
Enter ".help" for usage hints.
sqlite> CREATE TABLE fruits (name TEXT, color TEXT);
sqlite> INSERT INTO fruits (name, color) VALUES ('apple', 'red');
sqlite> INSERT INTO fruits (name, color) VALUES ('banana', 'yellow');
sqlite> 
```

### レプリケートする
別の端末を開いて、
```bash
$ docker ps | grep golang
737141c5681f   golang:1.17                                   "bash"                   16 minutes ago   Up 16 minutes                                               epic_mendel
$ docker exec -it epic_mendel bash
root@737141c5681f:/go# cd litestream/
root@737141c5681f:/go/litestream# export LITESTREAM_ACCESS_KEY_ID=<Access Key>
root@737141c5681f:/go/litestream# export LITESTREAM_SECRET_ACCESS_KEY=<Secret Key>
root@737141c5681f:/go/litestream# export LITESTREAM_ENDPOINT=gateway.storjshare.io
root@737141c5681f:/go/litestream# litestream replicate fruits.db s3://litestream/fruits.db
litestream latest
initialized db: /go/litestream/fruits.db
replicating to: name="s3" type="s3" bucket="litestream" path="fruits.db" region="" endpoint="https://gateway.storjshare.io" sync-interval=1s
litestream initialization complete
/go/litestream/fruits.db: init: no wal files available, clearing generation
/go/litestream/fruits.db: init: no wal files available, clearing generation
/go/litestream/fruits.db: sync: new generation "47ba1eac4ceb12ea", no generation exists
/go/litestream/fruits.db(s3): snapshot written 47ba1eac4ceb12ea/0000000000000000
/go/litestream/fruits.db(s3): wal segment written: 47ba1eac4ceb12ea/0000000000000000:0000000000000000 sz=16512
```
LITESTREAM_ENDPOINTにSTORJ DCSの画面から取れる `https://gateway.storjshare.io` をそのまま入れるとハマります。 `https://` を取り除いて入れること。

### リストアする
もう一つ別の端末を開き、
```bash
$ docker ps | grep golang
737141c5681f   golang:1.17                                   "bash"                   16 minutes ago   Up 16 minutes                                               epic_mendel
$ docker exec -it epic_mendel bash
root@737141c5681f:/go# export LITESTREAM_ACCESS_KEY_ID=<Access Key>
root@737141c5681f:/go# export LITESTREAM_SECRET_ACCESS_KEY=<Secret Key>
root@737141c5681f:/go# export LITESTREAM_ENDPOINT=gateway.storjshare.io
root@737141c5681f:/go# litestream restore -o fruits2.db s3://litestream/fruits.db
2022/09/06 12:16:03.298026 restoring snapshot 47ba1eac4ceb12ea/0000000000000000 to fruits2.db.tmp
2022/09/06 12:16:04.670117 applied wal 47ba1eac4ceb12ea/0000000000000000 elapsed=7.53352ms
2022/09/06 12:16:04.670130 renaming database from temporary location
root@737141c5681f:/go# sqlite3 fruits2.db 'select * from fruits'
apple|red
banana|yellow
root@737141c5681f:/go# 
```

### レプリケーションされているか確認する
最初の端末にて
```bash
sqlite> INSERT INTO fruits (name, color) VALUES ('grape', 'purple');
```
三番目の端末にて
```bash
root@737141c5681f:/go# litestream restore -o fruits3.db s3://litestream/fruits.db
2022/09/06 12:57:51.111777 restoring snapshot 2e989bbec9dfb611/0000000000000000 to fruits3.db.tmp
2022/09/06 12:57:53.233658 applied wal 2e989bbec9dfb611/0000000000000000 elapsed=6.843686ms
2022/09/06 12:57:53.233671 renaming database from temporary location
root@737141c5681f:/go# sqlite3 fruits3.db 'select * from fruits'
apple|red
banana|yellow
grape|purple
root@737141c5681f:/go# 
```

# おわりに
ソースからビルドすればSTORJ DCSでLitestreamを使用できました。SQLiteで扱うDBはさほど巨大にはならないでしょうからS3でも大した出費にはならない気もしますが、コストが押さえられるに越したことはないので結構良いのではないでしょうか。

[^1]:[$4/TB](https://www.storj.io/pricing)