82 lines
1.5 KiB
Go
82 lines
1.5 KiB
Go
|
package profileinstance
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"time"
|
||
|
|
||
|
"gfx.cafe/util/go/generic"
|
||
|
"github.com/rs/xid"
|
||
|
"github.com/spf13/afero"
|
||
|
)
|
||
|
|
||
|
type InstanceStore interface {
|
||
|
NewInstance(xs []byte) (*Instance, error)
|
||
|
GetInstance(id xid.ID) (*Instance, error)
|
||
|
}
|
||
|
|
||
|
type fileBasedInstanceStore struct {
|
||
|
expiry time.Duration
|
||
|
fs afero.Fs
|
||
|
|
||
|
cache generic.Map[xid.ID, *Instance]
|
||
|
}
|
||
|
|
||
|
func NewFileBasedInstanceStore(fs afero.Fs, expiry time.Duration) *fileBasedInstanceStore {
|
||
|
return &fileBasedInstanceStore{
|
||
|
fs: fs,
|
||
|
expiry: expiry,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (o *fileBasedInstanceStore) NewInstance(xs []byte) (*Instance, error) {
|
||
|
// save instance
|
||
|
id := xid.New()
|
||
|
i := &Instance{
|
||
|
id: id,
|
||
|
dat: xs,
|
||
|
}
|
||
|
|
||
|
file, err := o.fs.Create(id.String())
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
_, err = file.Write(xs)
|
||
|
if err != nil {
|
||
|
file.Close()
|
||
|
return nil, err
|
||
|
}
|
||
|
err = file.Close()
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
err = i.startServer()
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
o.cache.Store(id, i)
|
||
|
return i, nil
|
||
|
}
|
||
|
|
||
|
func (o *fileBasedInstanceStore) GetInstance(id xid.ID) (*Instance, error) {
|
||
|
if i, ok := o.cache.Load(id); ok {
|
||
|
return i, nil
|
||
|
}
|
||
|
if o.expiry > 0 {
|
||
|
if id.Time().After(time.Now().Add(o.expiry)) {
|
||
|
o.fs.Remove(id.String())
|
||
|
return nil, fmt.Errorf("profile expired")
|
||
|
}
|
||
|
}
|
||
|
bts, err := afero.ReadFile(o.fs, id.String())
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
i := &Instance{id: id, dat: bts}
|
||
|
err = i.startServer()
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
o.cache.Store(id, i)
|
||
|
return i, nil
|
||
|
}
|