all repos — fixyoutube-go @ 78a91dca196fbcf8499a86c8282cce3b83e1302d

A better way to embed YouTube videos everywhere (inspired by FixTweet).

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.Warn("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}