···176176177177 log.Info().Str("path", feedIndexPath).Msg("Feed index opened")
178178179179+ // One-time seed: copy any DIDs from the legacy BoltDB feed_registry bucket into
180180+ // SQLite known_dids. INSERT OR IGNORE makes this a no-op once DIDs are present.
181181+ if legacyDIDs := store.LegacyFeedDIDs(); len(legacyDIDs) > 0 {
182182+ added, err := feedIndex.SeedKnownDIDs(legacyDIDs)
183183+ if err != nil {
184184+ log.Warn().Err(err).Msg("Failed to seed known DIDs from legacy feed registry")
185185+ } else if added > 0 {
186186+ log.Info().Int("seeded", added).Msg("Seeded known_dids from legacy BoltDB feed registry")
187187+ }
188188+ }
189189+179190 // Populate feed registry from SQLite known_dids (replaces BoltDB feed registry)
180191 if knownDIDs, err := feedIndex.GetKnownDIDs(); err == nil {
181192 for _, did := range knownDIDs {
+18
internal/database/boltstore/store.go
···129129 return &JoinStore{db: s.db}
130130}
131131132132+// LegacyFeedDIDs reads DIDs from the old feed_registry bucket that existed
133133+// before the feed registry was moved to SQLite. Used for one-time migration
134134+// seeding on first startup after the transition.
135135+func (s *Store) LegacyFeedDIDs() []string {
136136+ var dids []string
137137+ _ = s.db.View(func(tx *bolt.Tx) error {
138138+ bucket := tx.Bucket([]byte("feed_registry"))
139139+ if bucket == nil {
140140+ return nil
141141+ }
142142+ return bucket.ForEach(func(k, _ []byte) error {
143143+ dids = append(dids, string(k))
144144+ return nil
145145+ })
146146+ })
147147+ return dids
148148+}
149149+132150// Stats returns database statistics.
133151func (s *Store) Stats() bolt.Stats {
134152 return s.db.Stats()
+18
internal/firehose/index.go
···245245 return idx.db
246246}
247247248248+// SeedKnownDIDs inserts DIDs into known_dids, ignoring any that already exist.
249249+// Used for one-time migration from legacy storage.
250250+func (idx *FeedIndex) SeedKnownDIDs(dids []string) (int, error) {
251251+ if len(dids) == 0 {
252252+ return 0, nil
253253+ }
254254+ var added int
255255+ for _, did := range dids {
256256+ res, err := idx.db.Exec(`INSERT OR IGNORE INTO known_dids (did) VALUES (?)`, did)
257257+ if err != nil {
258258+ return added, fmt.Errorf("seed known DID %s: %w", did, err)
259259+ }
260260+ n, _ := res.RowsAffected()
261261+ added += int(n)
262262+ }
263263+ return added, nil
264264+}
265265+248266// Close closes the index database
249267func (idx *FeedIndex) Close() error {
250268 if idx.db != nil {