167 lines
3.6 KiB
Go
167 lines
3.6 KiB
Go
|
package memory
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"slices"
|
||
|
"sync"
|
||
|
"time"
|
||
|
|
||
|
"forge.cadoles.com/Cadoles/emissary/internal/datastore"
|
||
|
"github.com/pkg/errors"
|
||
|
)
|
||
|
|
||
|
type specDefRecord struct {
|
||
|
Schema []byte
|
||
|
CreatedAt time.Time
|
||
|
UpdatedAt time.Time
|
||
|
}
|
||
|
|
||
|
type SpecDefinitionRepository struct {
|
||
|
definitions map[string]map[string]specDefRecord
|
||
|
mutex sync.RWMutex
|
||
|
}
|
||
|
|
||
|
// Delete implements datastore.SpecDefinitionRepository.
|
||
|
func (r *SpecDefinitionRepository) Delete(ctx context.Context, name string, version string) error {
|
||
|
r.mutex.Lock()
|
||
|
defer r.mutex.Unlock()
|
||
|
|
||
|
versions, exists := r.definitions[name]
|
||
|
if !exists {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
delete(versions, version)
|
||
|
|
||
|
r.definitions[name] = versions
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// Get implements datastore.SpecDefinitionRepository.
|
||
|
func (r *SpecDefinitionRepository) Get(ctx context.Context, name string, version string) (*datastore.SpecDefinition, error) {
|
||
|
r.mutex.RLock()
|
||
|
defer r.mutex.RUnlock()
|
||
|
|
||
|
versions, exists := r.definitions[name]
|
||
|
if !exists {
|
||
|
return nil, errors.WithStack(datastore.ErrNotFound)
|
||
|
}
|
||
|
|
||
|
rec, exists := versions[version]
|
||
|
if !exists {
|
||
|
return nil, errors.WithStack(datastore.ErrNotFound)
|
||
|
}
|
||
|
|
||
|
specDef := datastore.SpecDefinition{
|
||
|
SpecDefinitionHeader: datastore.SpecDefinitionHeader{
|
||
|
Name: name,
|
||
|
Version: version,
|
||
|
CreatedAt: rec.CreatedAt,
|
||
|
UpdatedAt: rec.UpdatedAt,
|
||
|
},
|
||
|
Schema: rec.Schema[:],
|
||
|
}
|
||
|
|
||
|
return &specDef, nil
|
||
|
}
|
||
|
|
||
|
// Query implements datastore.SpecDefinitionRepository.
|
||
|
func (r *SpecDefinitionRepository) Query(ctx context.Context, opts ...datastore.SpecDefinitionQueryOptionFunc) ([]datastore.SpecDefinitionHeader, int, error) {
|
||
|
options := &datastore.SpecDefinitionQueryOptions{}
|
||
|
for _, fn := range opts {
|
||
|
fn(options)
|
||
|
}
|
||
|
|
||
|
r.mutex.RLock()
|
||
|
defer r.mutex.RUnlock()
|
||
|
|
||
|
specDefs := make([]datastore.SpecDefinitionHeader, 0)
|
||
|
count := 0
|
||
|
|
||
|
for name, versions := range r.definitions {
|
||
|
for version, rec := range versions {
|
||
|
count++
|
||
|
|
||
|
matches := true
|
||
|
|
||
|
if options.Names != nil && !slices.Contains(options.Names, name) {
|
||
|
matches = false
|
||
|
}
|
||
|
|
||
|
if options.Versions != nil && !slices.Contains(options.Versions, version) {
|
||
|
matches = false
|
||
|
}
|
||
|
|
||
|
if options.Offset != nil && count < *options.Offset {
|
||
|
matches = false
|
||
|
}
|
||
|
|
||
|
if options.Limit != nil && len(specDefs) >= *options.Limit {
|
||
|
matches = false
|
||
|
}
|
||
|
|
||
|
if !matches {
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
specDefs = append(specDefs, datastore.SpecDefinitionHeader{
|
||
|
Name: name,
|
||
|
Version: version,
|
||
|
CreatedAt: rec.CreatedAt,
|
||
|
UpdatedAt: rec.UpdatedAt,
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return specDefs, count, nil
|
||
|
}
|
||
|
|
||
|
// Upsert implements datastore.SpecDefinitionRepository.
|
||
|
func (r *SpecDefinitionRepository) Upsert(ctx context.Context, name string, version string, schema []byte) (*datastore.SpecDefinition, error) {
|
||
|
r.mutex.Lock()
|
||
|
defer r.mutex.Unlock()
|
||
|
|
||
|
versions, exists := r.definitions[name]
|
||
|
if !exists {
|
||
|
versions = make(map[string]specDefRecord)
|
||
|
}
|
||
|
|
||
|
now := time.Now().UTC()
|
||
|
|
||
|
rec, exists := versions[version]
|
||
|
if !exists {
|
||
|
rec = specDefRecord{
|
||
|
CreatedAt: now,
|
||
|
UpdatedAt: now,
|
||
|
Schema: schema[:],
|
||
|
}
|
||
|
} else {
|
||
|
rec.UpdatedAt = now
|
||
|
rec.Schema = schema
|
||
|
}
|
||
|
|
||
|
versions[version] = rec
|
||
|
r.definitions[name] = versions
|
||
|
|
||
|
specDef := datastore.SpecDefinition{
|
||
|
SpecDefinitionHeader: datastore.SpecDefinitionHeader{
|
||
|
Name: name,
|
||
|
Version: version,
|
||
|
CreatedAt: rec.CreatedAt,
|
||
|
UpdatedAt: rec.UpdatedAt,
|
||
|
},
|
||
|
Schema: rec.Schema[:],
|
||
|
}
|
||
|
|
||
|
return &specDef, nil
|
||
|
}
|
||
|
|
||
|
func NewSpecDefinitionRepository() *SpecDefinitionRepository {
|
||
|
return &SpecDefinitionRepository{
|
||
|
definitions: make(map[string]map[string]specDefRecord),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var _ datastore.SpecDefinitionRepository = &SpecDefinitionRepository{}
|