Add output to persisted engine run, add code docs

This commit is contained in:
lash 2023-04-13 09:38:35 +01:00
parent 1844415ae9
commit 12ff703bc9
Signed by untrusted user who does not match committer: lash
GPG Key ID: 21D2E7BB88C2A746
4 changed files with 41 additions and 10 deletions

View File

@ -9,6 +9,16 @@ import (
"git.defalsify.org/festive/resource" "git.defalsify.org/festive/resource"
) )
// RunPersisted performs a single vm execution from client input using a persisted state.
//
// State is first loaded from storage. The vm is initialized with the state and executed. The new state is then saved to storage.
//
// The resulting output of the execution will be written to the provided writer.
//
// The state is identified by the SessionId member of the Config. Before first execution, the caller must ensure that an
// initialized state actually is available for the identifier, otherwise the method will fail.
//
// It will also fail if execution by the underlying Engine fails.
func RunPersisted(cfg Config, rs resource.Resource, pr persist.Persister, input []byte, w io.Writer, ctx context.Context) error { func RunPersisted(cfg Config, rs resource.Resource, pr persist.Persister, input []byte, w io.Writer, ctx context.Context) error {
err := pr.Load(cfg.SessionId) err := pr.Load(cfg.SessionId)
if err != nil { if err != nil {
@ -24,5 +34,5 @@ func RunPersisted(cfg Config, rs resource.Resource, pr persist.Persister, input
return err return err
} }
} }
return nil return en.WriteResult(w, ctx)
} }

View File

@ -11,12 +11,16 @@ import (
"git.defalsify.org/festive/state" "git.defalsify.org/festive/state"
) )
// FsPersister is an implementation of Persister that saves state to the file system.
type FsPersister struct { type FsPersister struct {
State *state.State State *state.State
Memory *cache.Cache Memory *cache.Cache
dir string dir string
} }
// NewFsPersister creates a new FsPersister.
//
// The filesystem store will be at the given directory. The directory must exist.
func NewFsPersister(dir string) *FsPersister { func NewFsPersister(dir string) *FsPersister {
fp, err := filepath.Abs(dir) fp, err := filepath.Abs(dir)
if err != nil { if err != nil {
@ -27,29 +31,37 @@ func NewFsPersister(dir string) *FsPersister {
} }
} }
// WithContent sets a current State and Cache object.
//
// This method is normally called before Serialize / Save.
func(p *FsPersister) WithContent(st *state.State, ca *cache.Cache) *FsPersister { func(p *FsPersister) WithContent(st *state.State, ca *cache.Cache) *FsPersister {
p.State = st p.State = st
p.Memory = ca p.Memory = ca
return p return p
} }
// GetState implements the Persister interface.
func(p *FsPersister) GetState() *state.State { func(p *FsPersister) GetState() *state.State {
return p.State return p.State
} }
// GetState implements the Persister interface.
func(p *FsPersister) GetMemory() cache.Memory { func(p *FsPersister) GetMemory() cache.Memory {
return p.Memory return p.Memory
} }
// GetState implements the Persister interface.
func(p *FsPersister) Serialize() ([]byte, error) { func(p *FsPersister) Serialize() ([]byte, error) {
return cbor.Marshal(p) return cbor.Marshal(p)
} }
// GetState implements the Persister interface.
func(p *FsPersister) Deserialize(b []byte) error { func(p *FsPersister) Deserialize(b []byte) error {
err := cbor.Unmarshal(b, p) err := cbor.Unmarshal(b, p)
return err return err
} }
// GetState implements the Persister interface.
func(p *FsPersister) Save(key string) error { func(p *FsPersister) Save(key string) error {
b, err := p.Serialize() b, err := p.Serialize()
if err != nil { if err != nil {
@ -60,6 +72,7 @@ func(p *FsPersister) Save(key string) error {
return ioutil.WriteFile(fp, b, 0600) return ioutil.WriteFile(fp, b, 0600)
} }
// GetState implements the Persister interface.
func(p *FsPersister) Load(key string) error { func(p *FsPersister) Load(key string) error {
fp := path.Join(p.dir, key) fp := path.Join(p.dir, key)
b, err := ioutil.ReadFile(fp) b, err := ioutil.ReadFile(fp)

View File

@ -5,12 +5,13 @@ import (
"git.defalsify.org/festive/state" "git.defalsify.org/festive/state"
) )
// Persister interface defines the methods needed for a component that can store the execution state to a storage location.
type Persister interface { type Persister interface {
Serialize() ([]byte, error) Serialize() ([]byte, error) // Output serializes representation of the state.
Deserialize(b []byte) error Deserialize(b []byte) error // Restore state from a serialized state.
Save(key string) error Save(key string) error // Serialize and commit the state representation to persisted storage.
Load(key string) error Load(key string) error // Load the state representation from persisted storage and Deserialize.
GetState() *state.State GetState() *state.State // Get the currently loaded State object.
GetMemory() cache.Memory GetMemory() cache.Memory // Get the currently loaded Cache object.
} }

View File

@ -4,10 +4,11 @@ import (
"context" "context"
) )
// Result contains the results of an external code operation.
type Result struct { type Result struct {
Content string Content string // content value for symbol after execution.
FlagSet []uint32 FlagSet []uint32 // request caller to set error flags at given indices.
FlagReset []uint32 FlagReset []uint32 // request caller to reset error flags at given indices.
} }
// EntryFunc is a function signature for retrieving value for a key // EntryFunc is a function signature for retrieving value for a key
@ -23,6 +24,9 @@ type Resource interface {
FuncFor(sym string) (EntryFunc, error) // Resolve symbol content point for. FuncFor(sym string) (EntryFunc, error) // Resolve symbol content point for.
} }
// MenuResource contains the base definition for building Resource implementations.
//
// TODO: Rename to BaseResource
type MenuResource struct { type MenuResource struct {
sinkValues []string sinkValues []string
codeFunc CodeFunc codeFunc CodeFunc
@ -53,14 +57,17 @@ func(m *MenuResource) WithTemplateGetter(templateGetter TemplateFunc) *MenuResou
return m return m
} }
// FuncFor implements Resource interface
func(m *MenuResource) FuncFor(sym string) (EntryFunc, error) { func(m *MenuResource) FuncFor(sym string) (EntryFunc, error) {
return m.funcFunc(sym) return m.funcFunc(sym)
} }
// GetCode implements Resource interface
func(m *MenuResource) GetCode(sym string) ([]byte, error) { func(m *MenuResource) GetCode(sym string) ([]byte, error) {
return m.codeFunc(sym) return m.codeFunc(sym)
} }
// GetTemplate implements Resource interface
func(m *MenuResource) GetTemplate(sym string) (string, error) { func(m *MenuResource) GetTemplate(sym string) (string, error) {
return m.templateFunc(sym) return m.templateFunc(sym)
} }