An atproto PDS written in Go
1package blockstore 2 3import ( 4 "context" 5 "fmt" 6 7 "github.com/bluesky-social/indigo/atproto/syntax" 8 "github.com/haileyok/cocoon/models" 9 blocks "github.com/ipfs/go-block-format" 10 "github.com/ipfs/go-cid" 11 "gorm.io/gorm" 12 "gorm.io/gorm/clause" 13) 14 15type SqliteBlockstore struct { 16 db *gorm.DB 17 did string 18 readonly bool 19 inserts []blocks.Block 20} 21 22func New(did string, db *gorm.DB) *SqliteBlockstore { 23 return &SqliteBlockstore{ 24 did: did, 25 db: db, 26 readonly: false, 27 inserts: []blocks.Block{}, 28 } 29} 30 31func NewReadOnly(did string, db *gorm.DB) *SqliteBlockstore { 32 return &SqliteBlockstore{ 33 did: did, 34 db: db, 35 readonly: true, 36 inserts: []blocks.Block{}, 37 } 38} 39 40func (bs *SqliteBlockstore) Get(ctx context.Context, cid cid.Cid) (blocks.Block, error) { 41 var block models.Block 42 if err := bs.db.Raw("SELECT * FROM blocks WHERE did = ? AND cid = ?", bs.did, cid.Bytes()).Scan(&block).Error; err != nil { 43 return nil, err 44 } 45 46 b, err := blocks.NewBlockWithCid(block.Value, cid) 47 if err != nil { 48 return nil, err 49 } 50 51 return b, nil 52} 53 54func (bs *SqliteBlockstore) Put(ctx context.Context, block blocks.Block) error { 55 bs.inserts = append(bs.inserts, block) 56 57 if bs.readonly { 58 return nil 59 } 60 61 b := models.Block{ 62 Did: bs.did, 63 Cid: block.Cid().Bytes(), 64 Rev: syntax.NewTIDNow(0).String(), // TODO: WARN, this is bad. don't do this 65 Value: block.RawData(), 66 } 67 68 if err := bs.db.Clauses(clause.OnConflict{ 69 Columns: []clause.Column{{Name: "did"}, {Name: "cid"}}, 70 UpdateAll: true, 71 }).Create(&b).Error; err != nil { 72 return err 73 } 74 75 return nil 76} 77 78func (bs *SqliteBlockstore) DeleteBlock(context.Context, cid.Cid) error { 79 panic("not implemented") 80} 81 82func (bs *SqliteBlockstore) Has(context.Context, cid.Cid) (bool, error) { 83 panic("not implemented") 84} 85 86func (bs *SqliteBlockstore) GetSize(context.Context, cid.Cid) (int, error) { 87 panic("not implemented") 88} 89 90func (bs *SqliteBlockstore) PutMany(context.Context, []blocks.Block) error { 91 panic("not implemented") 92} 93 94func (bs *SqliteBlockstore) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) { 95 panic("not implemented") 96} 97 98func (bs *SqliteBlockstore) HashOnRead(enabled bool) { 99 panic("not implemented") 100} 101 102func (bs *SqliteBlockstore) UpdateRepo(ctx context.Context, root cid.Cid, rev string) error { 103 if err := bs.db.Exec("UPDATE repos SET root = ?, rev = ? WHERE did = ?", root.Bytes(), rev, bs.did).Error; err != nil { 104 return err 105 } 106 107 return nil 108} 109 110func (bs *SqliteBlockstore) Execute(ctx context.Context) error { 111 if !bs.readonly { 112 return fmt.Errorf("blockstore was not readonly") 113 } 114 115 bs.readonly = false 116 for _, b := range bs.inserts { 117 bs.Put(ctx, b) 118 } 119 bs.readonly = true 120 121 return nil 122} 123 124func (bs *SqliteBlockstore) GetLog() []blocks.Block { 125 return bs.inserts 126}