-
Notifications
You must be signed in to change notification settings - Fork 9
/
protocache.go
75 lines (59 loc) · 1.86 KB
/
protocache.go
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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
// Copyright 2022 Namespace Labs Inc; All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
package compute
import (
"context"
"reflect"
"google.golang.org/protobuf/proto"
"namespacelabs.dev/foundation/internal/compute/cache"
"namespacelabs.dev/foundation/internal/fnerrors"
"namespacelabs.dev/foundation/schema"
)
func RegisterProtoCacheable() {
RegisterCacheable[proto.Message](protoCacheable{})
}
type protoCacheable struct{}
func (protoCacheable) ComputeDigest(ctx context.Context, v interface{}) (schema.Digest, error) {
_, h, err := marshalProto(v.(proto.Message))
if err != nil {
return schema.Digest{}, err
}
return h, nil
}
func (protoCacheable) LoadCached(ctx context.Context, c cache.Cache, t CacheableInstance, h schema.Digest) (Result[proto.Message], error) {
raw := t.NewInstance()
msg, ok := raw.(proto.Message)
if !ok {
return Result[proto.Message]{}, fnerrors.InternalError("expected %q to be a ptr to a proto.Message", reflect.TypeOf(raw))
}
bytes, err := c.Bytes(ctx, h)
if err != nil {
return Result[proto.Message]{}, err
}
if err := proto.Unmarshal(bytes, msg); err != nil {
return Result[proto.Message]{}, err
}
return Result[proto.Message]{
Digest: h,
Value: msg,
}, nil
}
func (protoCacheable) Cache(ctx context.Context, c cache.Cache, msg proto.Message) (schema.Digest, error) {
bytes, h, err := marshalProto(msg)
if err != nil {
return schema.Digest{}, err
}
if err := c.WriteBytes(ctx, h, bytes); err != nil {
return schema.Digest{}, err
}
return h, err
}
func marshalProto(msg proto.Message) ([]byte, schema.Digest, error) {
bytes, err := (proto.MarshalOptions{Deterministic: true}).Marshal(msg)
if err != nil {
return nil, schema.Digest{}, err
}
h, err := cache.DigestBytes(bytes)
return bytes, h, err
}