85 lines
1.6 KiB
Go
85 lines
1.6 KiB
Go
|
package goroutineinstance
|
||
|
|
||
|
import (
|
||
|
"encoding/json"
|
||
|
"fmt"
|
||
|
"time"
|
||
|
|
||
|
"gfx.cafe/util/go/generic"
|
||
|
"github.com/DataDog/gostackparse"
|
||
|
"github.com/rs/xid"
|
||
|
"github.com/spf13/afero"
|
||
|
)
|
||
|
|
||
|
type InstanceStore interface {
|
||
|
NewInstance(xs []*gostackparse.Goroutine) (*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(dat []*gostackparse.Goroutine) (*Instance, error) {
|
||
|
// save instance
|
||
|
id := xid.New()
|
||
|
i := &Instance{
|
||
|
id: id,
|
||
|
dat: dat,
|
||
|
}
|
||
|
|
||
|
jsonDat, err := json.Marshal(dat)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
file, err := o.fs.Create(id.String())
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
_, err = file.Write(jsonDat)
|
||
|
if err != nil {
|
||
|
file.Close()
|
||
|
return nil, err
|
||
|
}
|
||
|
err = file.Close()
|
||
|
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("goroutine expired")
|
||
|
}
|
||
|
}
|
||
|
bts, err := afero.ReadFile(o.fs, id.String())
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
i := &Instance{id: id}
|
||
|
err = json.Unmarshal(bts, &i.dat)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
o.cache.Store(id, i)
|
||
|
return i, nil
|
||
|
}
|