-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
172ca52
commit ff32b29
Showing
5 changed files
with
183 additions
and
35 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,33 @@ | ||
// Package turl implements the business logic of the tiny URL service. | ||
package turl | ||
|
||
// type TinyURL struct { | ||
// db db.TinyURL | ||
// cache cache.TinyURL | ||
// } | ||
// | ||
// func New(db db.TinyURL, cache cache.Interface) *TinyURL { | ||
// return &TinyURL{ | ||
// db: db, | ||
// cache: cache, | ||
// } | ||
import ( | ||
"github.com/beiai0xff/turl/pkg/cache" | ||
"github.com/beiai0xff/turl/pkg/storage" | ||
) | ||
|
||
// TinyURL represents the tiny URL service. | ||
type TinyURL struct { | ||
db storage.Storage | ||
distributedCache cache.Interface | ||
localCache cache.Interface | ||
} | ||
|
||
// New creates a new TinyURL service. | ||
func newTinyURL(db storage.Storage, dcache, lcache cache.Interface) *TinyURL { | ||
return &TinyURL{ | ||
db: db, | ||
distributedCache: dcache, | ||
localCache: lcache, | ||
} | ||
} | ||
|
||
// // Create creates a new tiny URL. | ||
// func (t *TinyURL) Create(longURL []byte) error { | ||
// return nil | ||
// } | ||
// | ||
// func (t *TinyURL) Create(longURL string) error { | ||
// // Retrieve a tiny URL. | ||
// func (t *TinyURL) Retrieve(short string) error { | ||
// return nil | ||
// | ||
// } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
// Package pkg provides the implementation of the storage interface. | ||
package storage | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/redis/go-redis/v9" | ||
"gorm.io/gorm" | ||
) | ||
|
||
// Ensuring that *storage implements the Storage interface | ||
var _ Storage = (*storage)(nil) | ||
|
||
// Storage is an interface that defines the methods that a storage system must implement. | ||
type Storage interface { | ||
// Insert adds a new TinyURL record to the storage. | ||
Insert(ctx context.Context, short uint64, longURL []byte) error | ||
// GetTinyURLByID retrieves a TinyURL record by its ID. | ||
GetTinyURLByID(ctx context.Context, short uint64) (*TinyURL, error) | ||
// Close closes the storage. | ||
Close() error | ||
} | ||
|
||
// TinyURL represents a shortened URL record. | ||
type TinyURL struct { | ||
gorm.Model | ||
LongURL []byte `gorm:"type:VARCHAR(500);not null" json:"long_url"` // The original URL. | ||
Short uint64 `gorm:"type:BIGINT;index;not null" json:"short"` // The shortened URL ID. | ||
} | ||
|
||
// storage is a concrete implementation of the Storage interface. | ||
type storage struct { | ||
db *gorm.DB // Database client. | ||
rdb redis.UniversalClient // Redis client. | ||
} | ||
|
||
// New creates a new storage instance. | ||
func New(db *gorm.DB, rdb redis.UniversalClient) Storage { | ||
return newStorage(db, rdb) | ||
} | ||
|
||
// newStorage is a helper function that creates a new storage instance. | ||
func newStorage(db *gorm.DB, rdb redis.UniversalClient) *storage { | ||
return &storage{ | ||
db: db, | ||
rdb: rdb, | ||
} | ||
} | ||
|
||
// Insert adds a new TinyURL record to the storage. | ||
func (s *storage) Insert(ctx context.Context, short uint64, long []byte) error { | ||
t := TinyURL{ | ||
Short: short, | ||
LongURL: long, | ||
} | ||
|
||
// Create a new record in the database. | ||
return s.db.WithContext(ctx).Create(&t).Error | ||
} | ||
|
||
// GetTinyURLByID retrieves a TinyURL record by its ID. | ||
func (s *storage) GetTinyURLByID(ctx context.Context, short uint64) (*TinyURL, error) { | ||
t := TinyURL{} | ||
// Query the database for the record. | ||
res := s.db.WithContext(ctx).Where("short = ?", short).Take(&t) | ||
|
||
if res.Error != nil { | ||
return nil, res.Error | ||
} | ||
|
||
return &t, nil | ||
} | ||
|
||
// Close closes the storage. | ||
func (s *storage) Close() error { | ||
return s.rdb.Close() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
package storage | ||
|
||
import ( | ||
"context" | ||
"os" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/require" | ||
"gorm.io/gorm" | ||
|
||
"github.com/beiai0xff/turl/pkg/db/mysql" | ||
"github.com/beiai0xff/turl/pkg/db/redis" | ||
"github.com/beiai0xff/turl/test" | ||
) | ||
|
||
func TestMain(m *testing.M) { | ||
db, _ := mysql.New(test.DSN) | ||
|
||
db.AutoMigrate(&TinyURL{}) | ||
|
||
os.Exit(m.Run()) | ||
} | ||
|
||
func TestNew(t *testing.T) { | ||
db, _ := mysql.New(test.DSN) | ||
rdb := redis.Client(test.RedisAddr) | ||
|
||
s := New(db, rdb) | ||
t.Cleanup(func() { | ||
s.Close() | ||
}) | ||
|
||
require.NotNil(t, s) | ||
} | ||
|
||
func Test_newStorage(t *testing.T) { | ||
db, _ := mysql.New(test.DSN) | ||
rdb := redis.Client(test.RedisAddr) | ||
|
||
s := newStorage(db, rdb) | ||
t.Cleanup(func() { | ||
s.Close() | ||
}) | ||
|
||
require.NotNil(t, s) | ||
} | ||
|
||
func Test_storage_GetTinyURLByID(t *testing.T) { | ||
db, _ := mysql.New(test.DSN) | ||
rdb := redis.Client(test.RedisAddr) | ||
|
||
short, long := uint64(10000), []byte("www.google.com") | ||
s, ctx := newStorage(db, rdb), context.Background() | ||
t.Cleanup(func() { s.Close() }) | ||
|
||
require.NoError(t, s.Insert(ctx, short, long)) | ||
got, err := s.GetTinyURLByID(ctx, short) | ||
require.NoError(t, err) | ||
require.Equal(t, long, got.LongURL) | ||
|
||
got, err = s.GetTinyURLByID(ctx, 100) | ||
require.ErrorIs(t, err, gorm.ErrRecordNotFound) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters