Monorepo for Tangled tangled.org
4

Configure Feed

Select the types of activity you want to include in your feed.

1package cursor 2 3import ( 4 "database/sql" 5 "errors" 6 "fmt" 7 "log/slog" 8 9 _ "github.com/mattn/go-sqlite3" 10) 11 12type SqliteStore struct { 13 db *sql.DB 14 tableName string 15} 16 17type SqliteStoreOpt func(*SqliteStore) 18 19func WithTableName(name string) SqliteStoreOpt { 20 return func(s *SqliteStore) { 21 s.tableName = name 22 } 23} 24 25func NewSQLiteStore(dbPath string, opts ...SqliteStoreOpt) (*SqliteStore, error) { 26 db, err := sql.Open("sqlite3", dbPath+"?_foreign_keys=1") 27 if err != nil { 28 return nil, fmt.Errorf("failed to open sqlite database: %w", err) 29 } 30 31 store := &SqliteStore{ 32 db: db, 33 tableName: "cursors", 34 } 35 36 for _, o := range opts { 37 o(store) 38 } 39 40 if err := store.init(); err != nil { 41 return nil, err 42 } 43 44 return store, nil 45} 46 47func (s *SqliteStore) init() error { 48 createTable := fmt.Sprintf(` 49 create table if not exists %s ( 50 knot text primary key, 51 cursor integer 52 );`, s.tableName) 53 _, err := s.db.Exec(createTable) 54 return err 55} 56 57func (s *SqliteStore) Set(key string, cursor int64) { 58 query := fmt.Sprintf(` 59 insert into %s (knot, cursor) 60 values (?, ?) 61 on conflict(knot) do update set cursor=excluded.cursor; 62 `, s.tableName) 63 64 if _, err := s.db.Exec(query, key, cursor); err != nil { 65 slog.Default().Error("cursor sqlite set failed", "key", key, "cursor", cursor, "err", err) 66 } 67} 68 69func (s *SqliteStore) Get(key string) (cursor int64) { 70 query := fmt.Sprintf(` 71 select cursor from %s where knot = ?; 72 `, s.tableName) 73 err := s.db.QueryRow(query, key).Scan(&cursor) 74 75 if err != nil { 76 if !errors.Is(err, sql.ErrNoRows) { 77 slog.Default().Error("cursor sqlite get failed", "key", key, "err", err) 78 } 79 return 0 80 } 81 82 return cursor 83}