146 lines
2.9 KiB
Go
146 lines
2.9 KiB
Go
package demos
|
|
|
|
import "sync"
|
|
|
|
// MemStore : Store en mémoire (dev/tests).
|
|
type MemStore struct {
|
|
mu sync.RWMutex
|
|
items map[string]Demo
|
|
}
|
|
|
|
func NewMemStore() *MemStore { return &MemStore{items: make(map[string]Demo)} }
|
|
|
|
func (m *MemStore) Create(d Demo) (Demo, error) {
|
|
m.mu.Lock()
|
|
defer m.mu.Unlock()
|
|
m.items[d.ID] = d
|
|
return d, nil
|
|
}
|
|
|
|
func (m *MemStore) Get(id string) (Demo, bool) {
|
|
m.mu.RLock()
|
|
defer m.mu.RUnlock()
|
|
d, ok := m.items[id]
|
|
return d, ok
|
|
}
|
|
|
|
func (m *MemStore) List() ([]Demo, error) {
|
|
m.mu.RLock()
|
|
defer m.mu.RUnlock()
|
|
out := make([]Demo, 0, len(m.items))
|
|
for _, d := range m.items {
|
|
out = append(out, d)
|
|
}
|
|
return out, nil
|
|
}
|
|
|
|
func (m *MemStore) ListByUsername(username string) ([]Demo, error) {
|
|
m.mu.RLock()
|
|
defer m.mu.RUnlock()
|
|
out := make([]Demo, 0)
|
|
for _, d := range m.items {
|
|
if d.Username == username {
|
|
out = append(out, d)
|
|
}
|
|
}
|
|
return out, nil
|
|
}
|
|
|
|
func (m *MemStore) Update(d Demo) (Demo, error) {
|
|
m.mu.Lock()
|
|
defer m.mu.Unlock()
|
|
m.items[d.ID] = d
|
|
return d, nil
|
|
}
|
|
|
|
func (m *MemStore) CountActive() (int, error) {
|
|
m.mu.RLock()
|
|
defer m.mu.RUnlock()
|
|
n := 0
|
|
for _, d := range m.items {
|
|
if d.Status.Active() {
|
|
n++
|
|
}
|
|
}
|
|
return n, nil
|
|
}
|
|
|
|
// MemPool : Pool en mémoire (dev/tests), PoolSizePerService slots par service.
|
|
type MemPool struct {
|
|
mu sync.Mutex
|
|
res []*ExternalResource
|
|
next uint
|
|
}
|
|
|
|
// NewMemPool construit un pool rempli (PoolSizePerService slots libres par service).
|
|
func NewMemPool() *MemPool {
|
|
p := &MemPool{}
|
|
for _, svc := range PooledServices {
|
|
for i := 1; i <= PoolSizePerService; i++ {
|
|
p.next++
|
|
p.res = append(p.res, &ExternalResource{
|
|
ID: p.next,
|
|
Service: svc,
|
|
Label: placeholderLabel(svc, i),
|
|
SecretRef: "secretref://" + svc + "/slot-" + itoa(i),
|
|
Status: ResourceFree,
|
|
})
|
|
}
|
|
}
|
|
return p
|
|
}
|
|
|
|
func (p *MemPool) Borrow(demoID string) ([]ExternalResource, error) {
|
|
p.mu.Lock()
|
|
defer p.mu.Unlock()
|
|
// Vérifie d'abord la dispo de chaque service (atomicité).
|
|
pick := make(map[string]*ExternalResource, len(PooledServices))
|
|
for _, svc := range PooledServices {
|
|
var found *ExternalResource
|
|
for _, r := range p.res {
|
|
if r.Service == svc && r.Status == ResourceFree {
|
|
found = r
|
|
break
|
|
}
|
|
}
|
|
if found == nil {
|
|
return nil, ErrPoolExhausted
|
|
}
|
|
pick[svc] = found
|
|
}
|
|
var out []ExternalResource
|
|
for _, r := range pick {
|
|
r.Status = ResourceBorrowed
|
|
r.DemoID = demoID
|
|
out = append(out, *r)
|
|
}
|
|
return out, nil
|
|
}
|
|
|
|
func (p *MemPool) Return(demoID string) error {
|
|
p.mu.Lock()
|
|
defer p.mu.Unlock()
|
|
for _, r := range p.res {
|
|
if r.DemoID == demoID {
|
|
r.Status = ResourceFree
|
|
r.DemoID = ""
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (p *MemPool) FreeCount() (map[string]int, error) {
|
|
p.mu.Lock()
|
|
defer p.mu.Unlock()
|
|
out := map[string]int{}
|
|
for _, svc := range PooledServices {
|
|
out[svc] = 0
|
|
}
|
|
for _, r := range p.res {
|
|
if r.Status == ResourceFree {
|
|
out[r.Service]++
|
|
}
|
|
}
|
|
return out, nil
|
|
}
|