Skip to content

Commit a57047f

Browse files
committed
replace in-memory cache with size-limited lrucache
Fixes #4
1 parent db55cb6 commit a57047f

2 files changed

Lines changed: 33 additions & 4 deletions

File tree

README.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,11 @@ you should see a 500px square coder octocat.
9494
By default, the imageproxy command does not cache responses, but caching can be
9595
enabled using the `-cache` flag. It supports the following values:
9696

97-
- `memory` - uses an in-memory cache. (This can exhaust your system's
98-
available memory and is not recommended for production systems)
97+
- `memory` - uses an in-memory LRU cache. By default, this is limited to
98+
100mb. To customize the size of the cache or the max age for cached items,
99+
use the format `memory:size:age` where size is measured in mb and age is a
100+
duration. For example, `memory:200:4h` will create a 200mb cache that will
101+
cache items no longer than 4 hours.
99102
- directory on local disk (e.g. `/tmp/imageproxy`) - will cache images
100103
on disk
101104
- s3 URL (e.g. `s3://region/bucket-name/optional-path-prefix`) - will cache

cmd/imageproxy/main.go

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,23 @@ import (
2323
"net/http"
2424
"net/url"
2525
"os"
26+
"strconv"
2627
"strings"
28+
"time"
2729

2830
"github.com/PaulARoy/azurestoragecache"
31+
"github.com/die-net/lrucache"
2932
"github.com/diegomarangoni/gcscache"
3033
"github.com/garyburd/redigo/redis"
31-
"github.com/gregjones/httpcache"
3234
"github.com/gregjones/httpcache/diskcache"
3335
rediscache "github.com/gregjones/httpcache/redis"
3436
"github.com/peterbourgon/diskv"
3537
"willnorris.com/go/imageproxy"
3638
"willnorris.com/go/imageproxy/internal/s3cache"
3739
)
3840

41+
const defaultMemorySize = 100
42+
3943
var addr = flag.String("addr", "localhost:8080", "TCP address to listen on")
4044
var whitelist = flag.String("whitelist", "", "comma separated list of allowed remote hosts")
4145
var referrers = flag.String("referrers", "", "comma separated list of allowed referring hosts")
@@ -102,7 +106,7 @@ func parseCache() (imageproxy.Cache, error) {
102106
}
103107

104108
if *cache == "memory" {
105-
return httpcache.NewMemoryCache(), nil
109+
*cache = fmt.Sprintf("memory:%d", defaultMemorySize)
106110
}
107111

108112
u, err := url.Parse(*cache)
@@ -115,6 +119,8 @@ func parseCache() (imageproxy.Cache, error) {
115119
return azurestoragecache.New("", "", u.Host)
116120
case "gcs":
117121
return gcscache.New(u.String()), nil
122+
case "memory":
123+
return lruCache(u.Opaque)
118124
case "redis":
119125
conn, err := redis.DialURL(u.String(), redis.DialPassword(os.Getenv("REDIS_PASSWORD")))
120126
if err != nil {
@@ -130,6 +136,26 @@ func parseCache() (imageproxy.Cache, error) {
130136
}
131137
}
132138

139+
// lruCache creates an LRU Cache with the specified options of the form
140+
// "maxSize:maxAge". maxSize is specified in megabytes, maxAge is a duration.
141+
func lruCache(options string) (*lrucache.LruCache, error) {
142+
parts := strings.SplitN(options, ":", 2)
143+
size, err := strconv.ParseInt(parts[0], 10, 64)
144+
if err != nil {
145+
return nil, err
146+
}
147+
148+
var age time.Duration
149+
if len(parts) > 1 {
150+
age, err = time.ParseDuration(parts[1])
151+
if err != nil {
152+
return nil, err
153+
}
154+
}
155+
156+
return lrucache.New(size*1e6, int64(age.Seconds())), nil
157+
}
158+
133159
func diskCache(path string) *diskcache.Cache {
134160
d := diskv.New(diskv.Options{
135161
BasePath: path,

0 commit comments

Comments
 (0)