buildr/modules/state/store.go
Peter 5af8ddceab
Some checks failed
continuous-integration/drone/push Build is failing
refactor: rework plugins to track their state
- introduce individual commands to manage plugins
- store plugin in state to skip loading them to memory every time
2023-06-29 20:14:52 +02:00

89 lines
1.7 KiB
Go

package state
import (
"context"
"errors"
"fmt"
"time"
"code.icb4dc0.de/buildr/buildr/modules/state/ent"
"code.icb4dc0.de/buildr/buildr/modules/state/ent/kventry"
_ "modernc.org/sqlite"
)
var ErrEmptyKey = errors.New("key may not be empty")
func NewEntStore(ctx context.Context, client *ent.Client) (*EntStateRepository, error) {
_, err := client.KVEntry.
Delete().
Where(kventry.TTLLTE(time.Now().UTC())).
Exec(ctx)
if err != nil {
return nil, fmt.Errorf("failed to delete expired entries: %w", err)
}
return &EntStateRepository{
client: client,
}, nil
}
var _ Store = (*EntStateRepository)(nil)
type EntStateRepository struct {
client *ent.Client
}
func (s *EntStateRepository) Get(ctx context.Context, key Key) (state []byte, meta Metadata, err error) {
keyHash := key.Bytes()
if len(keyHash) == 0 {
return nil, Metadata{}, ErrEmptyKey
}
kvEntry, err := s.client.KVEntry.
Query().
Where(kventry.Key(keyHash)).
Only(ctx)
if err != nil {
if ent.IsNotFound(err) {
return nil, Metadata{}, nil
}
return nil, Metadata{}, err
}
if kvEntry.TTL != nil && kvEntry.TTL.Before(time.Now().UTC()) {
return nil, Metadata{}, nil
}
return kvEntry.State, metadataForEntry(*kvEntry), nil
}
func (s *EntStateRepository) Set(ctx context.Context, key Key, state []byte, opts ...EntryOption) error {
keyHash := key.Bytes()
if len(keyHash) == 0 {
return ErrEmptyKey
}
create := s.client.KVEntry.
Create()
for i := range opts {
opts[i].applyToEntry(create)
}
return create.
SetKey(keyHash).
SetState(state).
OnConflict().
UpdateModifiedAt().
UpdateState().
Exec(ctx)
}
func metadataForEntry(entry ent.KVEntry) Metadata {
return Metadata{
ModifiedAt: entry.ModifiedAt,
TTL: entry.TTL,
}
}