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