| // Copyright 2020 The LUCI Authors. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| package redisconn |
| |
| import ( |
| "context" |
| "time" |
| |
| "github.com/gomodule/redigo/redis" |
| |
| "go.chromium.org/luci/common/trace" |
| "go.chromium.org/luci/server/caching" |
| ) |
| |
| // redisBlobCache implements caching.BlobCache using Redis. |
| type redisBlobCache struct { |
| Prefix string // prefix to prepend to keys |
| } |
| |
| var _ caching.BlobCache = (*redisBlobCache)(nil) |
| |
| func (rc *redisBlobCache) key(k string) string { return rc.Prefix + k } |
| |
| // Get returns a cached item or ErrCacheMiss if it's not in the cache. |
| func (rc *redisBlobCache) Get(ctx context.Context, key string) (blob []byte, err error) { |
| ctx, span := trace.StartSpan(ctx, "go.chromium.org/luci/server.RedisBlobCache.Get") |
| defer func() { span.End(err) }() |
| |
| conn, err := Get(ctx) |
| if err != nil { |
| return nil, err |
| } |
| defer conn.Close() |
| |
| blob, err = redis.Bytes(conn.Do("GET", rc.key(key))) |
| if err == redis.ErrNil { |
| return nil, caching.ErrCacheMiss |
| } |
| return blob, err |
| } |
| |
| // Set unconditionally overwrites an item in the cache. |
| // |
| // If 'exp' is zero, the item will have no expiration time. |
| func (rc *redisBlobCache) Set(ctx context.Context, key string, value []byte, exp time.Duration) (err error) { |
| ctx, span := trace.StartSpan(ctx, "go.chromium.org/luci/server.RedisBlobCache.Set") |
| defer func() { span.End(err) }() |
| |
| conn, err := Get(ctx) |
| if err != nil { |
| return err |
| } |
| defer conn.Close() |
| |
| if exp == 0 { |
| _, err = conn.Do("SET", rc.key(key), value) |
| } else { |
| _, err = conn.Do("PSETEX", rc.key(key), exp.Nanoseconds()/1e6, value) |
| } |
| return err |
| } |