persist.go (2404B)
1 package engine 2 3 import ( 4 "context" 5 "io" 6 7 "git.defalsify.org/vise.git/persist" 8 "git.defalsify.org/vise.git/resource" 9 ) 10 11 // PersistedEngine adds persisted state to the Engine object. It provides a persisted state option for synchronous/interactive clients. 12 type PersistedEngine struct { 13 *Engine 14 pr persist.Persister 15 } 16 17 18 // NewPersistedEngine creates a new PersistedEngine 19 func NewPersistedEngine(ctx context.Context, cfg Config, pr persist.Persister, rs resource.Resource) (PersistedEngine, error) { 20 err := pr.Load(cfg.SessionId) 21 if err != nil { 22 return PersistedEngine{}, err 23 } 24 st := pr.GetState() 25 ca := pr.GetMemory() 26 27 enb := NewEngine(ctx, cfg, st, rs, ca) 28 en := PersistedEngine{ 29 &enb, 30 pr, 31 } 32 return en, err 33 } 34 35 // Exec executes the parent method Engine.Exec, and afterwards persists the new state. 36 func(pe PersistedEngine) Exec(ctx context.Context, input []byte) (bool, error) { 37 v, err := pe.Engine.Exec(ctx, input) 38 if err != nil { 39 return v, err 40 } 41 err = pe.pr.Save(pe.Engine.session) 42 return v, err 43 } 44 45 // Finish implements EngineIsh interface 46 func(pe PersistedEngine) Finish() error { 47 Logg.Tracef("that's a wrap", "engine", pe) 48 return pe.pr.Save(pe.Engine.session) 49 } 50 51 // RunPersisted performs a single vm execution from client input using a persisted state. 52 // 53 // State is first loaded from storage. The vm is initialized with the state and executed. The new state is then saved to storage. 54 // 55 // The resulting output of the execution will be written to the provided writer. 56 // 57 // The state is identified by the SessionId member of the Config. Before first execution, the caller must ensure that an 58 // initialized state actually is available for the identifier, otherwise the method will fail. 59 // 60 // It will also fail if execution by the underlying Engine fails. 61 func RunPersisted(cfg Config, rs resource.Resource, pr persist.Persister, input []byte, w io.Writer, ctx context.Context) error { 62 err := pr.Load(cfg.SessionId) 63 if err != nil { 64 return err 65 } 66 67 st := pr.GetState() 68 ca := pr.GetMemory() 69 en := NewEngine(ctx, cfg, st, rs, ca) 70 71 c, err := en.WriteResult(ctx, w) 72 if err != nil { 73 return err 74 } 75 err = pr.Save(cfg.SessionId) 76 if err != nil { 77 return err 78 } 79 if c > 0 { 80 return err 81 } 82 83 _, err = en.Exec(ctx, input) 84 if err != nil { 85 return err 86 } 87 _, err = en.WriteResult(ctx, w) 88 if err != nil { 89 return err 90 } 91 en.Finish() 92 return pr.Save(cfg.SessionId) 93 }