Source File
caching.go
Belonging Package
golang.org/x/pkgsite/internal/middleware
package middleware
import (
icache
)
var (
keyCacheHit = tag.MustNewKey("cache.hit")
keyCacheName = tag.MustNewKey("cache.name")
keyCacheOperation = tag.MustNewKey("cache.operation")
cacheResults = stats.Int64(
"go-discovery/cache/result_count",
"The result of a cache request.",
stats.UnitDimensionless,
)
cacheLatency = stats.Float64(
"go-discovery/cache/result_latency",
"Cache serving latency latency",
stats.UnitMilliseconds,
)
cacheErrors = stats.Int64(
"go-discovery/cache/errors",
"Errors retrieving from cache.",
stats.UnitDimensionless,
)
CacheResultCount = &view.View{
Name: "go-discovery/cache/result_count",
Measure: cacheResults,
Aggregation: view.Count(),
Description: "cache results, by cache name and whether it was a hit",
TagKeys: []tag.Key{keyCacheName, keyCacheHit},
}
CacheLatency = &view.View{
Name: "go-discovery/cache/result_latency",
Measure: cacheLatency,
Description: "cache result latency, by cache name and whether it was a hit",
Aggregation: ochttp.DefaultLatencyDistribution,
TagKeys: []tag.Key{keyCacheName, keyCacheHit},
}
CacheErrorCount = &view.View{
Name: "go-discovery/cache/errors",
Measure: cacheErrors,
Aggregation: view.Count(),
Description: "cache errors, by cache name",
TagKeys: []tag.Key{keyCacheName, keyCacheOperation},
}
TestMode = false
)
func ( context.Context, string, bool, time.Duration) {
:= float64() / float64(time.Millisecond)
stats.RecordWithTags(, []tag.Mutator{
tag.Upsert(keyCacheName, ),
tag.Upsert(keyCacheHit, strconv.FormatBool()),
}, cacheResults.M(1), cacheLatency.M())
}
func ( context.Context, , string) {
stats.RecordWithTags(, []tag.Mutator{
tag.Upsert(keyCacheName, ),
tag.Upsert(keyCacheOperation, ),
}, cacheErrors.M(1))
}
type cache struct {
name string
authValues []string
cache *icache.Cache
delegate http.Handler
expirer Expirer
}
:= .Header.Get(config.BypassCacheAuthHeader)
for , := range .authValues {
if == {
.delegate.ServeHTTP(, )
return
}
if , := .Cookie(cookie.AlternativeModuleFlash); == nil {
.delegate.ServeHTTP(, )
return
}
:= .Context()
:= .URL.String()
:= time.Now()
, := .get(, )
recordCacheResult(, .name, , time.Since())
if {
if , := io.Copy(, ); != nil {
log.Errorf(, "error copying zip bytes: %v", )
}
return
}
:= newRecorder()
.delegate.ServeHTTP(, )
if .bufErr == nil && (.statusCode == 0 || .statusCode == http.StatusOK) {
:= .expirer()
if TestMode {
.put(, , , )
} else {
go .put(, , , )
}
}
}
, := context.WithTimeout(, 100*time.Millisecond)
defer ()
, := .cache.Get(, )
if != nil {
select {
case <-.Done():
log.Infof(, "cache get(%q): context timed out", )
default:
log.Infof(, "cache get(%q): %v", , )
}
recordCacheError(, .name, "GET")
return nil, false
}
if == nil {
return nil, false
}
, := gzip.NewReader(bytes.NewReader())
if != nil {
log.Errorf(, "cache: gzip.NewReader: %v", )
recordCacheError(, .name, "UNZIP")
return nil, false
}
return , true
}
func ( *cache) ( context.Context, string, *cacheRecorder, time.Duration) {
if := .zipWriter.Close(); != nil {
log.Errorf(, "cache: error closing zip for %q: %v", , )
return
}
log.Infof(, "caching response of length %d for %s", .buf.Len(), )
, := context.WithTimeout(context.Background(), 1*time.Second)
defer ()
if := .cache.Put(, , .buf.Bytes(), ); != nil {
recordCacheError(, .name, "SET")
log.Warningf(, "cache set %q: %v", , )
}
}
func ( http.ResponseWriter) *cacheRecorder {
:= &bytes.Buffer{}
:= gzip.NewWriter()
return &cacheRecorder{ResponseWriter: , buf: , zipWriter: }
}
type cacheRecorder struct {
http.ResponseWriter
statusCode int
bufErr error
buf *bytes.Buffer
zipWriter *gzip.Writer
}
func ( *cacheRecorder) ( []byte) (int, error) {
.statusCode =
}
.ResponseWriter.WriteHeader()
![]() |
The pages are generated with Golds v0.3.2-preview. (GOOS=darwin GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds. |