shortify/storage.go
2025-08-06 10:23:12 +02:00

72 lines
1.4 KiB
Go

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)
}
}
}