Skip to content

Commit a7c1ddd

Browse files
committed
make litestream work with sqlite wal mode
1 parent 6673dac commit a7c1ddd

File tree

5 files changed

+28
-8
lines changed

5 files changed

+28
-8
lines changed

README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,20 @@ Reproduction steps to see this issue after enabling WAL mode which is commented
3636
6. Now close the Docker Container resulting in a data loss
3737

3838
For this reason, I'll be avoiding WAL mode for now. When the time comes & I need multiple writes, I'll use PostgreSQL instead of SQLite if I need multiple writers on a database but since the process of multiple writes is instantanious (milliseconds) so I'll be going with SQLite for now anyways.
39+
40+
#### SQLite WAL Mode now works when used in combination with Litestream
41+
42+
I repeated the above 6 steps exactly as specified & there was no data loss.
43+
44+
I guess Litestream wrote it to its WAL Mode & when it found a wrong pointer, Litestream restored the database.
45+
46+
This was the log from Litestream that got me to this conclusion:
47+
48+
```bash
49+
time=2024-02-28T05:44:50.247Z level=WARN msg="init: cannot determine last wal position, clearing generation" db=/data/users.prod.sqlite error="primary wal header: EOF"
50+
time=2024-02-28T05:44:50.406Z level=INFO msg="sync: new generation" db=/data/users.prod.sqlite generation=ab8dd20a19bb28f7 reason="no generation exists"
51+
time=2024-02-28T05:44:51.298Z level=INFO msg="write snapshot" db=/data/users.prod.sqlite replica=s3 position=ab8dd20a19bb28f7/00000000:4152
52+
time=2024-02-28T05:44:51.720Z level=INFO msg="snapshot written" db=/data/users.prod.sqlite replica=s3 position=ab8dd20a19bb28f7/00000000:4152 elapsed=422.755427ms sz=1512
53+
time=2024-02-28T05:44:52.234Z level=INFO msg="write wal segment" db=/data/users.prod.sqlite replica=s3 position=ab8dd20a19bb28f7/00000000:0
54+
time=2024-02-28T05:44:52.602Z level=INFO msg="wal segment written" db=/data/users.prod.sqlite replica=s3 position=ab8dd20a19bb28f7/00000000:0 elapsed=367.834931ms sz=4152
55+
```

scripts/drizzle-migrate.mjs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ const url = isProduction
1111
console.log({ url })
1212
const client = sqlite(url, { verbose: console.log })
1313
// use sqlite pragma. recommended from https://cj.rs/blog/sqlite-pragma-cheatsheet-for-performance-and-consistency/
14-
// client.pragma('journal_mode=WAL') // see https://github.com/WiseLibs/better-sqlite3/blob/master/docs/performance.md
15-
// client.pragma('synchronous=normal')
16-
// client.pragma('foreign_keys=on')
14+
client.pragma('journal_mode=WAL') // see https://github.com/WiseLibs/better-sqlite3/blob/master/docs/performance.md
15+
client.pragma('synchronous=normal')
16+
client.pragma('foreign_keys=on')
1717
const db = drizzle(client)
1818

1919
async function main() {

scripts/run.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ MIGRATE_DATABASE=false
1010

1111
# Inspired by https://pranavmalvawala.com/run-script-only-on-first-start-up & https://serverfault.com/a/1134812/1078165
1212
CONTAINER_FIRST_STARTUP="CONTAINER_FIRST_STARTUP"
13-
if [[ ! -e /data/$CONTAINER_FIRST_STARTUP || $MIGRATE_DATABASE ]]; then
13+
if [[ ! -e /data/$CONTAINER_FIRST_STARTUP ]] && [[ $MIGRATE_DATABASE = true ]]; then
1414
# Place your script that you only want to run on first startup.
1515
echo 'Initialize database first time only'
1616
touch /data/$CONTAINER_FIRST_STARTUP

src/app/db/index.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ console.log(`ahoy!! using ${url}`)
1414

1515
const client = sqlite(url, { verbose: console.log })
1616
// use sqlite pragma. recommended from https://cj.rs/blog/sqlite-pragma-cheatsheet-for-performance-and-consistency/
17-
// client.pragma('journal_mode=WAL') // see https://github.com/WiseLibs/better-sqlite3/blob/master/docs/performance.md
18-
// client.pragma('synchronous=normal')
19-
// client.pragma('foreign_keys=on')
17+
client.pragma('journal_mode=WAL') // see https://github.com/WiseLibs/better-sqlite3/blob/master/docs/performance.md
18+
client.pragma('synchronous=normal')
19+
client.pragma('foreign_keys=on')
2020
export const db = drizzle(client)
2121

2222
// migrate(db, {

src/app/page.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@ import { GetData } from '@app/components/GetData'
33
export default function Home() {
44
return (
55
<main>
6-
<h1>Easypanel + Next.js + SQLite + Drizzle + Docker</h1>
6+
<h1>
7+
Easypanel + Next.js + SQLite + Drizzle + Litestream (Database Backups) +
8+
Docker
9+
</h1>
710
<GetData />
811
</main>
912
)

0 commit comments

Comments
 (0)