-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmodels.go
71 lines (61 loc) · 1.81 KB
/
models.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
package robinson
import "sync"
// Crusoe is single-value cache model.
type Crusoe[ValueType any] struct {
value ValueType
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]{}
}
// NewCrusoe creates new single-value cache item.
func NewCrusoe[ValueType any]() Crusoe[ValueType] {
return Crusoe[ValueType]{}
}
// 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)
}