File: err_cacher.go

package info (click to toggle)
gitlab-agent 16.1.3-2
  • links: PTS, VCS
  • area: contrib
  • in suites: forky, sid, trixie
  • size: 6,324 kB
  • sloc: makefile: 175; sh: 52; ruby: 3
file content (58 lines) | stat: -rw-r--r-- 1,786 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
package redistool

import (
	"context"
	"time"

	"github.com/redis/rueidis"
	"gitlab.com/gitlab-org/cluster-integration/gitlab-agent/v16/internal/tool/errz"
	"go.uber.org/zap"
)

type ErrMarshaler interface {
	// Marshal turns error into []byte.
	Marshal(error) ([]byte, error)
	// Unmarshal turns []byte into error.
	Unmarshal([]byte) (error, error)
}

type ErrCacher[K any] struct {
	Log           *zap.Logger
	ErrRep        errz.ErrReporter
	Client        rueidis.Client
	ErrMarshaler  ErrMarshaler
	KeyToRedisKey KeyToRedisKey[K]
}

func (c *ErrCacher[K]) GetError(ctx context.Context, key K) error {
	getCmd := c.Client.B().Get().Key(c.KeyToRedisKey(key)).Build()
	result, err := c.Client.Do(ctx, getCmd).ToString() // TODO use AsBytes() when have updated to Go 1.20
	if err != nil {
		if err != rueidis.Nil { // nolint:errorlint
			c.ErrRep.HandleProcessingError(ctx, c.Log, "Failed to get cached error from Redis", err)
		}
		return nil // Returns nil according to the interface contract.
	}
	if len(result) == 0 {
		return nil
	}
	e, err := c.ErrMarshaler.Unmarshal([]byte(result))
	if err != nil {
		c.ErrRep.HandleProcessingError(ctx, c.Log, "Failed to unmarshal cached error", err)
		return nil // Returns nil according to the interface contract.
	}
	return e
}

func (c *ErrCacher[K]) CacheError(ctx context.Context, key K, err error, errTtl time.Duration) {
	data, err := c.ErrMarshaler.Marshal(err)
	if err != nil {
		c.ErrRep.HandleProcessingError(ctx, c.Log, "Failed to marshal error for caching", err)
		return
	}
	setCmd := c.Client.B().Set().Key(c.KeyToRedisKey(key)).Value(rueidis.BinaryString(data)).Px(errTtl).Build()
	err = c.Client.Do(ctx, setCmd).Error()
	if err != nil {
		c.ErrRep.HandleProcessingError(ctx, c.Log, "Failed to cache error in Redis", err)
	}
}