Last active
October 14, 2015 19:46
-
-
Save joshrotenberg/e9d0274f3dc9b79353cd to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package groupcache_expire | |
| import ( | |
| "log" | |
| "strings" | |
| "time" | |
| "github.com/golang/groupcache" | |
| ) | |
| // this is the format that we'll use to prefix our keys | |
| const prefixFormat = "15:04:05" | |
| // wrap up some of the details of cache creation | |
| type Cache struct { | |
| cacheGroup *groupcache.Group | |
| peers *groupcache.HTTPPool | |
| expiration time.Duration | |
| } | |
| // this is really the root of how we handle expiration. you can probably | |
| // think of ten other ways to do it, but Go's time.Truncate() comes | |
| // in really handy if you want to set an explicit TTL style expiration. | |
| func stampKey(key string, expiration time.Duration) string { | |
| tf := time.Now().Truncate(expiration).Format(prefixFormat) | |
| tn := time.Now().Format(prefixFormat) | |
| log.Println(tf, tn) | |
| return strings.Join([]string{tf, key}, "-") | |
| } | |
| func unstampKey(key string) string { | |
| parts := strings.Split(key, "-") | |
| return parts[1] | |
| } | |
| func getter(ctx groupcache.Context, key string, dest groupcache.Sink) error { | |
| log.Printf("key %s not found (stamped: %s)", unstampKey(key), key) | |
| dest.SetString(fakeDb[unstampKey(key)]) | |
| return nil | |
| } | |
| func NewCache(name string, url string, expiration time.Duration, size int64) *Cache { | |
| peers := groupcache.NewHTTPPool(url) | |
| var stringcache = groupcache.NewGroup(name, size, groupcache.GetterFunc(getter)) | |
| return &Cache{ | |
| cacheGroup: stringcache, | |
| peers: peers, | |
| expiration: expiration, | |
| } | |
| } | |
| func (mc Cache) Stats() groupcache.CacheStats { | |
| return mc.cacheGroup.CacheStats(groupcache.MainCache) | |
| } | |
| func (mc Cache) Get(key string) string { | |
| var data string | |
| stampedKey := stampKey(key, mc.expiration) | |
| err := mc.cacheGroup.Get(nil, stampedKey, groupcache.StringSink(&data)) | |
| if err != nil { | |
| panic(err) | |
| } | |
| return data | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package groupcache_expire | |
| import ( | |
| "log" | |
| "testing" | |
| "time" | |
| ) | |
| var ( | |
| // our handy in memory fake NoSQL key value store that holds | |
| // a mapping of english to czech numbers 0-5. | |
| fakeDb = map[string]string{ | |
| "zero": "nula", | |
| "one": "jeden", | |
| "two": "dva", | |
| "three": "tři", | |
| "four": "čtyři", | |
| "five": "pět", | |
| } | |
| ) | |
| func TestExpire(t *testing.T) { | |
| // if we were running groupcache for real and i was demonstrating | |
| // the distributed nature, this would matter more. | |
| url := "http://localhost:8282" | |
| maxAge := time.Duration(10 * time.Second) | |
| // create a new cache and give it plenty of space | |
| // so we know our misses are caused by key expiration and not | |
| // eviction. | |
| c := NewCache("mycache", url, maxAge, 4096) | |
| for i := 0; i < 10; i++ { | |
| for k, _ := range fakeDb { | |
| c.Get(k) | |
| } | |
| stats := c.Stats() | |
| log.Printf("Items: %d, Gets: %d, Hits: %d", | |
| stats.Items, stats.Gets, stats.Hits) | |
| time.Sleep(1 * time.Second) | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment