From 22df76a97f72a2d0e300cf002e5d7308b52448d3 Mon Sep 17 00:00:00 2001 From: Egor Aristov Date: Tue, 21 Oct 2025 09:42:11 +0300 Subject: [PATCH] tons of code --- lib/golang/lib.go | 90 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 84 insertions(+), 6 deletions(-) diff --git a/lib/golang/lib.go b/lib/golang/lib.go index 0eaf1d1..a4a4662 100644 --- a/lib/golang/lib.go +++ b/lib/golang/lib.go @@ -1,6 +1,7 @@ package kittenipc import ( + "bufio" "fmt" "net" "os" @@ -9,6 +10,7 @@ import ( "slices" "time" + "github.com/go-json-experiment/json" "github.com/samber/mo" ) @@ -24,6 +26,7 @@ type KittenIPC struct { socketPath string listener net.Listener conn net.Conn + errCh chan error } func New(cmd *exec.Cmd, api any, cfg Config) (*KittenIPC, error) { @@ -43,6 +46,8 @@ func New(cmd *exec.Cmd, api any, cfg Config) (*KittenIPC, error) { } cmd.Args = append(cmd.Args, ipcSocketArg, k.socketPath) + k.errCh = make(chan error, 1) + return &k, nil } @@ -60,6 +65,14 @@ func (k *KittenIPC) Start() error { return fmt.Errorf("cmd start: %w", err) } + if err := k.acceptConn(); err != nil { + return fmt.Errorf("accept connection: %w", err) + } + + return nil +} + +func (k *KittenIPC) acceptConn() error { const acceptTimeout = time.Second * 10 res := make(chan mo.Result[net.Conn], 1) @@ -83,11 +96,53 @@ func (k *KittenIPC) Start() error { return fmt.Errorf("accept: %w", res.Error()) } k.conn = res.MustGet() + k.startRcvData() } - return nil } +type MsgType int + +const ( + MsgCall MsgType = 1 + MsgResponse MsgType = 2 +) + +type Message struct { + Type MsgType `json:"type"` + Id int64 `json:"id"` + Method string `json:"method"` + Params []any `json:"params"` + Result []any `json:"result"` + Error string `json:"error"` +} + +func (k *KittenIPC) startRcvData() { + scn := bufio.NewScanner(k.conn) + for scn.Scan() { + var msg Message + if err := json.Unmarshal(scn.Bytes(), &msg); err != nil { + k.raiseErr(fmt.Errorf("unmarshal message: %w", err)) + break + } + k.processMsg(msg) + } + if err := scn.Err(); err != nil { + k.raiseErr(err) + } +} + +func (k *KittenIPC) processMsg(msg Message) { + +} + +func (k *KittenIPC) raiseErr(err error) { + select { + case k.errCh <- err: + default: + } +} + func (k *KittenIPC) closeSock() error { if err := k.listener.Close(); err != nil { return fmt.Errorf("close socket listener: %w", err) @@ -96,13 +151,36 @@ func (k *KittenIPC) closeSock() error { } func (k *KittenIPC) Wait() error { - if err := k.cmd.Wait(); err != nil { - return fmt.Errorf("cmd wait: %w", err) - } - if err := k.closeSock(); err != nil { - return fmt.Errorf("closeSock: %w", err) + waitErrCh := make(chan error, 1) + + go func() { + waitErrCh <- k.cmd.Wait() + }() + + select { + case err := <-k.errCh: + runtimeErr := fmt.Errorf("runtime error: %w", err) + killErr := k.cmd.Process.Kill() + return mergeErr(runtimeErr, killErr) + case err := <-waitErrCh: + if err != nil { + return fmt.Errorf("cmd wait: %w", err) + } } return nil } + +func mergeErr(errs ...error) (ret error) { + for _, err := range errs { + if err != nil { + if ret == nil { + ret = err + } else { + ret = fmt.Errorf("%w; %w", ret, err) + } + } + } + return +}