1
0
mirror of https://github.com/kataras/iris.git synced 2026-01-09 21:15:56 +00:00

Nothing special here, remote cache is not ready yet

Remote Cache is not inside docs or history because it's not ready for
production yet, however it seems to works fine, but until I test it on
more than 2kk requests I will not add this on history or docs. The
upcoming 24 hours I will upload a relative package which will combine
all cache features to one
This commit is contained in:
Gerasimos Maropoulos
2016-10-28 21:55:00 +03:00
parent 3243432d48
commit 6f22da7622
3 changed files with 30 additions and 38 deletions

View File

@@ -71,7 +71,6 @@ func (cs *cacheService) start() {
now := time.Now()
for k, v := range cs.cache {
if now.After(v.expires) {
println("remove cache")
delete(cs.cache, k)
}
}
@@ -84,7 +83,7 @@ func (cs *cacheService) start() {
func (cs *cacheService) get(key string) *cacheEntry {
cs.mu.RLock()
if v, ok := cs.cache[key]; ok {
if v, ok := cs.cache[key]; ok && time.Now().Before(v.expires) { // we check for expiration, the gc clears the cache but gc maybe late
cs.mu.RUnlock()
return v
}
@@ -199,13 +198,8 @@ func getResponseStatusCode(ctx *Context) int {
func (cs *cacheService) Cache(bodyHandler HandlerFunc, expiration time.Duration) HandlerFunc {
expiration = validateCacheDuration(expiration)
if cs.gcDuration == -1 {
// if gc duration is not setted yet or this is the only one Cache which happens to have bigger expiration than the minimumAllowedCacheDuration
// then set that as the gcDuration
cs.gcDuration = expiration // the first time the lowerExpiration should be > minimumAllowedCacheDuration so:
} else if expiration < cs.gcDuration { // find the lower
// if this expiration is lower than the already setted, set the gcDuration to this
cs.gcDuration = expiration
if cs.gcDuration == -1 || expiration < cs.gcDuration {
cs.gcDuration = expiration // the first time the gcDuration should be > minimumAllowedCacheDuration so:
}
h := func(ctx *Context) {
@@ -245,6 +239,9 @@ const (
queryCacheDuration = "cache_duration"
queryCacheStatusCode = "cache_status_code"
queryCacheContentType = "cache_content_type"
requestCacheTimeout = 5 * time.Second
statusCacheSucceed = StatusOK
statusCacheFailed = StatusBadRequest
)
// RemoteCache accepts the remote server address and path of the external cache service, the body handler and optional an expiration
@@ -262,25 +259,25 @@ func RemoteCache(cacheServerAddr string, bodyHandler HandlerFunc, expiration tim
req := fasthttp.AcquireRequest()
req.SetRequestURI(cacheServerAddr)
req.Header.SetMethodBytes(MethodGetBytes)
req.URI().QueryArgs().Add("cache_key", GetRemoteCacheKey(ctx))
req.URI().QueryArgs().Add(queryCacheKey, GetRemoteCacheKey(ctx))
res := fasthttp.AcquireResponse()
err := client.DoTimeout(req, res, time.Duration(5)*time.Second)
if err != nil || res.StatusCode() == StatusBadRequest {
err := client.DoTimeout(req, res, requestCacheTimeout)
if err != nil || res.StatusCode() == statusCacheFailed {
// if not found on cache, then execute the handler and save the cache to the remote server
bodyHandler.Serve(ctx)
// save to the remote cache
req.Header.SetMethodBytes(MethodPostBytes)
req.URI().QueryArgs().Add("cache_duration", cacheDurationStr)
args := req.URI().QueryArgs()
args.Add(queryCacheDuration, cacheDurationStr)
statusCode := strconv.Itoa(ctx.Response.StatusCode())
req.URI().QueryArgs().Add("cache_status_code", statusCode)
args.Add(queryCacheStatusCode, statusCode)
cType := string(ctx.Response.Header.Peek(contentType))
req.URI().QueryArgs().Add("cache_content_type", cType)
args.Add(queryCacheContentType, cType)
req.SetBody(ctx.Response.Body())
go func() {
client.DoTimeout(req, res, time.Duration(5)*time.Second)
client.DoTimeout(req, res, requestCacheTimeout)
fasthttp.ReleaseRequest(req)
fasthttp.ReleaseResponse(res)
}()
@@ -332,11 +329,11 @@ func ServeRemoteCache(gcDuration time.Duration) HandlerFunc {
// use the app.ServeRemoteCache instead of iris.ServeRemoteCache
func (cs *cacheService) ServeRemoteCache(gcDuration time.Duration) HandlerFunc {
cs.gcDuration = validateCacheDuration(gcDuration)
// the service started at pre-listen state(on .Build) if gcDuration > 0
h := func(ctx *Context) {
key := ctx.URLParam("cache_key")
key := ctx.URLParam(queryCacheKey)
if key == "" {
ctx.SetStatusCode(StatusBadRequest)
ctx.SetStatusCode(statusCacheFailed)
return
}
@@ -347,11 +344,11 @@ func (cs *cacheService) ServeRemoteCache(gcDuration time.Duration) HandlerFunc {
}
} else if ctx.IsPost() {
// get the cache expiration via url param
expirationSeconds, err := ctx.URLParamInt64("cache_duration")
expirationSeconds, err := ctx.URLParamInt64(queryCacheDuration)
// get the body from the requested body
body := ctx.Request.Body()
if len(body) == 0 {
ctx.SetStatusCode(StatusBadRequest)
ctx.SetStatusCode(statusCacheFailed)
return
}
@@ -365,27 +362,22 @@ func (cs *cacheService) ServeRemoteCache(gcDuration time.Duration) HandlerFunc {
expirationSeconds = int64(minimumAllowedCacheDuration.Seconds())
}
cacheDuration := time.Duration(expirationSeconds) * time.Second
statusCode, err := ctx.URLParamInt("cache_status_code")
if err != nil {
statusCode = StatusOK
}
cType := ctx.URLParam("cache_content_type")
if cType == "" {
cType = contentHTML
}
cacheDuration := validateCacheDuration(time.Duration(expirationSeconds) * time.Second)
statusCode, _ := ctx.URLParamInt(queryCacheDuration)
statusCode = validateStatusCode(statusCode)
cType := validateContentType(ctx.URLParam(queryCacheContentType))
cs.set(key, statusCode, cType, body, cacheDuration)
ctx.SetStatusCode(StatusOK)
ctx.SetStatusCode(statusCacheSucceed)
return
} else if ctx.IsDelete() {
cs.remove(key)
ctx.SetStatusCode(StatusOK)
ctx.SetStatusCode(statusCacheSucceed)
return
}
ctx.SetStatusCode(StatusBadRequest)
ctx.SetStatusCode(statusCacheFailed)
}
return h

View File

@@ -1207,7 +1207,7 @@ func CERT(addr string, cert tls.Certificate) (net.Listener, error) {
// LETSENCRYPT returns a new Automatic TLS Listener using letsencrypt.org service
// receives two parameters, the first is the domain of the server
// and the second is optionally, the cache file, if you skip it then the cache directory is "./letsencrypt.cache"
// if you want to disable cache file then simple give it a value of emtpy string ""
// if you want to disable cache file then simple give it a value of empty string ""
//
// supports localhost domains for testing,
// but I recommend you to use the LETSENCRYPTPROD if you gonna to use it on production
@@ -1243,7 +1243,7 @@ func LETSENCRYPT(addr string, cacheFileOptional ...string) (net.Listener, error)
// LETSENCRYPTPROD returns a new Automatic TLS Listener using letsencrypt.org service
// receives two parameters, the first is the domain of the server
// and the second is optionally, the cache directory, if you skip it then the cache directory is "./certcache"
// if you want to disable cache directory then simple give it a value of emtpy string ""
// if you want to disable cache directory then simple give it a value of empty string ""
//
// does NOT supports localhost domains for testing, use LETSENCRYPT instead.
//

View File

@@ -553,7 +553,7 @@ func (s *Framework) ListenTLS(addr string, certFile, keyFile string) {
// it's also starts a second 'http' server to redirect all 'http://$ADDR_HOSTNAME:80' to the' https://$ADDR'
// it creates a cache file to store the certifications, for performance reasons, this file by-default is "./letsencrypt.cache"
// if you skip the second parameter then the cache file is "./letsencrypt.cache"
// if you want to disable cache then simple pass as second argument an empty emtpy string ""
// if you want to disable cache then simple pass as second argument an empty empty string ""
//
// example: https://github.com/iris-contrib/examples/blob/master/letsencyrpt/main.go
//
@@ -568,7 +568,7 @@ func ListenLETSENCRYPT(addr string, cacheFileOptional ...string) {
// it's also starts a second 'http' server to redirect all 'http://$ADDR_HOSTNAME:80' to the' https://$ADDR'
// it creates a cache file to store the certifications, for performance reasons, this file by-default is "./letsencrypt.cache"
// if you skip the second parameter then the cache file is "./letsencrypt.cache"
// if you want to disable cache then simple pass as second argument an empty emtpy string ""
// if you want to disable cache then simple pass as second argument an empty empty string ""
//
// example: https://github.com/iris-contrib/examples/blob/master/letsencyrpt/main.go
//