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, } }