Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🚀 [Feature]: ObjectBox storage support #1531

Open
3 tasks done
karnadii opened this issue Nov 19, 2024 · 2 comments
Open
3 tasks done

🚀 [Feature]: ObjectBox storage support #1531

karnadii opened this issue Nov 19, 2024 · 2 comments

Comments

@karnadii
Copy link

Feature Description

implement driver for ObjectBox from github.com/objectbox/objectbox-go

Additional Context (optional)

No response

Code Snippet (optional)

package main

import "github.com/gofiber/storage/%package%"

func main() {
  // Steps to reproduce
}

Checklist:

  • I agree to follow Fiber's Code of Conduct.
  • I have checked for existing issues that describe my suggestion prior to opening this one.
  • I understand that improperly formatted feature requests may be closed without explanation.
@karnadii
Copy link
Author

I have make some small implementation
but I just learned go two days ago so I don't know what the best practice is

package middleware

import (
	"math/rand/v2"
	"time"

	"github.com/objectbox/objectbox-go/objectbox"
)

//go:generate go run github.com/objectbox/objectbox-go/cmd/objectbox-gogen

type CacheEntry struct {
	Id        uint64 `objectbox:"id"`
	Key       string `objectbox:"index"`
	Value     []byte
	ExpiresAt int64
}

type ObjectBoxStorage struct {
	ob  *objectbox.ObjectBox
	box *CacheEntryBox
}

func NewObjectBoxStorage() (*ObjectBoxStorage, error) {
	ob, err := objectbox.NewBuilder().Model(ObjectBoxModel()).Build()
	if err != nil {
		return nil, err
	}

	storage := &ObjectBoxStorage{
		ob:  ob,
		box: BoxForCacheEntry(ob),
	}

	// Run cleanup every hour
	go func() {
		ticker := time.NewTicker(1 * time.Hour)
		for range ticker.C {
			storage.cleanupExpired()
		}
	}()

	return storage, nil
}

func (s *ObjectBoxStorage) Get(key string) ([]byte, error) {
	if rand.Float32() < 0.1 {
		s.cleanupExpired()
	}

	query := s.box.Query(CacheEntry_.Key.Equals(key, true), CacheEntry_.ExpiresAt.GreaterThan(time.Now().Unix()))
	entries, err := query.Find()
	if err != nil {
		return nil, err
	}

	if len(entries) == 0 {
		return nil, nil
	}
	return entries[0].Value, nil

}

func (s *ObjectBoxStorage) Set(key string, val []byte, exp time.Duration) error {
	entry := &CacheEntry{
		Key:       key,
		Value:     val,
		ExpiresAt: time.Now().Add(exp).Unix(),
	}
	_, err := s.box.Put(entry)
	return err
}

func (s *ObjectBoxStorage) Delete(key string) error {
	query := s.box.Query(CacheEntry_.Key.Equals(key, true))
	entries, err := query.Find()
	if err != nil {
		return err
	}

	for _, entry := range entries {
		if err := s.box.Remove(entry); err != nil {
			return err
		}
	}

	return nil
}

func (s *ObjectBoxStorage) Reset() error {
	return s.box.RemoveAll()
}

func (s *ObjectBoxStorage) Close() error {
	s.ob.Close()
	return nil
}

func (s *ObjectBoxStorage) cleanupExpired() {
	query := s.box.Query(CacheEntry_.ExpiresAt.LessThan(time.Now().Unix()))
	entries, err := query.Find()
	if err != nil {
		return
	}
	s.box.ObjectBox.RunInWriteTx(func() error {
		for _, entry := range entries {
			s.box.Remove(entry)
		}
		return nil
	})

}

@gaby
Copy link
Member

gaby commented Nov 19, 2024

I will take a look later to see how much effort is this.

@gaby gaby self-assigned this Nov 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants