From d006c992ec0a5a3cce3bcaf109b7735c5e8fc3a2 Mon Sep 17 00:00:00 2001 From: vilmibm Date: Fri, 23 Dec 2022 21:31:08 -0800 Subject: [PATCH] refactor Gateway out --- server/cmd/main.go | 46 +++++++++++++++++++++++++++++--------- server/witch/witch.go | 51 +++++-------------------------------------- 2 files changed, 41 insertions(+), 56 deletions(-) diff --git a/server/cmd/main.go b/server/cmd/main.go index e428740..05e3c57 100644 --- a/server/cmd/main.go +++ b/server/cmd/main.go @@ -71,10 +71,12 @@ func _main() (err error) { type gameWorldServer struct { proto.UnimplementedGameWorldServer - db db.DB - mu sync.Mutex // for msgRouter - msgRouter map[string]func(*proto.ClientMessage) error - Gateway *witch.Gateway + db db.DB + msgRouterMutex sync.Mutex + msgRouter map[string]func(*proto.ClientMessage) error + Gateway *witch.Gateway + scripts map[int]*witch.ScriptContext + scriptsMutex sync.RWMutex } func newServer() (*gameWorldServer, error) { @@ -93,15 +95,39 @@ func newServer() (*gameWorldServer, error) { } s := &gameWorldServer{ - msgRouter: make(map[string]func(*proto.ClientMessage) error), - db: db, + msgRouter: make(map[string]func(*proto.ClientMessage) error), + db: db, + scripts: make(map[int]*witch.ScriptContext), + scriptsMutex: sync.RWMutex{}, } - gw := witch.NewGateway(s.HandleCmd) - s.Gateway = gw return s, nil } +func (s *gameWorldServer) verbHandler(verb, rest string, sender, target db.Object) error { + /* + So right here is a problem: we are definitely making >1 LuaState per + goroutine. Top priority before anything else is getting a goroutine made + for the script contexts + */ + s.scriptsMutex.RLock() + sc, ok := s.scripts[target.ID] + s.scriptsMutex.RUnlock() + + if !ok || sc.NeedsRefresh(target) { + sc, err := witch.NewScriptContext(target) + if err != nil { + return err + } + + s.scriptsMutex.Lock() + s.scripts[target.ID] = sc + s.scriptsMutex.Unlock() + } + + return sc.Handle(verb, rest, sender, target) +} + func (s *gameWorldServer) HandleCmd(verb, rest string, sender *db.Object) { // TODO } @@ -213,9 +239,9 @@ func (s *gameWorldServer) Ping(ctx context.Context, _ *proto.SessionInfo) (*prot } func (s *gameWorldServer) Messages(si *proto.SessionInfo, stream proto.GameWorld_MessagesServer) error { - s.mu.Lock() + s.msgRouterMutex.Lock() s.msgRouter[si.SessionID] = stream.Send - s.mu.Unlock() + s.msgRouterMutex.Unlock() // TODO this is clearly bad but it works. I should refactor this so that messages are received on a channel. for { diff --git a/server/witch/witch.go b/server/witch/witch.go index ea5e722..bd9c84a 100644 --- a/server/witch/witch.go +++ b/server/witch/witch.go @@ -1,8 +1,6 @@ package witch import ( - "sync" - "github.com/vilmibm/hermeticum/server/db" lua "github.com/yuin/gopher-lua" ) @@ -15,14 +13,14 @@ import ( */ -type scriptContext struct { +type ScriptContext struct { script string l *lua.LState incoming chan string // TODO whatever is needed to support calling a Go API } -func (sc *scriptContext) NeedsRefresh(obj db.Object) bool { +func (sc *ScriptContext) NeedsRefresh(obj db.Object) bool { return sc.script != obj.Script } @@ -62,7 +60,7 @@ end) // - do i inject from Go or prepend some Lua code? // TODO figure out how the Lua code can affect Go and thus the database -func newScriptContext(obj db.Object) (*scriptContext, error) { +func NewScriptContext(obj db.Object) (*ScriptContext, error) { l := lua.NewState() l.SetGlobal("has", l.NewFunction(hasWrapper(obj))) @@ -73,49 +71,10 @@ func newScriptContext(obj db.Object) (*scriptContext, error) { return nil, err } - return &scriptContext{}, nil + return &ScriptContext{}, nil } -func (sc *scriptContext) Handle(verb, rest string, sender, target *db.Object) error { - +func (sc *ScriptContext) Handle(verb, rest string, sender, target db.Object) error { // TODO call _handle function from the Lstate return nil } - -type Gateway struct { - // maps game object IDs to script contexts - m map[int]*scriptContext - mu sync.RWMutex - cb func(string, string, *db.Object) -} - -func NewGateway(cb func(string, string, *db.Object)) *Gateway { - return &Gateway{ - m: map[int]*scriptContext{}, - mu: sync.RWMutex{}, - // TODO use cb from scriptContext - cb: cb, - } -} - -func (g *Gateway) VerbHandler(verb, rest string, sender, target db.Object) error { - var sc *scriptContext - g.mu.RLock() - sc, ok := g.m[target.ID] - g.mu.RUnlock() - - if !ok || sc.NeedsRefresh(target) { - sc, err := newScriptContext(target) - if err != nil { - return err - } - - g.mu.Lock() - g.m[target.ID] = sc - g.mu.Unlock() - } - - sc.Handle(verb, rest, &sender, &target) - - return nil -}