memory.go 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. package memory
  2. import (
  3. "context"
  4. "encoding/json"
  5. "fmt"
  6. "time"
  7. "github.com/TecharoHQ/anubis/decaymap"
  8. "github.com/TecharoHQ/anubis/lib/store"
  9. )
  10. type factory struct{}
  11. func (factory) Build(ctx context.Context, _ json.RawMessage) (store.Interface, error) {
  12. return New(ctx), nil
  13. }
  14. func (factory) Valid(json.RawMessage) error { return nil }
  15. func init() {
  16. store.Register("memory", factory{})
  17. }
  18. type impl struct {
  19. store *decaymap.Impl[string, []byte]
  20. }
  21. func (i *impl) Delete(_ context.Context, key string) error {
  22. if !i.store.Delete(key) {
  23. return fmt.Errorf("%w: %q", store.ErrNotFound, key)
  24. }
  25. return nil
  26. }
  27. func (i *impl) Get(_ context.Context, key string) ([]byte, error) {
  28. result, ok := i.store.Get(key)
  29. if !ok {
  30. return nil, fmt.Errorf("%w: %q", store.ErrNotFound, key)
  31. }
  32. return result, nil
  33. }
  34. func (i *impl) Set(_ context.Context, key string, value []byte, expiry time.Duration) error {
  35. i.store.Set(key, value, expiry)
  36. return nil
  37. }
  38. func (i *impl) IsPersistent() bool {
  39. return false
  40. }
  41. func (i *impl) cleanupThread(ctx context.Context) {
  42. t := time.NewTicker(5 * time.Minute)
  43. defer t.Stop()
  44. for {
  45. select {
  46. case <-ctx.Done():
  47. return
  48. case <-t.C:
  49. i.store.Cleanup()
  50. }
  51. }
  52. }
  53. // New creates a simple in-memory store. This will not scale to multiple Anubis instances.
  54. func New(ctx context.Context) store.Interface {
  55. result := &impl{
  56. store: decaymap.New[string, []byte](),
  57. }
  58. go result.cleanupThread(ctx)
  59. return result
  60. }