Auto-indexing service and GraphQL API for AT Protocol Records quickslice.slices.network/
atproto gleam graphql
at main 74 lines 2.3 kB view raw
1// server/src/database/sqlite/connection.gleam 2 3import database/executor.{type DbError, type Executor, ConnectionError} 4import database/sqlite/executor as sqlite_executor 5import gleam/result 6import gleam/string 7import logging 8import sqlight 9 10/// Connect to SQLite database and return an Executor 11/// Handles SQLite-specific connection setup (PRAGMAs, etc.) 12pub fn connect(url: String) -> Result(Executor, DbError) { 13 let path = parse_path(url) 14 15 use conn <- result.try( 16 sqlight.open(path) 17 |> result.map_error(fn(e) { 18 ConnectionError( 19 "Failed to open SQLite database: " <> sqlight_error_message(e), 20 ) 21 }), 22 ) 23 24 // Enable WAL mode for better concurrency 25 use _ <- result.try(exec_pragma(conn, "PRAGMA journal_mode = WAL")) 26 27 // Performance tuning - safe with WAL mode 28 use _ <- result.try(exec_pragma(conn, "PRAGMA synchronous = NORMAL")) 29 use _ <- result.try(exec_pragma(conn, "PRAGMA cache_size = -64000")) 30 use _ <- result.try(exec_pragma(conn, "PRAGMA mmap_size = 268435456")) 31 use _ <- result.try(exec_pragma(conn, "PRAGMA temp_store = MEMORY")) 32 use _ <- result.try(exec_pragma(conn, "PRAGMA busy_timeout = 5000")) 33 34 // Enable foreign key constraints 35 use _ <- result.try(exec_pragma(conn, "PRAGMA foreign_keys = ON")) 36 37 logging.log(logging.Info, "Connected to SQLite database: " <> path) 38 39 Ok(sqlite_executor.new(conn)) 40} 41 42/// Parse the path from a SQLite URL 43/// Supports: "sqlite:./path/to/db", "file:./path/to/db", or just "./path/to/db" 44fn parse_path(url: String) -> String { 45 case string.split_once(url, ":") { 46 Ok(#(scheme, rest)) -> 47 case scheme { 48 "sqlite" | "file" -> 49 case string.starts_with(rest, "//") { 50 True -> string.drop_start(rest, 2) 51 False -> rest 52 } 53 _ -> url 54 } 55 Error(_) -> url 56 } 57} 58 59/// Execute a PRAGMA statement 60fn exec_pragma(conn: sqlight.Connection, pragma: String) -> Result(Nil, DbError) { 61 sqlight.exec(pragma, conn) 62 |> result.map_error(fn(e) { 63 ConnectionError( 64 "Failed to execute " <> pragma <> ": " <> sqlight_error_message(e), 65 ) 66 }) 67} 68 69/// Get error message from sqlight error 70fn sqlight_error_message(err: sqlight.Error) -> String { 71 case err { 72 sqlight.SqlightError(_, message, _) -> message 73 } 74}