A community based topic aggregation platform built on atproto
1package carstore
2
3import (
4 "context"
5 "fmt"
6 "io"
7
8 "github.com/bluesky-social/indigo/carstore"
9 "github.com/bluesky-social/indigo/models"
10 "github.com/ipfs/go-cid"
11 "gorm.io/gorm"
12)
13
14// CarStore wraps Indigo's carstore for managing ATProto repository CAR files
15type CarStore struct {
16 cs carstore.CarStore
17}
18
19// NewCarStore creates a new CarStore instance using Indigo's implementation
20func NewCarStore(db *gorm.DB, carDirs []string) (*CarStore, error) {
21 // Initialize Indigo's carstore
22 cs, err := carstore.NewCarStore(db, carDirs)
23 if err != nil {
24 return nil, fmt.Errorf("initializing carstore: %w", err)
25 }
26
27 return &CarStore{
28 cs: cs,
29 }, nil
30}
31
32// ImportSlice imports a CAR file slice for a user
33func (c *CarStore) ImportSlice(ctx context.Context, uid models.Uid, since *string, carData []byte) (cid.Cid, error) {
34 rootCid, _, err := c.cs.ImportSlice(ctx, uid, since, carData)
35 if err != nil {
36 return cid.Undef, fmt.Errorf("importing CAR slice for UID %d: %w", uid, err)
37 }
38 return rootCid, nil
39}
40
41// ReadUserCar reads a user's repository CAR file
42func (c *CarStore) ReadUserCar(ctx context.Context, uid models.Uid, sinceRev string, incremental bool, w io.Writer) error {
43 if err := c.cs.ReadUserCar(ctx, uid, sinceRev, incremental, w); err != nil {
44 return fmt.Errorf("reading user CAR for UID %d: %w", uid, err)
45 }
46 return nil
47}
48
49// GetUserRepoHead gets the latest repository head CID for a user
50func (c *CarStore) GetUserRepoHead(ctx context.Context, uid models.Uid) (cid.Cid, error) {
51 head, err := c.cs.GetUserRepoHead(ctx, uid)
52 if err != nil {
53 return cid.Undef, fmt.Errorf("getting repo head for UID %d: %w", uid, err)
54 }
55 return head, nil
56}
57
58// CompactUserShards performs garbage collection and compaction for a user's data
59func (c *CarStore) CompactUserShards(ctx context.Context, uid models.Uid, aggressive bool) error {
60 _, err := c.cs.CompactUserShards(ctx, uid, aggressive)
61 if err != nil {
62 return fmt.Errorf("compacting shards for UID %d: %w", uid, err)
63 }
64 return nil
65}
66
67// WipeUserData removes all data for a user
68func (c *CarStore) WipeUserData(ctx context.Context, uid models.Uid) error {
69 if err := c.cs.WipeUserData(ctx, uid); err != nil {
70 return fmt.Errorf("wiping data for UID %d: %w", uid, err)
71 }
72 return nil
73}
74
75// NewDeltaSession creates a new session for writing deltas
76func (c *CarStore) NewDeltaSession(ctx context.Context, uid models.Uid, since *string) (*carstore.DeltaSession, error) {
77 session, err := c.cs.NewDeltaSession(ctx, uid, since)
78 if err != nil {
79 return nil, fmt.Errorf("creating delta session for UID %d: %w", uid, err)
80 }
81 return session, nil
82}
83
84// ReadOnlySession creates a read-only session for reading user data
85func (c *CarStore) ReadOnlySession(uid models.Uid) (*carstore.DeltaSession, error) {
86 session, err := c.cs.ReadOnlySession(uid)
87 if err != nil {
88 return nil, fmt.Errorf("creating read-only session for UID %d: %w", uid, err)
89 }
90 return session, nil
91}
92
93// Stat returns statistics about the carstore
94func (c *CarStore) Stat(ctx context.Context, uid models.Uid) ([]carstore.UserStat, error) {
95 stats, err := c.cs.Stat(ctx, uid)
96 if err != nil {
97 return nil, fmt.Errorf("getting stats for UID %d: %w", uid, err)
98 }
99 return stats, nil
100}