-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathmodels.go
More file actions
98 lines (85 loc) · 2.24 KB
/
Copy pathmodels.go
File metadata and controls
98 lines (85 loc) · 2.24 KB
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
package robinson
import (
"sync"
"time"
)
// Crusoe is single-value cache model.
type Crusoe[ValueType any] struct {
value ValueType
options
me sync.RWMutex
}
// NewCrusoePointer creates new single-value cache item and return a pointer to the item.
func NewCrusoePointer[ValueType any]() *Crusoe[ValueType] {
return &Crusoe[ValueType]{}
}
type options = struct {
evictionTime time.Duration
doNotTouch bool
}
func WithEvict[ValueType any](ttl time.Duration) func(*options) {
return func(opts *options) {
opts.evictionTime = ttl
}
}
func WithDoNotTouch[ValueType any]() func(*options) {
return func(opts *options) {
opts.doNotTouch = true
}
}
// NewCrusoe creates new single-value cache item.
func NewCrusoe[ValueType any](optFns ...func(*options)) Crusoe[ValueType] {
opts := options{}
for _, fn := range optFns {
fn(&opts)
}
return Crusoe[ValueType]{
options: opts,
}
}
// Get returns current value from cache.
func (c *Crusoe[ValueType]) Get() ValueType {
c.me.RLock()
output := c.value
c.me.RUnlock()
return output
}
// Set sets value to cache.
func (c *Crusoe[ValueType]) Set(value ValueType) {
c.me.Lock()
c.value = value
c.me.Unlock()
}
// Call calls function with current value and using arbitrary processing in the function may set a new value to cache.
// It is possible to use this function to update cache value using an external source or whatever, the operation is atomic.
func (c *Crusoe[ValueType]) Call(f func(v ValueType) ValueType) {
if f != nil {
c.me.Lock()
defer c.me.Unlock()
c.value = f(c.value)
}
}
// CallWithError calls function with current value and allows error handling.
// The operation is atomic. If the function returns an error, the cache value is not updated.
func (c *Crusoe[ValueType]) CallWithError(f func(v ValueType) (ValueType, error)) error {
if f == nil {
return NewFunctionNotPassedError()
}
c.me.Lock()
defer c.me.Unlock()
newValue, err := f(c.value)
if err != nil {
return err
}
c.value = newValue
return nil
}
// Check calls function with current value and returns the result of the function without changing the cache value.
func (c *Crusoe[ValueType]) Check(f func(v ValueType) bool) bool {
if f == nil {
return false
}
c.me.RLock()
defer c.me.RUnlock()
return f(c.value)
}