예제 #1
0
파일: redis.go 프로젝트: app-kit/go-appkit
// Save a new item into the cache.
func (r *Redis) Set(item kit.CacheItem) Error {
	key := item.GetKey()
	if key == "" {
		return kit.AppError{Code: "empty_key"}
	}
	key = r.key(key)

	if item.IsExpired() {
		return kit.AppError{Code: "item_expired"}
	}

	expireSeconds := 0
	if expires := item.GetExpiresAt(); !expires.IsZero() {
		seconds := expires.Sub(time.Now()).Seconds()
		if seconds > 0 && seconds < 1 {
			return kit.AppError{Code: "item_expired"}
		}
		expireSeconds = int(seconds)
	}

	conn := r.pool.Get()
	defer conn.Close()

	value, err := item.ToString()
	if err != nil {
		return kit.AppError{
			Code:    "cacheitem_tostring_error",
			Message: err.Error(),
			Errors:  []error{err},
		}
	}
	if value == "" {
		return kit.AppError{Code: "empty_value"}
	}

	conn.Send("SET", key, value)
	if expireSeconds > 0 {
		conn.Send("EXPIRE", key, expireSeconds)
	}

	if tags := item.GetTags(); tags != nil {
		tagKey := r.tagKey(key)
		conn.Send("SET", tagKey, strings.Join(tags, ";"))
		if expireSeconds > 0 {
			conn.Send("EXPIRE", tagKey, expireSeconds)
		}
	}

	if err := conn.Flush(); err != nil {
		return redisErr(err)
	}

	return nil
}
예제 #2
0
파일: fs.go 프로젝트: app-kit/go-appkit
// Retrieve a cache item from the cache.
func (fs *Fs) Get(key string, items ...kit.CacheItem) (kit.CacheItem, apperror.Error) {
	var item kit.CacheItem = &StrItem{}
	if items != nil {
		if len(items) != 1 {
			return nil, &apperror.Err{
				Code:    "invalid_item",
				Message: "You must specify one item only",
			}
		}
		item = items[0]
	}

	key = fs.key(key)
	if key == "" {
		return nil, apperror.New("empty_key")
	}

	exists, err := utils.FileExists(fs.keyPath(key))
	if err != nil {
		return nil, err
	}

	if !exists {
		return nil, nil
	}

	metaContent, err := utils.ReadFile(fs.keyMetaPath(key))
	if err != nil {
		return nil, err
	}
	if err := json.Unmarshal(metaContent, &item); err != nil {
		return nil, apperror.Wrap(err, "metadata_unmarshal_error")
	}

	// Reset ExpiresAt if it is zero, since json.Unmarshal produces
	// a time.Time which is not exactly equal to the zero value.
	if item.GetExpiresAt().IsZero() {
		item.SetExpiresAt(time.Time{})
	}

	content, err := utils.ReadFile(fs.keyPath(key))
	if err != nil {
		return nil, err
	}

	if err := item.FromString(string(content)); err != nil {
		return nil, apperror.Wrap(err, "cacheitem_fromstring_error")
	}

	// Return nil if item is expired.
	if item.IsExpired() {
		return nil, nil
	}

	return item, nil
}
예제 #3
0
파일: fs.go 프로젝트: app-kit/go-appkit
// Save a new item into the cache.
func (fs *Fs) Set(item kit.CacheItem) apperror.Error {
	key := fs.key(item.GetKey())
	if key == "" {
		return apperror.New("empty_key")
	}

	if item.IsExpired() {
		return apperror.New("item_expired")
	}

	value, err := item.ToString()
	if err != nil {
		return apperror.Wrap(err, "cacheitem_tostring_error")
	}
	if value == "" {
		return apperror.New("empty_value")
	}

	// Marshal metadata.
	tmpVal := item.GetValue()
	item.SetValue(nil)

	js, err2 := json.Marshal(item)
	if err2 != nil {
		return apperror.Wrap(err2, "json_marshal_error")
	}
	item.SetValue(tmpVal)

	if err := utils.WriteFile(fs.keyPath(key), []byte(value), false); err != nil {
		return err
	}
	if err := utils.WriteFile(fs.keyMetaPath(key), js, false); err != nil {
		return err
	}

	return nil
}
예제 #4
0
파일: redis.go 프로젝트: app-kit/go-appkit
// Retrieve a cache item from the cache.
func (r *Redis) Get(key string, items ...kit.CacheItem) (kit.CacheItem, Error) {
	var item kit.CacheItem = &StrItem{}
	if items != nil {
		if len(items) != 1 {
			return nil, kit.AppError{
				Code:     "invalid_item",
				Message:  "You must specify one item only",
				Internal: true,
			}
		}
		item = items[0]
	}

	if key == "" {
		return nil, kit.AppError{Code: "empty_key"}
	}
	item.SetKey(key)
	key = r.key(key)

	conn := r.pool.Get()
	defer conn.Close()

	result, err := redis.Strings(conn.Do("MGET", key, r.tagKey(key)))
	if err != nil {
		return nil, redisErr(err)
	}

	// Retrieve the value.
	if result[0] == "" {
		return nil, nil
	}
	if err := item.FromString(result[0]); err != nil {
		return nil, kit.AppError{
			Code:    "cacheitem_fromstring_error",
			Message: err.Error(),
			Errors:  []error{err},
		}
	}

	// Parse and set tags.
	if result[1] != "" {
		item.SetTags(strings.Split(result[1], ";"))
	}

	// Now get the ttl.
	ttl, err := redis.Int(conn.Do("TTL", key))
	if err == nil && ttl > 0 {
		expires := time.Now().Add(time.Duration(ttl) * time.Second)
		item.SetExpiresAt(expires)
	} else if err != nil && err != redis.ErrNil {
		return nil, redisErr(err)
	}

	// Return nil if item is expired.
	if item.IsExpired() {
		return nil, nil
	}

	return item, nil
}