Skip to content

Commit

Permalink
Adding statistics
Browse files Browse the repository at this point in the history
  • Loading branch information
mchavez committed Aug 29, 2024
1 parent 0e39de8 commit f6539ef
Show file tree
Hide file tree
Showing 2 changed files with 172 additions and 32 deletions.
200 changes: 170 additions & 30 deletions pkg/uhttp/dbcache.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ const (
errQueryingTable = "Error querying cache table"
failRollback = "Failed to rollback transaction"
failInsert = "Failed to insert data into cache table"
staticQuery = "UPDATE http_cache SET %s=(%s+1) WHERE key = ?"
)

func NewDBCache(ctx context.Context, cfg CacheConfig) (*DBCache, error) {
Expand All @@ -70,10 +71,18 @@ func NewDBCache(ctx context.Context, cfg CacheConfig) (*DBCache, error) {
}

// Create cache table and index
_, err = db.Exec(`
_, err = db.ExecContext(ctx, `
CREATE TABLE IF NOT EXISTS http_cache(
id INTEGER PRIMARY KEY, key NVARCHAR, data BLOB, expiration INTEGER, url NVARCHAR,
Hits INTEGER, Misses INTEGER, DelHits INTEGER, DelMisses INTEGER, Collisions INTEGER
id INTEGER PRIMARY KEY,
key NVARCHAR,
data BLOB,
expiration INTEGER,
url NVARCHAR,
hits INTEGER DEFAULT 0,
misses INTEGER DEFAULT 0,
delhits INTEGER DEFAULT 0,
delmisses INTEGER DEFAULT 0,
collisions INTEGER DEFAULT 0
);
CREATE UNIQUE INDEX IF NOT EXISTS idx_cache_key ON http_cache (key);`)
if err != nil {
Expand Down Expand Up @@ -132,7 +141,7 @@ func (d *DBCache) CreateCacheKey(req *http.Request) (string, error) {
var headerParts []string
for key, values := range req.Header {
for _, value := range values {
if key == "Accept" || key == "Authorization" || key == "Cookie" || key == "Range" {
if key == "Accept" || key == "Content-Type" || key == "Cookie" || key == "Range" {
headerParts = append(headerParts, fmt.Sprintf("%s=%s", key, value))
}
}
Expand Down Expand Up @@ -168,14 +177,25 @@ func (d *DBCache) Get(ctx context.Context, key string) (*http.Response, error) {
return nil, err
}

err = d.Hits(ctx, key)
if err != nil {
ctxzap.Extract(ctx).Debug("Failed to update hits", zap.Error(err))
}

return resp, nil
}

err = d.Misses(ctx, key)
if err != nil {
ctxzap.Extract(ctx).Debug("Failed to update misses", zap.Error(err))
}

return nil, nil
}

// Set stores and save response in the db.
func (d *DBCache) Set(ctx context.Context, key string, value *http.Response) error {
var url string
if d.IsNilConnection() {
return fmt.Errorf("%s", nilConnection)
}
Expand All @@ -185,7 +205,15 @@ func (d *DBCache) Set(ctx context.Context, key string, value *http.Response) err
return err
}

err = d.Insert(ctx, key, cacheableResponse)
if value.Request != nil {
url = getFullUrl(value.Request)
}

err = d.Insert(ctx,
key,
cacheableResponse,
url,
)
if err != nil {
return err
}
Expand Down Expand Up @@ -221,7 +249,7 @@ func (d *DBCache) Clear(ctx context.Context) error {
}

// Insert data into the cache table.
func (d *DBCache) Insert(ctx context.Context, key string, value any) error {
func (d *DBCache) Insert(ctx context.Context, key string, value any, url string) error {
var (
bytes []byte
err error
Expand All @@ -247,10 +275,11 @@ func (d *DBCache) Insert(ctx context.Context, key string, value any) error {
return err
}

_, err = tx.Exec("INSERT INTO http_cache(key, data, expiration) values(?, ?, ?)",
_, err = tx.ExecContext(ctx, "INSERT INTO http_cache(key, data, expiration, url) values(?, ?, ?, ?)",
key,
bytes,
time.Now().UnixNano(),
url,
)
if err != nil {
if errtx := tx.Rollback(); errtx != nil {
Expand Down Expand Up @@ -309,7 +338,7 @@ func (d *DBCache) Select(ctx context.Context, key string) ([]byte, error) {
}

l := ctxzap.Extract(ctx)
rows, err := d.db.Query("SELECT data FROM http_cache where key = ?", key)
rows, err := d.db.QueryContext(ctx, "SELECT data FROM http_cache where key = ?", key)
if err != nil {
l.Debug(errQueryingTable, zap.Error(err))
return nil, err
Expand All @@ -333,32 +362,30 @@ func (d *DBCache) Remove(ctx context.Context, key string) error {
}

l := ctxzap.Extract(ctx)
if ok, _ := d.Has(ctx, key); ok {
tx, err := d.db.Begin()
if err != nil {
l.Debug(failStartTransaction, zap.Error(err))
return err
}

_, err = d.db.Exec("DELETE FROM http_cache WHERE key = ?", key)
if err != nil {
if errtx := tx.Rollback(); errtx != nil {
l.Debug(failRollback, zap.Error(errtx))
}
tx, err := d.db.Begin()
if err != nil {
l.Debug(failStartTransaction, zap.Error(err))
return err
}

l.Debug("error deleting key", zap.Error(err))
return err
_, err = d.db.ExecContext(ctx, "DELETE FROM http_cache WHERE key = ?", key)
if err != nil {
if errtx := tx.Rollback(); errtx != nil {
l.Debug(failRollback, zap.Error(errtx))
}

err = tx.Commit()
if err != nil {
if errtx := tx.Rollback(); errtx != nil {
l.Debug(failRollback, zap.Error(errtx))
}
l.Debug("error deleting key", zap.Error(err))
return err
}

l.Debug("Failed to remove cache value", zap.Error(err))
return err
err = tx.Commit()
if err != nil {
if errtx := tx.Rollback(); errtx != nil {
l.Debug(failRollback, zap.Error(errtx))
}

l.Debug("Failed to remove cache value", zap.Error(err))
return err
}

return nil
Expand Down Expand Up @@ -396,7 +423,7 @@ func (d *DBCache) DeleteExpired(ctx context.Context) error {
}

l := ctxzap.Extract(ctx)
rows, err := d.db.Query("SELECT key, expiration FROM http_cache")
rows, err := d.db.QueryContext(ctx, "SELECT key, expiration FROM http_cache")
if err != nil {
l.Debug(errQueryingTable, zap.Error(err))
return err
Expand Down Expand Up @@ -433,3 +460,116 @@ func (d *DBCache) DeleteExpired(ctx context.Context) error {

return nil
}

func getFullUrl(r *http.Request) string {
return fmt.Sprintf("%s://%s%s", r.URL.Scheme, r.Host, r.URL.Path)
}

func (d *DBCache) Hits(ctx context.Context, key string) error {
if d.IsNilConnection() {
return fmt.Errorf("%s", nilConnection)
}

strField := "hits"
err := d.Update(ctx, strField, key)
if err != nil {
return err
}

return nil
}

func (d *DBCache) DelHits(ctx context.Context, key string) error {
if d.IsNilConnection() {
return fmt.Errorf("%s", nilConnection)
}

strField := "delhits"
err := d.Update(ctx, strField, key)
if err != nil {
return err
}

return nil
}

func (d *DBCache) Misses(ctx context.Context, key string) error {
if d.IsNilConnection() {
return fmt.Errorf("%s", nilConnection)
}

strField := "misses"
err := d.Update(ctx, strField, key)
if err != nil {
return err
}

return nil
}

func (d *DBCache) DelMisses(ctx context.Context, key string) error {
if d.IsNilConnection() {
return fmt.Errorf("%s", nilConnection)
}

strField := "delmisses"
err := d.Update(ctx, strField, key)
if err != nil {
return err
}

return nil
}

func (d *DBCache) Collisions(ctx context.Context, key string) error {
if d.IsNilConnection() {
return fmt.Errorf("%s", nilConnection)
}

strField := "collisions"
err := d.Update(ctx, strField, key)
if err != nil {
return err
}

return nil
}

func (d *DBCache) Update(ctx context.Context, field, key string) error {
l := ctxzap.Extract(ctx)
tx, err := d.db.Begin()
if err != nil {
l.Debug(failStartTransaction, zap.Error(err))
return err
}

query, args := d.queryString(field)
_, err = d.db.ExecContext(ctx, fmt.Sprintf(query, args...), key)
if err != nil {
if errtx := tx.Rollback(); errtx != nil {
l.Debug(failRollback, zap.Error(errtx))
}

l.Debug("error updating "+field, zap.Error(err))
return err
}

err = tx.Commit()
if err != nil {
if errtx := tx.Rollback(); errtx != nil {
l.Debug(failRollback, zap.Error(errtx))
}

l.Debug("Failed to update "+field, zap.Error(err))
return err
}

return nil
}

func (d *DBCache) queryString(field string) (string, []interface{}) {
return staticQuery, []interface{}{
fmt.Sprint(field),
fmt.Sprint(field),
}
}
4 changes: 2 additions & 2 deletions pkg/uhttp/dbcache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@ func TestDBCache(t *testing.T) {
fc, err := getDBCacheForTesting()
require.Nil(t, err)

err = fc.Insert(ctx, "url", urlTest)
err = fc.Insert(ctx, "urlTest", urlTest, "http://example.com")
require.Nil(t, err)

res, err := fc.Select(ctx, "url")
res, err := fc.Select(ctx, "urlTest")
require.Nil(t, err)
require.NotNil(t, res)

Expand Down

0 comments on commit f6539ef

Please sign in to comment.