checkpoint on integratng wstore. moved to wails data structures, got immer working again, Window object, transitioned to generic DB ops, lots more

This commit is contained in:
sawka
2024-05-24 15:08:24 -06:00
parent 8173bc3c61
commit 134ba3c34c
19 changed files with 542 additions and 289 deletions
+55 -28
View File
@@ -4,12 +4,14 @@
package blockcontroller
import (
"context"
"encoding/base64"
"encoding/json"
"fmt"
"io"
"log"
"sync"
"time"
"github.com/creack/pty"
"github.com/google/uuid"
@@ -24,6 +26,8 @@ const (
BlockController_Cmd = "cmd"
)
const DefaultTimeout = 2 * time.Second
var globalLock = &sync.Mutex{}
var blockControllerMap = make(map[string]*BlockController)
@@ -32,11 +36,18 @@ type BlockController struct {
BlockId string
BlockDef *wstore.BlockDef
InputCh chan BlockCommand
Status string
ShellProc *shellexec.ShellProc
ShellInputCh chan *InputCommand
}
func (bc *BlockController) WithLock(f func()) {
bc.Lock.Lock()
defer bc.Lock.Unlock()
f()
}
func jsonDeepCopy(val map[string]any) (map[string]any, error) {
barr, err := json.Marshal(val)
if err != nil {
@@ -50,10 +61,9 @@ func jsonDeepCopy(val map[string]any) (map[string]any, error) {
return rtn, nil
}
func CreateBlock(bdef *wstore.BlockDef, rtOpts *wstore.RuntimeOpts) (*wstore.Block, error) {
func CreateBlock(ctx context.Context, bdef *wstore.BlockDef, rtOpts *wstore.RuntimeOpts) (*wstore.Block, error) {
blockId := uuid.New().String()
blockData := &wstore.Block{
Lock: &sync.Mutex{},
BlockId: blockId,
BlockDef: bdef,
Controller: bdef.Controller,
@@ -65,7 +75,10 @@ func CreateBlock(bdef *wstore.BlockDef, rtOpts *wstore.RuntimeOpts) (*wstore.Blo
if err != nil {
return nil, fmt.Errorf("error copying meta: %w", err)
}
wstore.BlockMap.Set(blockId, blockData)
err = wstore.DBInsert(ctx, blockData)
if err != nil {
return nil, fmt.Errorf("error inserting block: %w", err)
}
if blockData.Controller != "" {
StartBlockController(blockId, blockData)
}
@@ -179,10 +192,10 @@ func (bc *BlockController) DoRunShellCommand(rc *RunShellOpts) error {
func (bc *BlockController) Run(bdata *wstore.Block) {
defer func() {
bdata.WithLock(func() {
bc.WithLock(func() {
// if the controller had an error status, don't change it
if bdata.ControllerStatus == "running" {
bdata.ControllerStatus = "done"
if bc.Status == "running" {
bc.Status = "done"
}
})
eventbus.SendEvent(application.WailsEvent{
@@ -193,8 +206,8 @@ func (bc *BlockController) Run(bdata *wstore.Block) {
defer globalLock.Unlock()
delete(blockControllerMap, bc.BlockId)
}()
bdata.WithLock(func() {
bdata.ControllerStatus = "running"
bc.WithLock(func() {
bc.Status = "running"
})
// only controller is "shell" for now
@@ -221,9 +234,6 @@ func (bc *BlockController) Run(bdata *wstore.Block) {
func StartBlockController(blockId string, bdata *wstore.Block) {
if bdata.Controller != BlockController_Shell {
log.Printf("unknown controller %q\n", bdata.Controller)
bdata.WithLock(func() {
bdata.ControllerStatus = "error"
})
return
}
globalLock.Lock()
@@ -234,6 +244,7 @@ func StartBlockController(blockId string, bdata *wstore.Block) {
bc := &BlockController{
Lock: &sync.Mutex{},
BlockId: blockId,
Status: "init",
InputCh: make(chan BlockCommand),
}
blockControllerMap[blockId] = bc
@@ -246,31 +257,47 @@ func GetBlockController(blockId string) *BlockController {
return blockControllerMap[blockId]
}
func ProcessStaticCommand(blockId string, cmdGen BlockCommand) {
func ProcessStaticCommand(blockId string, cmdGen BlockCommand) error {
ctx, cancelFn := context.WithTimeout(context.Background(), DefaultTimeout)
defer cancelFn()
switch cmd := cmdGen.(type) {
case *MessageCommand:
log.Printf("MESSAGE: %s | %q\n", blockId, cmd.Message)
return nil
case *SetViewCommand:
log.Printf("SETVIEW: %s | %q\n", blockId, cmd.View)
block := wstore.BlockMap.Get(blockId)
if block != nil {
block.WithLock(func() {
block.View = cmd.View
})
block, err := wstore.DBGet[wstore.Block](ctx, blockId)
if err != nil {
return fmt.Errorf("error getting block: %w", err)
}
block.View = cmd.View
err = wstore.DBUpdate[wstore.Block](ctx, block)
if err != nil {
return fmt.Errorf("error updating block: %w", err)
}
return nil
case *SetMetaCommand:
log.Printf("SETMETA: %s | %v\n", blockId, cmd.Meta)
block := wstore.BlockMap.Get(blockId)
if block != nil {
block.WithLock(func() {
for k, v := range cmd.Meta {
if v == nil {
delete(block.Meta, k)
continue
}
block.Meta[k] = v
}
})
block, err := wstore.DBGet[wstore.Block](ctx, blockId)
if err != nil {
return fmt.Errorf("error getting block: %w", err)
}
if block == nil {
return nil
}
for k, v := range cmd.Meta {
if v == nil {
delete(block.Meta, k)
continue
}
block.Meta[k] = v
}
err = wstore.DBUpdate(ctx, block)
if err != nil {
return fmt.Errorf("error updating block: %w", err)
}
return nil
default:
return fmt.Errorf("unknown command type %T", cmdGen)
}
}