package shortify import ( "errors" "log" "go.etcd.io/bbolt" ) var bucketName = []byte("shorturls") func (s *Shortener) get(shortID string) (string, error) { if val, ok := s.memStore.Load(shortID); ok { s.cache.Add(shortID, val.(string)) return val.(string), nil } if val, ok := s.cache.Get(shortID); ok { return val.(string), nil } var longURL string err := s.db.View(func(tx *bbolt.Tx) error { b := tx.Bucket(bucketName) if b == nil { return errors.New("not found") } v := b.Get([]byte(shortID)) if v != nil { longURL = string(v) s.cache.Add(shortID, longURL) return nil } return errors.New("not found") }) return longURL, err } func (s *Shortener) put(shortID, longURL string) error { s.memStore.Store(shortID, longURL) s.cache.Add(shortID, longURL) // Queue write to DB (non-blocking) select { case s.writeChan <- [2]string{shortID, longURL}: default: log.Println("Warning: write queue full, short URL write may be dropped") } return nil } func (s *Shortener) asyncDBWriter() { for pair := range s.writeChan { shortID := pair[0] longURL := pair[1] err := s.db.Update(func(tx *bbolt.Tx) error { b, err := tx.CreateBucketIfNotExists(bucketName) if err != nil { return err } return b.Put([]byte(shortID), []byte(longURL)) }) if err != nil { log.Printf("DB write failed for %s: %v", shortID, err) } } }