an app.bsky.* indexer

use cursor service in census, fixup firehose cursor saving

Changed files
+50 -34
cmd
+10 -29
cmd/monarch/census.go
···
"github.com/bluesky-social/indigo/xrpc"
"github.com/urfave/cli/v2"
"golang.org/x/sync/semaphore"
-
"gorm.io/gorm"
)
type CensusService struct {
-
store *gorm.DB
+
cursor *CursorService
backfill *backfill.Backfiller
storeLk sync.Mutex
···
GetOrCreateJob(context.Context, string, string) (backfill.Job, error)
}
-
func NewCensusService(store *gorm.DB, backfillSvc *backfill.Backfiller) *CensusService {
+
func NewCensusService(cursorSvc *CursorService, backfillSvc *backfill.Backfiller) *CensusService {
return &CensusService{
-
store: store,
+
cursor: cursorSvc,
backfill: backfillSvc,
}
}
-
type relayCursor struct {
-
ID int `gorm:"primaryKey"`
-
Host string
-
Cursor string
-
}
-
-
type hostCursor struct {
-
ID int `gorm:"primaryKey"`
-
Host string
-
Cursor string
-
}
-
// fetch the PDSes known to the relay
func (cs *CensusService) listHosts(ctx context.Context, cctx *cli.Context) {
relay := cctx.String("relay-host")
···
Host: "https://" + relay,
}
-
var rcur relayCursor
-
if err := cs.store.Where("host = ?", relay).Attrs(relayCursor{
-
Host: relay,
-
Cursor: "",
-
}).FirstOrCreate(&rcur).Error; err != nil {
+
hcur, err := cs.cursor.GetHostCursor(relay)
+
if err != nil {
slog.Error("error fetching relay cursor", "err", err)
}
var wg sync.WaitGroup
sem := semaphore.NewWeighted(maxCrawlers)
-
curs := rcur.Cursor
+
curs := hcur.Cursor
for {
select {
case <-ctx.Done():
···
if res.Cursor != nil && *res.Cursor != "" {
curs = *res.Cursor
-
if err := cs.store.Model(&rcur).Update("cursor", curs).Error; err != nil {
+
if err := cs.cursor.SetHostCursor(relay, curs); err != nil {
slog.Error("error updating cursor for relay", "err", err)
}
} else {
···
}
cs.storeLk.Lock()
-
var hcur hostCursor
-
if err := cs.store.Where("host = ?", host).Attrs(hostCursor{
-
Host: host,
-
Cursor: "",
-
}).FirstOrCreate(&hcur).Error; err != nil {
+
hcur, err := cs.cursor.GetHostCursor(host)
+
if err != nil {
slog.Error("error fetching host cursor", "err", err)
}
cs.storeLk.Unlock()
···
if res.Cursor != nil && *res.Cursor != "" {
curs = *res.Cursor
cs.storeLk.Lock()
-
if err := cs.store.Model(&hcur).Update("cursor", curs).Error; err != nil {
+
if err := cs.cursor.SetHostCursor(host, curs); err != nil {
slog.Error("error updating cursor for host", "err", err)
}
cs.storeLk.Unlock()
-1
cmd/monarch/cursors.go
···
func NewCursorService(store *gorm.DB) *CursorService {
store.AutoMigrate(&firehoseCursor{})
-
store.AutoMigrate(&relayCursor{})
store.AutoMigrate(&hostCursor{})
return &CursorService{
+7 -3
cmd/monarch/firehose.go
···
defer cs.firehoseLk.Unlock()
var fcur firehoseCursor
-
if err := cs.store.Where("key = ?", "firehose").Attrs(firehoseCursor{Val: cs.firehoseSeq}).FirstOrCreate(&fcur).Error; err != nil {
+
if err := cs.store.Where(firehoseCursor{
+
Key: "firehose",
+
}).Attrs(firehoseCursor{
+
Key: "firehose",
+
Val: 0,
+
}).FirstOrCreate(&fcur).Error; err != nil {
return 0, fmt.Errorf("error getting firehose seq from DB: %w", err)
}
return fcur.Val, nil
···
cs.firehoseLk.Lock()
defer cs.firehoseLk.Unlock()
-
var fcur firehoseCursor
-
if err := cs.store.Where("key = ?", "firehose").Assign(firehoseCursor{Val: cs.firehoseSeq}).FirstOrCreate(&fcur).Error; err != nil {
+
if err := cs.store.Where(firehoseCursor{Key: "firehose"}).Update("val", cs.firehoseSeq).Error; err != nil {
return fmt.Errorf("error persisting firehose seq: %w", err)
}
return nil
+32
cmd/monarch/hosts.go
···
+
package main
+
+
type hostCursor struct {
+
ID int `gorm:"primaryKey"`
+
Host string
+
Cursor string
+
}
+
+
func (cs *CursorService) GetHostCursor(host string) (*hostCursor, error) {
+
var out hostCursor
+
+
if err := cs.store.Where(hostCursor{
+
Host: host,
+
}).Attrs(hostCursor{
+
Host: host,
+
Cursor: "",
+
}).FirstOrCreate(&out).Error; err != nil {
+
return nil, err
+
}
+
+
return &out, nil
+
}
+
+
func (cs *CursorService) SetHostCursor(host string, cursor string) error {
+
if err := cs.store.Where(hostCursor{
+
Host: host,
+
}).Update("cursor", cursor).Error; err != nil {
+
return err
+
}
+
+
return nil
+
}
+1 -1
cmd/monarch/main.go
···
app.backfill = NewBackfillService(backfill.NewGormstore(app.state), app.handler, cctx)
go app.backfill.Start()
-
app.census = NewCensusService(app.state, app.backfill)
+
app.census = NewCensusService(app.cursor, app.backfill)
go app.census.Start(ctx, cctx)
wsconn, err := NewFirehoseConnection(ctx, cctx, app.cursor)