An implementation of the ATProto statusphere example app but in Go
1package database
2
3import (
4 "database/sql"
5 "errors"
6 "fmt"
7 "log/slog"
8 "os"
9
10 _ "github.com/glebarez/go-sqlite"
11)
12
13type DB struct {
14 db *sql.DB
15}
16
17func New(dbPath string) (*DB, error) {
18 if dbPath != ":memory:" {
19 err := createDbFile(dbPath)
20 if err != nil {
21 return nil, fmt.Errorf("create db file: %w", err)
22 }
23 }
24
25 db, err := sql.Open("sqlite", dbPath)
26 if err != nil {
27 return nil, fmt.Errorf("open database: %w", err)
28 }
29
30 err = db.Ping()
31 if err != nil {
32 return nil, fmt.Errorf("ping db: %w", err)
33 }
34
35 err = createOauthRequestsTable(db)
36 if err != nil {
37 return nil, fmt.Errorf("creating oauth requests table: %w", err)
38 }
39
40 err = createOauthSessionsTable(db)
41 if err != nil {
42 return nil, fmt.Errorf("creating oauth sessions table: %w", err)
43 }
44
45 err = createStatusTable(db)
46 if err != nil {
47 return nil, fmt.Errorf("creating status table: %w", err)
48 }
49
50 err = createProfileTable(db)
51 if err != nil {
52 return nil, fmt.Errorf("creating profile table: %w", err)
53 }
54
55 err = createJetstreamTable(db)
56 if err != nil {
57 return nil, fmt.Errorf("creating jetstream table: %w", err)
58 }
59
60 return &DB{db: db}, nil
61}
62
63func (d *DB) Close() {
64 err := d.db.Close()
65 if err != nil {
66 slog.Error("failed to close db", "error", err)
67 }
68}
69
70func createDbFile(dbFilename string) error {
71 if _, err := os.Stat(dbFilename); !errors.Is(err, os.ErrNotExist) {
72 return nil
73 }
74
75 f, err := os.Create(dbFilename)
76 if err != nil {
77 return fmt.Errorf("create db file : %w", err)
78 }
79 f.Close()
80 return nil
81}