Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b698d1bdc0 | |||
| 8d9bc1c422 |
@@ -30,6 +30,15 @@ func (db *DB) GetOverviewStats(ctx context.Context) (*models.OverviewStats, erro
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = db.Pool.QueryRow(ctx, `
|
||||||
|
SELECT COALESCE(SUM(size_bytes), 0)
|
||||||
|
FROM access_log
|
||||||
|
WHERE cache_hit = TRUE AND created_at > NOW() - INTERVAL '30 days'
|
||||||
|
`).Scan(&stats.BandwidthSaved30d)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return &stats, nil
|
return &stats, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package proxy
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"git.unkin.net/unkin/artifactapi/internal/provider"
|
"git.unkin.net/unkin/artifactapi/internal/provider"
|
||||||
"git.unkin.net/unkin/artifactapi/pkg/models"
|
"git.unkin.net/unkin/artifactapi/pkg/models"
|
||||||
@@ -60,10 +61,29 @@ func (c *Classifier) Classify(remote models.Remote, path string) Classification
|
|||||||
return ClassImmutable
|
return ClassImmutable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// patternCache memoises regex compilation. Classify runs on every proxied
|
||||||
|
// request and previously recompiled each remote's pattern lists every time;
|
||||||
|
// keying by the pattern string lets each distinct pattern compile once and
|
||||||
|
// then be reused, with no invalidation needed (the pattern text is the key).
|
||||||
|
// A pattern that fails to compile is cached as a typed nil so we don't retry.
|
||||||
|
var patternCache sync.Map // map[string]*regexp.Regexp
|
||||||
|
|
||||||
|
func compileCached(pattern string) *regexp.Regexp {
|
||||||
|
if v, ok := patternCache.Load(pattern); ok {
|
||||||
|
return v.(*regexp.Regexp)
|
||||||
|
}
|
||||||
|
re, err := regexp.Compile(pattern)
|
||||||
|
if err != nil {
|
||||||
|
re = nil
|
||||||
|
}
|
||||||
|
patternCache.Store(pattern, re)
|
||||||
|
return re
|
||||||
|
}
|
||||||
|
|
||||||
func compilePatterns(patterns []string) []*regexp.Regexp {
|
func compilePatterns(patterns []string) []*regexp.Regexp {
|
||||||
compiled := make([]*regexp.Regexp, 0, len(patterns))
|
compiled := make([]*regexp.Regexp, 0, len(patterns))
|
||||||
for _, p := range patterns {
|
for _, p := range patterns {
|
||||||
if re, err := regexp.Compile(p); err == nil {
|
if re := compileCached(p); re != nil {
|
||||||
compiled = append(compiled, re)
|
compiled = append(compiled, re)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,6 +50,11 @@ export function Dashboard() {
|
|||||||
value={formatNumber(stats.total_blobs_deduped)}
|
value={formatNumber(stats.total_blobs_deduped)}
|
||||||
sub="shared blobs"
|
sub="shared blobs"
|
||||||
/>
|
/>
|
||||||
|
<StatsCard
|
||||||
|
label="Bandwidth Saved"
|
||||||
|
value={formatBytes(stats.bandwidth_saved_30d)}
|
||||||
|
sub="last 30 days"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{health && (
|
{health && (
|
||||||
|
|||||||
Reference in New Issue
Block a user