72 lines
1.4 KiB
Go
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)
|
|
}
|
|
}
|
|
}
|