···1818 echo *echo.Echo
1919 logger *slog.Logger
20202121- filterDids map[string]bool // DID -> exists (for quick filtering)
2222- backfillBuffer map[string][]*Op // DID -> buffered ops during backfill
2323- mu sync.RWMutex
2121+ filterDids map[string]bool // DID -> exists (for quick filtering)
2222+ mu sync.RWMutex
24232524 // for signature verification
2625 Dir identity.Directory
···4241}
43424443func NewNexus(config NexusConfig) (*Nexus, error) {
4545- // Open SQLite DB with GORM
4644 db, err := gorm.Open(sqlite.Open(config.DBPath), &gorm.Config{})
4745 if err != nil {
4846 return nil, err
4947 }
50485151- // Auto-migrate the schema
5252- if err := db.AutoMigrate(&models.BufferedEvt{}, &models.FilterDid{}); err != nil {
4949+ if err := db.AutoMigrate(&models.BufferedEvt{}, &models.FilterDid{}, &models.RepoRecord{}); err != nil {
5350 return nil, err
5451 }
55525656- // Create Echo instance
5753 e := echo.New()
5854 e.HideBanner = true
59556060- // main thing is skipping handle verification
6156 bdir := identity.BaseDirectory{
6257 SkipHandleVerification: true,
6358 TryAuthoritativeDNS: false,
···7065 echo: e,
7166 logger: slog.Default().With("system", "nexus"),
72677373- filterDids: make(map[string]bool),
7474- backfillBuffer: make(map[string][]*Op),
6868+ filterDids: make(map[string]bool),
75697670 Dir: &cdir,
7771···8377 return nil, err
8478 }
85798686- // Register routes
8780 n.registerRoutes()
88818982 return n, nil
···123116 for _, f := range filterDids {
124117 n.filterDids[f.Did] = true
125118126126- // Resume backfill for any repos in pending or backfilling state
127119 if f.State == models.RepoStatePending || f.State == models.RepoStateBackfilling {
128120 go n.backfillDid(context.Background(), f.Did)
129121 }
-7
nexus/outbox.go
···2323 }
2424}
25252626-// Subscribe drains buffered events from DB, then streams live events from channel
2727-// The send function is called for each event (e.g., ws.WriteJSON)
2826func (o *Outbox) Subscribe(ctx context.Context, send func(*Op) error) error {
2929- // 1. Load and drain buffered events from DB first
3027 var bufferedEvts []models.BufferedEvt
3128 if err := o.db.Order("id ASC").Find(&bufferedEvts).Error; err != nil {
3229 o.logger.Error("failed to load buffered events", "error", err)
···5956 }
6057 }
61586262- // Delete drained events
6359 if err := o.db.Delete(&bufferedEvts).Error; err != nil {
6460 o.logger.Error("failed to delete buffered events", "error", err)
6561 } else {
···6763 }
6864 }
69657070- // 2. Stream live events from channel
7166 o.logger.Info("starting live event stream")
7267 for {
7368 select {
···8277 }
8378}
84798585-// Send attempts to deliver event via channel, falls back to DB if channel is full or blocked
8680func (o *Outbox) Send(op *Op) error {
8781 select {
8882 case o.outCh <- op:
8983 return nil
9084 default:
9191- // Channel full or no readers, persist to DB
9285 return o.bufferToDB(op)
9386 }
9487}