volatile/volatile.go (view raw)
1package volatile
2
3import (
4 "fmt"
5 "time"
6
7 "github.com/sirupsen/logrus"
8)
9
10var logger = logrus.New()
11
12type Element[K comparable, V any] struct {
13 key K
14 value *V
15 Timestamp time.Time
16}
17
18type Volatile[K comparable, V any] struct {
19 data []Element[K, V]
20 timeToLive time.Duration
21}
22
23func reverseIntArray(arr []int) {
24 length := len(arr)
25 for i := 0; i < length/2; i++ {
26 arr[i], arr[length-i-1] = arr[length-i-1], arr[i]
27 }
28}
29
30func NewVolatile[K comparable, V any](timeToLive time.Duration) *Volatile[K, V] {
31 return &Volatile[K, V]{
32 data: nil,
33 timeToLive: timeToLive,
34 }
35}
36
37func (v *Volatile[K, V]) removeIndex(index int) error {
38 if index < 0 || index >= len(v.data) {
39 return fmt.Errorf("Index out of bounds")
40 }
41 v.data = append(v.data[:index], v.data[index+1:]...)
42 return nil
43}
44
45func (v *Volatile[K, V]) clean() error {
46 now := time.Now()
47
48 for i := len(v.data) - 1; i >= 0; i-- {
49 if now.Sub(v.data[i].Timestamp) > v.timeToLive {
50 err := v.removeIndex(i)
51 if err != nil {
52 return err
53 }
54 }
55 }
56 return nil
57}
58
59func (v *Volatile[K, V]) indexOf(key K) int {
60 for i := range v.data {
61 e := v.data[i]
62 if e.key == key {
63 return i
64 }
65 }
66 return -1
67}
68
69func (v *Volatile[K, V]) Has(key K) bool {
70 err := v.clean()
71 if err != nil {
72 logger.Println(err)
73 return false
74 }
75 return v.indexOf(key) != -1
76}
77
78func (v *Volatile[K, V]) Get(key K) (*V, error) {
79 err := v.clean()
80 if err != nil {
81 logger.Println(err)
82 return nil, err
83 }
84
85 i := v.indexOf(key)
86 if i == -1 {
87 return nil, fmt.Errorf("Not found")
88 }
89 return v.data[i].value, nil
90}
91
92func (v *Volatile[K, V]) Remove(key K) (*V, error) {
93 i := v.indexOf(key)
94 if i == -1 {
95 err := fmt.Errorf("Can't remove unexisting index")
96 logger.Debug("Trying to delete unexisting key: ", key)
97 return nil, err
98 }
99
100 value := &v.data[i].value
101 err := v.removeIndex(i)
102 if err != nil {
103 logger.Error(err)
104 return nil, err
105 }
106 err = v.clean()
107 if err != nil {
108 logger.Error(err)
109 return nil, err
110 }
111 return *value, nil
112}
113
114func (v *Volatile[K, V]) Set(key K, value *V) error {
115 err := v.clean()
116 if err != nil {
117 logger.Error(err)
118 return err
119 }
120
121 v.Remove(key)
122
123 e := Element[K, V]{key: key, value: value, Timestamp: time.Now()}
124 v.data = append(v.data, e)
125 return nil
126}