From d309164aca3a5d85e64414d86882db0a630775d0 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Wed, 1 May 2024 10:57:10 -0700 Subject: [PATCH 01/76] move message and query into cardinal. --- cardinal/cardinal.go | 16 ++++++-------- cardinal/cardinal_test.go | 11 +++++----- cardinal/engine_test.go | 13 +++++------ cardinal/example_messagetype_test.go | 3 +-- cardinal/gamestate/tick_test.go | 6 ++--- cardinal/{message => }/message.go | 2 +- .../manager.go => message_manager.go} | 22 +++++++++---------- cardinal/{message => }/message_test.go | 2 +- cardinal/plugin_persona.go | 12 +++++----- cardinal/{query => }/query.go | 19 ++++++++-------- .../{query/manager.go => query_manager.go} | 16 +++++++------- cardinal/{query => }/query_test.go | 7 +++--- cardinal/router/iterator/iterator_test.go | 4 ++-- cardinal/server/receipts_test.go | 3 +-- cardinal/server/server_test.go | 6 ++--- cardinal/state_test.go | 3 +-- cardinal/testutils/testutils.go | 8 +++---- cardinal/world.go | 10 ++++----- cardinal/world_recovery_test.go | 3 +-- cardinal/world_test.go | 7 +++--- 20 files changed, 78 insertions(+), 95 deletions(-) rename cardinal/{message => }/message.go (99%) rename cardinal/{message/manager.go => message_manager.go} (76%) rename cardinal/{message => }/message_test.go (99%) rename cardinal/{query => }/query.go (91%) rename cardinal/{query/manager.go => query_manager.go} (73%) rename cardinal/{query => }/query_test.go (96%) diff --git a/cardinal/cardinal.go b/cardinal/cardinal.go index 6378bbd2a..c2e649109 100644 --- a/cardinal/cardinal.go +++ b/cardinal/cardinal.go @@ -9,8 +9,6 @@ import ( "pkg.world.dev/world-engine/cardinal/component" "pkg.world.dev/world-engine/cardinal/iterators" - "pkg.world.dev/world-engine/cardinal/message" - "pkg.world.dev/world-engine/cardinal/query" "pkg.world.dev/world-engine/cardinal/search" "pkg.world.dev/world-engine/cardinal/system" "pkg.world.dev/world-engine/cardinal/types" @@ -113,15 +111,15 @@ func MustRegisterComponent[T types.Component](w *World) { } } -func EachMessage[In any, Out any](wCtx engine.Context, fn func(message.TxData[In]) (Out, error)) error { - var msg message.MessageType[In, Out] +func EachMessage[In any, Out any](wCtx engine.Context, fn func(TxData[In]) (Out, error)) error { + var msg MessageType[In, Out] msgType := reflect.TypeOf(msg) tempRes, ok := wCtx.GetMessageByType(msgType) if !ok { return eris.Errorf("Could not find %s, Message may not be registered.", msg.Name()) } var _ types.Message = &msg - res, ok := tempRes.(*message.MessageType[In, Out]) + res, ok := tempRes.(*MessageType[In, Out]) if !ok { return eris.New("wrong type") } @@ -132,7 +130,7 @@ func EachMessage[In any, Out any](wCtx engine.Context, fn func(message.TxData[In // RegisterMessage registers a message to the world. Cardinal will automatically set up HTTP routes that map to each // registered message. Message URLs are take the form of "group.name". A default group, "game", is used // unless the WithCustomMessageGroup option is used. Example: game.throw-rock -func RegisterMessage[In any, Out any](world *World, name string, opts ...message.MessageOption[In, Out]) error { +func RegisterMessage[In any, Out any](world *World, name string, opts ...MessageOption[In, Out]) error { if world.worldStage.Current() != worldstage.Init { return eris.Errorf( "engine state is %s, expected %s to register messages", @@ -142,7 +140,7 @@ func RegisterMessage[In any, Out any](world *World, name string, opts ...message } // Create the message type - msgType := message.NewMessageType[In, Out](name, opts...) + msgType := NewMessageType[In, Out](name, opts...) // Register the message with the manager err := world.msgManager.RegisterMessage(msgType, reflect.TypeOf(*msgType)) @@ -157,7 +155,7 @@ func RegisterQuery[Request any, Reply any]( w *World, name string, handler func(wCtx engine.Context, req *Request) (*Reply, error), - opts ...query.Option[Request, Reply], + opts ...QueryOption[Request, Reply], ) (err error) { if w.worldStage.Current() != worldstage.Init { return eris.Errorf( @@ -167,7 +165,7 @@ func RegisterQuery[Request any, Reply any]( ) } - q, err := query.NewQueryType[Request, Reply](name, handler, opts...) + q, err := NewQueryType[Request, Reply](name, handler, opts...) if err != nil { return err } diff --git a/cardinal/cardinal_test.go b/cardinal/cardinal_test.go index 24ef2256a..d2138a805 100644 --- a/cardinal/cardinal_test.go +++ b/cardinal/cardinal_test.go @@ -19,7 +19,6 @@ import ( "pkg.world.dev/world-engine/assert" "pkg.world.dev/world-engine/cardinal" - "pkg.world.dev/world-engine/cardinal/message" "pkg.world.dev/world-engine/cardinal/router/mocks" "pkg.world.dev/world-engine/cardinal/search/filter" "pkg.world.dev/world-engine/cardinal/testutils" @@ -52,11 +51,11 @@ type Qux struct{} func (Qux) Name() string { return "qux" } -type Health struct { +type CardinalTestHealth struct { Value int } -func (Health) Name() string { return "health" } +func (CardinalTestHealth) Name() string { return "health" } func TestForEachTransaction(t *testing.T) { tf := testutils.NewTestFixture(t, nil) @@ -73,7 +72,7 @@ func TestForEachTransaction(t *testing.T) { err := cardinal.RegisterSystems(world, func(wCtx engine.Context) error { return cardinal.EachMessage[SomeMsgRequest, SomeMsgResponse](wCtx, - func(t message.TxData[SomeMsgRequest]) (result SomeMsgResponse, err error) { + func(t cardinal.TxData[SomeMsgRequest]) (result SomeMsgResponse, err error) { if t.Msg.GenerateError { return result, errors.New("some error") } @@ -183,7 +182,7 @@ func TestTransactionAreAppliedToSomeEntities(t *testing.T) { world, func(wCtx engine.Context) error { return cardinal.EachMessage[*ModifyScoreMsg, *EmptyMsgResult](wCtx, - func(msData message.TxData[*ModifyScoreMsg]) (*EmptyMsgResult, error) { + func(msData cardinal.TxData[*ModifyScoreMsg]) (*EmptyMsgResult, error) { ms := msData.Msg err := cardinal.UpdateComponent[ScoreComponent]( wCtx, ms.PlayerID, func(s *ScoreComponent) *ScoreComponent { @@ -644,7 +643,7 @@ func TestTransactionExample(t *testing.T) { } // test same as above but with .Each addHealthToEntity.Each(wCtx, - func(tx message.TxData[AddHealthToEntityTx]) (AddHealthToEntityResult, error) { + func(tx cardinal.TxData[AddHealthToEntityTx]) (AddHealthToEntityResult, error) { targetID := tx.Msg.TargetID err := cardinal.UpdateComponent[Health](wCtx, targetID, func(h *Health) *Health { diff --git a/cardinal/engine_test.go b/cardinal/engine_test.go index 35aa1e8de..aeb50d546 100644 --- a/cardinal/engine_test.go +++ b/cardinal/engine_test.go @@ -10,7 +10,6 @@ import ( "pkg.world.dev/world-engine/assert" "pkg.world.dev/world-engine/cardinal" - "pkg.world.dev/world-engine/cardinal/message" "pkg.world.dev/world-engine/cardinal/router/iterator" "pkg.world.dev/world-engine/cardinal/router/mocks" "pkg.world.dev/world-engine/cardinal/testutils" @@ -134,7 +133,7 @@ func TestCannotWaitForNextTickAfterEngineIsShutDown(t *testing.T) { world := tf.World msgName := "foo" assert.NilError(t, - cardinal.RegisterMessage[FooIn, FooOut](world, msgName, message.WithMsgEVMSupport[FooIn, FooOut]())) + cardinal.RegisterMessage[FooIn, FooOut](world, msgName, cardinal.WithMsgEVMSupport[FooIn, FooOut]())) fooTx, ok := world.GetMessageByFullName("game." + msgName) assert.True(t, ok) var returnVal FooOut @@ -143,7 +142,7 @@ func TestCannotWaitForNextTickAfterEngineIsShutDown(t *testing.T) { world, func(wCtx engine.Context) error { return cardinal.EachMessage[FooIn, FooOut]( - wCtx, func(message.TxData[FooIn]) (FooOut, error) { + wCtx, func(cardinal.TxData[FooIn]) (FooOut, error) { return returnVal, returnErr }, ) @@ -197,7 +196,7 @@ func TestEVMTxConsume(t *testing.T) { tf := testutils.NewTestFixture(t, nil) world := tf.World msgName := "foo" - err := cardinal.RegisterMessage[FooIn, FooOut](world, msgName, message.WithMsgEVMSupport[FooIn, FooOut]()) + err := cardinal.RegisterMessage[FooIn, FooOut](world, msgName, cardinal.WithMsgEVMSupport[FooIn, FooOut]()) assert.NilError(t, err) var returnVal FooOut @@ -205,7 +204,7 @@ func TestEVMTxConsume(t *testing.T) { err = cardinal.RegisterSystems(world, func(eCtx cardinal.WorldContext) error { return cardinal.EachMessage[FooIn, FooOut]( - eCtx, func(message.TxData[FooIn]) (FooOut, error) { + eCtx, func(cardinal.TxData[FooIn]) (FooOut, error) { return returnVal, returnErr }, ) @@ -371,7 +370,7 @@ func TestTransactionsSentToRouterAfterTick(t *testing.T) { type fooMsgRes struct{} msgName := "foo" - err := cardinal.RegisterMessage[fooMsg, fooMsgRes](world, msgName, message.WithMsgEVMSupport[fooMsg, fooMsgRes]()) + err := cardinal.RegisterMessage[fooMsg, fooMsgRes](world, msgName, cardinal.WithMsgEVMSupport[fooMsg, fooMsgRes]()) assert.NilError(t, err) evmTxHash := "0x12345" @@ -449,7 +448,7 @@ func TestRecoverFromChain(t *testing.T) { fooMessages := 0 err := cardinal.RegisterSystems(world, func(engineContext cardinal.WorldContext) error { - return cardinal.EachMessage[fooMsg, fooMsgRes](engineContext, func(message.TxData[fooMsg]) (fooMsgRes, error) { + return cardinal.EachMessage[fooMsg, fooMsgRes](engineContext, func(cardinal.TxData[fooMsg]) (fooMsgRes, error) { fooMessages++ return fooMsgRes{}, nil }) diff --git a/cardinal/example_messagetype_test.go b/cardinal/example_messagetype_test.go index 7fd3224b8..ab313a262 100644 --- a/cardinal/example_messagetype_test.go +++ b/cardinal/example_messagetype_test.go @@ -6,7 +6,6 @@ import ( "fmt" "pkg.world.dev/world-engine/cardinal" - "pkg.world.dev/world-engine/cardinal/message" "pkg.world.dev/world-engine/cardinal/types/engine" ) @@ -33,7 +32,7 @@ func ExampleMessageType() { err = cardinal.RegisterSystems(world, func(wCtx engine.Context) error { return cardinal.EachMessage[MovePlayerMsg, MovePlayerResult](wCtx, - func(txData message.TxData[MovePlayerMsg]) (MovePlayerResult, error) { + func(txData cardinal.TxData[MovePlayerMsg]) (MovePlayerResult, error) { // handle the transaction // ... diff --git a/cardinal/gamestate/tick_test.go b/cardinal/gamestate/tick_test.go index 3504b0eab..39166083f 100644 --- a/cardinal/gamestate/tick_test.go +++ b/cardinal/gamestate/tick_test.go @@ -5,7 +5,7 @@ import ( "testing" "pkg.world.dev/world-engine/assert" - "pkg.world.dev/world-engine/cardinal/message" + "pkg.world.dev/world-engine/cardinal" "pkg.world.dev/world-engine/cardinal/testutils" "pkg.world.dev/world-engine/cardinal/types" "pkg.world.dev/world-engine/cardinal/types/txpool" @@ -19,8 +19,8 @@ func TestCanSaveAndRecoverTransactions(t *testing.T) { Value int } - msgAlpha := message.NewMessageType[MsgIn, MsgOut]("alpha") - msgBeta := message.NewMessageType[MsgIn, MsgOut]("beta") + msgAlpha := cardinal.NewMessageType[MsgIn, MsgOut]("alpha") + msgBeta := cardinal.NewMessageType[MsgIn, MsgOut]("beta") assert.NilError(t, msgAlpha.SetID(16)) assert.NilError(t, msgBeta.SetID(32)) msgs := []types.Message{msgAlpha, msgBeta} diff --git a/cardinal/message/message.go b/cardinal/message.go similarity index 99% rename from cardinal/message/message.go rename to cardinal/message.go index ac0e849b7..cc5468ce0 100644 --- a/cardinal/message/message.go +++ b/cardinal/message.go @@ -1,4 +1,4 @@ -package message +package cardinal import ( "errors" diff --git a/cardinal/message/manager.go b/cardinal/message_manager.go similarity index 76% rename from cardinal/message/manager.go rename to cardinal/message_manager.go index 9392f62c4..86241ba14 100644 --- a/cardinal/message/manager.go +++ b/cardinal/message_manager.go @@ -1,4 +1,4 @@ -package message +package cardinal import ( "errors" @@ -9,22 +9,22 @@ import ( "pkg.world.dev/world-engine/cardinal/types" ) -type Manager struct { +type MessageManager struct { // registeredMessages maps message FullNames to a types.Message. registeredMessages map[string]types.Message registeredMessagesByType map[reflect.Type]types.Message nextMessageID types.MessageID } -func NewManager() *Manager { - return &Manager{ +func NewMessageManager() *MessageManager { + return &MessageManager{ registeredMessages: map[string]types.Message{}, registeredMessagesByType: map[reflect.Type]types.Message{}, nextMessageID: 1, } } -func (m *Manager) RegisterMessage(msgType types.Message, msgReflectType reflect.Type) error { +func (m *MessageManager) RegisterMessage(msgType types.Message, msgReflectType reflect.Type) error { fullName := msgType.FullName() // Checks if the message is already previously registered. if err := errors.Join(m.isMessageFullNameUnique(fullName), m.isMessageTypeUnique(msgReflectType)); err != nil { @@ -46,7 +46,7 @@ func (m *Manager) RegisterMessage(msgType types.Message, msgReflectType reflect. } // GetRegisteredMessages returns the list of all registered messages -func (m *Manager) GetRegisteredMessages() []types.Message { +func (m *MessageManager) GetRegisteredMessages() []types.Message { msgs := make([]types.Message, 0, len(m.registeredMessages)) for _, msg := range m.registeredMessages { msgs = append(msgs, msg) @@ -56,7 +56,7 @@ func (m *Manager) GetRegisteredMessages() []types.Message { // GetMessageByID iterates over the all registered messages and returns the types.Message associated with the // MessageID. -func (m *Manager) GetMessageByID(id types.MessageID) types.Message { +func (m *MessageManager) GetMessageByID(id types.MessageID) types.Message { for _, msg := range m.registeredMessages { if id == msg.ID() { return msg @@ -66,18 +66,18 @@ func (m *Manager) GetMessageByID(id types.MessageID) types.Message { } // GetMessageByFullName returns the message with the given full name, if it exists. -func (m *Manager) GetMessageByFullName(fullName string) (types.Message, bool) { +func (m *MessageManager) GetMessageByFullName(fullName string) (types.Message, bool) { msg, ok := m.registeredMessages[fullName] return msg, ok } -func (m *Manager) GetMessageByType(mType reflect.Type) (types.Message, bool) { +func (m *MessageManager) GetMessageByType(mType reflect.Type) (types.Message, bool) { msg, ok := m.registeredMessagesByType[mType] return msg, ok } // isMessageFullNameUnique checks if the message name already exist in messages map. -func (m *Manager) isMessageFullNameUnique(fullName string) error { +func (m *MessageManager) isMessageFullNameUnique(fullName string) error { _, ok := m.registeredMessages[fullName] if ok { return eris.Errorf("message %q is already registered", fullName) @@ -86,7 +86,7 @@ func (m *Manager) isMessageFullNameUnique(fullName string) error { } // isMessageTypeUnique checks if the message type name already exist in messages map. -func (m *Manager) isMessageTypeUnique(msgReflectType reflect.Type) error { +func (m *MessageManager) isMessageTypeUnique(msgReflectType reflect.Type) error { _, ok := m.registeredMessagesByType[msgReflectType] if ok { return eris.Errorf("message type %q is already registered", msgReflectType) diff --git a/cardinal/message/message_test.go b/cardinal/message_test.go similarity index 99% rename from cardinal/message/message_test.go rename to cardinal/message_test.go index 1bd09c216..f92ea1d7b 100644 --- a/cardinal/message/message_test.go +++ b/cardinal/message_test.go @@ -1,4 +1,4 @@ -package message +package cardinal import ( "testing" diff --git a/cardinal/plugin_persona.go b/cardinal/plugin_persona.go index be4223751..a474d5011 100644 --- a/cardinal/plugin_persona.go +++ b/cardinal/plugin_persona.go @@ -7,12 +7,10 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/rotisserie/eris" - "pkg.world.dev/world-engine/cardinal/message" "pkg.world.dev/world-engine/cardinal/persona" "pkg.world.dev/world-engine/cardinal/persona/component" "pkg.world.dev/world-engine/cardinal/persona/msg" "pkg.world.dev/world-engine/cardinal/persona/query" - querylib "pkg.world.dev/world-engine/cardinal/query" "pkg.world.dev/world-engine/cardinal/search" "pkg.world.dev/world-engine/cardinal/search/filter" "pkg.world.dev/world-engine/cardinal/types" @@ -73,7 +71,7 @@ func (p *personaPlugin) Register(world *World) error { func (p *personaPlugin) RegisterQueries(world *World) error { err := RegisterQuery[query.PersonaSignerQueryRequest, query.PersonaSignerQueryResponse](world, "signer", query.PersonaSignerQuery, - querylib.WithCustomQueryGroup[query.PersonaSignerQueryRequest, query.PersonaSignerQueryResponse]("persona")) + WithCustomQueryGroup[query.PersonaSignerQueryRequest, query.PersonaSignerQueryResponse]("persona")) if err != nil { return err } @@ -101,8 +99,8 @@ func (p *personaPlugin) RegisterMessages(world *World) error { RegisterMessage[msg.CreatePersona, msg.CreatePersonaResult]( world, msg.CreatePersonaMessageName, - message.WithCustomMessageGroup[msg.CreatePersona, msg.CreatePersonaResult]("persona"), - message.WithMsgEVMSupport[msg.CreatePersona, msg.CreatePersonaResult]()), + WithCustomMessageGroup[msg.CreatePersona, msg.CreatePersonaResult]("persona"), + WithMsgEVMSupport[msg.CreatePersona, msg.CreatePersonaResult]()), RegisterMessage[msg.AuthorizePersonaAddress, msg.AuthorizePersonaAddressResult]( world, "authorize-persona-address", @@ -122,7 +120,7 @@ func AuthorizePersonaAddressSystem(wCtx engine.Context) error { } return EachMessage[msg.AuthorizePersonaAddress, msg.AuthorizePersonaAddressResult]( wCtx, - func(txData message.TxData[msg.AuthorizePersonaAddress]) ( + func(txData TxData[msg.AuthorizePersonaAddress]) ( result msg.AuthorizePersonaAddressResult, err error, ) { txMsg, tx := txData.Msg, txData.Tx @@ -175,7 +173,7 @@ func CreatePersonaSystem(wCtx engine.Context) error { } return EachMessage[msg.CreatePersona, msg.CreatePersonaResult]( wCtx, - func(txData message.TxData[msg.CreatePersona]) (result msg.CreatePersonaResult, err error) { + func(txData TxData[msg.CreatePersona]) (result msg.CreatePersonaResult, err error) { txMsg := txData.Msg result.Success = false diff --git a/cardinal/query/query.go b/cardinal/query.go similarity index 91% rename from cardinal/query/query.go rename to cardinal/query.go index 6b3373f20..200c509cd 100644 --- a/cardinal/query/query.go +++ b/cardinal/query.go @@ -1,4 +1,4 @@ -package query +package cardinal import ( "encoding/json" @@ -8,14 +8,13 @@ import ( "github.com/rotisserie/eris" "pkg.world.dev/world-engine/cardinal/abi" - "pkg.world.dev/world-engine/cardinal/message" "pkg.world.dev/world-engine/cardinal/types" "pkg.world.dev/world-engine/cardinal/types/engine" ) var _ engine.Query = &queryType[struct{}, struct{}]{} -type Option[Request, Reply any] func(qt *queryType[Request, Reply]) +type QueryOption[Request, Reply any] func(qt *queryType[Request, Reply]) type queryType[Request any, Reply any] struct { name string @@ -25,7 +24,7 @@ type queryType[Request any, Reply any] struct { replyABI *ethereumAbi.Type } -func WithQueryEVMSupport[Request, Reply any]() Option[Request, Reply] { +func WithQueryEVMSupport[Request, Reply any]() QueryOption[Request, Reply] { return func(qt *queryType[Request, Reply]) { if err := qt.generateABIBindings(); err != nil { panic(err) @@ -37,7 +36,7 @@ func WithQueryEVMSupport[Request, Reply any]() Option[Request, Reply] { // By default, queries are registered under the "game" group which maps it to the /query/game/:queryType route. // This option allows you to set a custom group, which allow you to register the query // under /query//:queryType. -func WithCustomQueryGroup[Request, Reply any](group string) Option[Request, Reply] { +func WithCustomQueryGroup[Request, Reply any](group string) QueryOption[Request, Reply] { return func(qt *queryType[Request, Reply]) { qt.group = group } @@ -46,7 +45,7 @@ func WithCustomQueryGroup[Request, Reply any](group string) Option[Request, Repl func NewQueryType[Request any, Reply any]( name string, handler func(wCtx engine.Context, req *Request) (*Reply, error), - opts ...Option[Request, Reply], + opts ...QueryOption[Request, Reply], ) (engine.Query, error) { err := validateQuery[Request, Reply](name, handler) if err != nil { @@ -130,7 +129,7 @@ func (r *queryType[req, rep]) HandleQueryRaw(wCtx engine.Context, bz []byte) ([] func (r *queryType[req, rep]) DecodeEVMRequest(bz []byte) (any, error) { if r.requestABI == nil { - return nil, eris.Wrap(message.ErrEVMTypeNotSet, "") + return nil, eris.Wrap(ErrEVMTypeNotSet, "") } args := ethereumAbi.Arguments{{Type: *r.requestABI}} unpacked, err := args.Unpack(bz) @@ -149,7 +148,7 @@ func (r *queryType[req, rep]) DecodeEVMRequest(bz []byte) (any, error) { func (r *queryType[req, rep]) DecodeEVMReply(bz []byte) (any, error) { if r.replyABI == nil { - return nil, eris.Wrap(message.ErrEVMTypeNotSet, "") + return nil, eris.Wrap(ErrEVMTypeNotSet, "") } args := ethereumAbi.Arguments{{Type: *r.replyABI}} unpacked, err := args.Unpack(bz) @@ -168,7 +167,7 @@ func (r *queryType[req, rep]) DecodeEVMReply(bz []byte) (any, error) { func (r *queryType[req, rep]) EncodeEVMReply(a any) ([]byte, error) { if r.replyABI == nil { - return nil, eris.Wrap(message.ErrEVMTypeNotSet, "") + return nil, eris.Wrap(ErrEVMTypeNotSet, "") } args := ethereumAbi.Arguments{{Type: *r.replyABI}} bz, err := args.Pack(a) @@ -177,7 +176,7 @@ func (r *queryType[req, rep]) EncodeEVMReply(a any) ([]byte, error) { func (r *queryType[Request, Reply]) EncodeAsABI(input any) ([]byte, error) { if r.requestABI == nil || r.replyABI == nil { - return nil, eris.Wrap(message.ErrEVMTypeNotSet, "") + return nil, eris.Wrap(ErrEVMTypeNotSet, "") } var args ethereumAbi.Arguments diff --git a/cardinal/query/manager.go b/cardinal/query_manager.go similarity index 73% rename from cardinal/query/manager.go rename to cardinal/query_manager.go index f3910d12e..d825337c9 100644 --- a/cardinal/query/manager.go +++ b/cardinal/query_manager.go @@ -1,4 +1,4 @@ -package query +package cardinal import ( "github.com/rotisserie/eris" @@ -6,19 +6,19 @@ import ( "pkg.world.dev/world-engine/cardinal/types/engine" ) -type Manager struct { +type QueryManager struct { registeredQueries map[string]engine.Query } -func NewManager() *Manager { - return &Manager{ +func NewQueryManager() *QueryManager { + return &QueryManager{ registeredQueries: make(map[string]engine.Query), } } // RegisterQuery registers a query with the query manager. // There can only be one query with a given name. -func (m *Manager) RegisterQuery(name string, query engine.Query) error { +func (m *QueryManager) RegisterQuery(name string, query engine.Query) error { // Check that the query is not already registered if err := m.isQueryNameUnique(name); err != nil { return err @@ -31,7 +31,7 @@ func (m *Manager) RegisterQuery(name string, query engine.Query) error { } // GetRegisteredQueries returns all the registered queries. -func (m *Manager) GetRegisteredQueries() []engine.Query { +func (m *QueryManager) GetRegisteredQueries() []engine.Query { registeredQueries := make([]engine.Query, 0, len(m.registeredQueries)) for _, query := range m.registeredQueries { registeredQueries = append(registeredQueries, query) @@ -40,7 +40,7 @@ func (m *Manager) GetRegisteredQueries() []engine.Query { } // GetQueryByName returns a query corresponding to its name. -func (m *Manager) GetQueryByName(name string) (engine.Query, error) { +func (m *QueryManager) GetQueryByName(name string) (engine.Query, error) { query, ok := m.registeredQueries[name] if !ok { return nil, eris.Errorf("query %q is not registered", name) @@ -48,7 +48,7 @@ func (m *Manager) GetQueryByName(name string) (engine.Query, error) { return query, nil } -func (m *Manager) isQueryNameUnique(name string) error { +func (m *QueryManager) isQueryNameUnique(name string) error { if _, ok := m.registeredQueries[name]; ok { return eris.Errorf("query %q is already registered", name) } diff --git a/cardinal/query/query_test.go b/cardinal/query_test.go similarity index 96% rename from cardinal/query/query_test.go rename to cardinal/query_test.go index 25307a577..1fea4efb7 100644 --- a/cardinal/query/query_test.go +++ b/cardinal/query_test.go @@ -1,4 +1,4 @@ -package query_test +package cardinal_test import ( "errors" @@ -6,7 +6,6 @@ import ( "pkg.world.dev/world-engine/assert" "pkg.world.dev/world-engine/cardinal" - "pkg.world.dev/world-engine/cardinal/query" "pkg.world.dev/world-engine/cardinal/search/filter" "pkg.world.dev/world-engine/cardinal/testutils" "pkg.world.dev/world-engine/cardinal/types" @@ -71,7 +70,7 @@ func TestNewQueryTypeWithEVMSupport(t *testing.T) { ) (*FooReply, error) { return &FooReply{}, errors.New("this function should never get called") }, - query.WithQueryEVMSupport[FooReq, FooReply](), + cardinal.WithQueryEVMSupport[FooReq, FooReply](), ) } @@ -153,7 +152,7 @@ func TestQueryEVM(t *testing.T) { ) (*FooReply, error) { return &expectedReply, nil }, - query.WithQueryEVMSupport[FooRequest, FooReply](), + cardinal.WithQueryEVMSupport[FooRequest, FooReply](), ) assert.NilError(t, err) diff --git a/cardinal/router/iterator/iterator_test.go b/cardinal/router/iterator/iterator_test.go index f0b26dff3..f6cea4008 100644 --- a/cardinal/router/iterator/iterator_test.go +++ b/cardinal/router/iterator/iterator_test.go @@ -10,14 +10,14 @@ import ( "google.golang.org/protobuf/proto" "pkg.world.dev/world-engine/assert" - "pkg.world.dev/world-engine/cardinal/message" + "pkg.world.dev/world-engine/cardinal" "pkg.world.dev/world-engine/cardinal/router/iterator" "pkg.world.dev/world-engine/cardinal/types" shard "pkg.world.dev/world-engine/rift/shard/v2" ) var _ shard.TransactionHandlerClient = &mockQuerier{} -var fooMsg = message.NewMessageType[fooIn, fooOut]("foo") +var fooMsg = cardinal.NewMessageType[fooIn, fooOut]("foo") type fooIn struct{ X int } type fooOut struct{} diff --git a/cardinal/server/receipts_test.go b/cardinal/server/receipts_test.go index 472daa257..f2f76da4c 100644 --- a/cardinal/server/receipts_test.go +++ b/cardinal/server/receipts_test.go @@ -6,7 +6,6 @@ import ( "net/http" "pkg.world.dev/world-engine/cardinal" - "pkg.world.dev/world-engine/cardinal/message" "pkg.world.dev/world-engine/cardinal/server/handler" "pkg.world.dev/world-engine/sign" ) @@ -21,7 +20,7 @@ func (s *ServerTestSuite) TestReceiptsQuery() { s.Require().NoError(err) wantErrorMessage := "THIS_ERROR_MESSAGE_SHOULD_BE_IN_THE_RECEIPT" err = cardinal.RegisterSystems(world, func(ctx cardinal.WorldContext) error { - return cardinal.EachMessage[fooIn, fooOut](ctx, func(message.TxData[fooIn]) (fooOut, error) { + return cardinal.EachMessage[fooIn, fooOut](ctx, func(cardinal.TxData[fooIn]) (fooOut, error) { if ctx.CurrentTick()%2 == 0 { return fooOut{Y: 4}, nil } diff --git a/cardinal/server/server_test.go b/cardinal/server/server_test.go index f1b2e2698..5927736be 100644 --- a/cardinal/server/server_test.go +++ b/cardinal/server/server_test.go @@ -19,9 +19,7 @@ import ( "pkg.world.dev/world-engine/assert" "pkg.world.dev/world-engine/cardinal" - "pkg.world.dev/world-engine/cardinal/message" "pkg.world.dev/world-engine/cardinal/persona/msg" - "pkg.world.dev/world-engine/cardinal/query" "pkg.world.dev/world-engine/cardinal/server/handler" "pkg.world.dev/world-engine/cardinal/server/utils" "pkg.world.dev/world-engine/cardinal/testutils" @@ -209,7 +207,7 @@ func (s *ServerTestSuite) TestQueryCustomGroup() { called = true return &SomeResponse{}, nil }, - query.WithCustomQueryGroup[SomeRequest, SomeResponse](group), + cardinal.WithCustomQueryGroup[SomeRequest, SomeResponse](group), ) s.Require().NoError(err) s.fixture.DoTick() @@ -283,7 +281,7 @@ func (s *ServerTestSuite) setupWorld(opts ...cardinal.WorldOption) { personaToPosition := make(map[string]types.EntityID) err = cardinal.RegisterSystems(s.world, func(context engine.Context) error { return cardinal.EachMessage[MoveMsgInput, MoveMessageOutput](context, - func(tx message.TxData[MoveMsgInput]) (MoveMessageOutput, error) { + func(tx cardinal.TxData[MoveMsgInput]) (MoveMessageOutput, error) { posID, exists := personaToPosition[tx.Tx.PersonaTag] if !exists { id, err := cardinal.Create(context, LocationComponent{}) diff --git a/cardinal/state_test.go b/cardinal/state_test.go index bbff4da5f..141b9f971 100644 --- a/cardinal/state_test.go +++ b/cardinal/state_test.go @@ -8,7 +8,6 @@ import ( "pkg.world.dev/world-engine/assert" "pkg.world.dev/world-engine/cardinal" "pkg.world.dev/world-engine/cardinal/iterators" - "pkg.world.dev/world-engine/cardinal/message" "pkg.world.dev/world-engine/cardinal/search/filter" "pkg.world.dev/world-engine/cardinal/testutils" "pkg.world.dev/world-engine/cardinal/types" @@ -312,7 +311,7 @@ func TestCanFindTransactionsAfterReloadingEngine(t *testing.T) { world, func(wCtx engine.Context) error { someTx, err := testutils.GetMessage[Msg, Result](wCtx) - return cardinal.EachMessage[Msg, Result](wCtx, func(tx message.TxData[Msg]) (Result, error) { + return cardinal.EachMessage[Msg, Result](wCtx, func(tx cardinal.TxData[Msg]) (Result, error) { someTx.SetResult(wCtx, tx.Hash, Result{}) return Result{}, err }) diff --git a/cardinal/testutils/testutils.go b/cardinal/testutils/testutils.go index 6bab0f4d8..45691c18d 100644 --- a/cardinal/testutils/testutils.go +++ b/cardinal/testutils/testutils.go @@ -9,7 +9,7 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/rotisserie/eris" - "pkg.world.dev/world-engine/cardinal/message" + "pkg.world.dev/world-engine/cardinal" "pkg.world.dev/world-engine/cardinal/types" "pkg.world.dev/world-engine/cardinal/types/engine" "pkg.world.dev/world-engine/sign" @@ -61,15 +61,15 @@ func UniqueSignature() *sign.Transaction { return UniqueSignatureWithName("some_persona_tag") } -func GetMessage[In any, Out any](wCtx engine.Context) (*message.MessageType[In, Out], error) { - var msg message.MessageType[In, Out] +func GetMessage[In any, Out any](wCtx engine.Context) (*cardinal.MessageType[In, Out], error) { + var msg cardinal.MessageType[In, Out] msgType := reflect.TypeOf(msg) tempRes, ok := wCtx.GetMessageByType(msgType) if !ok { return nil, eris.Errorf("Could not find %q, Message may not be registered.", msg.Name()) } var _ types.Message = &msg - res, ok := tempRes.(*message.MessageType[In, Out]) + res, ok := tempRes.(*cardinal.MessageType[In, Out]) if !ok { return &msg, eris.New("wrong type") } diff --git a/cardinal/world.go b/cardinal/world.go index 646cb5c33..f2218b64b 100644 --- a/cardinal/world.go +++ b/cardinal/world.go @@ -20,8 +20,6 @@ import ( "pkg.world.dev/world-engine/cardinal/component" "pkg.world.dev/world-engine/cardinal/gamestate" ecslog "pkg.world.dev/world-engine/cardinal/log" - "pkg.world.dev/world-engine/cardinal/message" - "pkg.world.dev/world-engine/cardinal/query" "pkg.world.dev/world-engine/cardinal/receipt" "pkg.world.dev/world-engine/cardinal/router" "pkg.world.dev/world-engine/cardinal/search" @@ -60,10 +58,10 @@ type World struct { // Core modules worldStage *worldstage.Manager - msgManager *message.Manager + msgManager *MessageManager systemManager *system.Manager componentManager *component.Manager - queryManager *query.Manager + queryManager *QueryManager router router.Router txPool *txpool.TxPool @@ -127,10 +125,10 @@ func NewWorld(opts ...WorldOption) (*World, error) { // Core modules worldStage: worldstage.NewManager(), - msgManager: message.NewManager(), + msgManager: NewMessageManager(), systemManager: system.NewManager(), componentManager: component.NewManager(&redisMetaStore), - queryManager: query.NewManager(), + queryManager: NewQueryManager(), router: nil, // Will be set if run mode is production or its injected via options txPool: txpool.New(), diff --git a/cardinal/world_recovery_test.go b/cardinal/world_recovery_test.go index 1fe26f80f..d45145750 100644 --- a/cardinal/world_recovery_test.go +++ b/cardinal/world_recovery_test.go @@ -7,7 +7,6 @@ import ( "github.com/golang/mock/gomock" "pkg.world.dev/world-engine/cardinal" - "pkg.world.dev/world-engine/cardinal/message" "pkg.world.dev/world-engine/cardinal/router/iterator" iteratormocks "pkg.world.dev/world-engine/cardinal/router/iterator/mocks" "pkg.world.dev/world-engine/cardinal/router/mocks" @@ -49,7 +48,7 @@ func TestWorldRecovery(t *testing.T) { fooResponse]( world, msgName, - message.WithMsgEVMSupport[fooMessage, fooResponse]()) + cardinal.WithMsgEVMSupport[fooMessage, fooResponse]()) g.Assert(err).IsNil() var ok bool fooTx, ok = world.GetMessageByFullName("game." + msgName) diff --git a/cardinal/world_test.go b/cardinal/world_test.go index 1dc94b543..54d8201f4 100644 --- a/cardinal/world_test.go +++ b/cardinal/world_test.go @@ -18,7 +18,6 @@ import ( "pkg.world.dev/world-engine/assert" "pkg.world.dev/world-engine/cardinal/iterators" - "pkg.world.dev/world-engine/cardinal/message" "pkg.world.dev/world-engine/cardinal/search/filter" "pkg.world.dev/world-engine/cardinal/types" "pkg.world.dev/world-engine/cardinal/types/engine" @@ -537,15 +536,15 @@ func doTickCapturePanic(ctx context.Context, world *World) (err error) { return nil } -func getMessage[In any, Out any](wCtx engine.Context) (*message.MessageType[In, Out], error) { - var msg message.MessageType[In, Out] +func getMessage[In any, Out any](wCtx engine.Context) (*MessageType[In, Out], error) { + var msg MessageType[In, Out] msgType := reflect.TypeOf(msg) tempRes, ok := wCtx.GetMessageByType(msgType) if !ok { return &msg, eris.Errorf("Could not find %s, Message may not be registered.", msg.Name()) } var _ types.Message = &msg - res, ok := tempRes.(*message.MessageType[In, Out]) + res, ok := tempRes.(*MessageType[In, Out]) if !ok { return &msg, eris.New("wrong type") } From 246023d18fbce840736922707fc3599a0e16076b Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Wed, 1 May 2024 11:19:45 -0700 Subject: [PATCH 02/76] lint stuff. --- cardinal/message.go | 4 ++-- e2e/testgames/game/query/location.go | 3 +-- e2e/testgames/game/sys/error.go | 3 +-- e2e/testgames/game/sys/join.go | 3 +-- e2e/testgames/game/sys/move.go | 3 +-- 5 files changed, 6 insertions(+), 10 deletions(-) diff --git a/cardinal/message.go b/cardinal/message.go index cc5468ce0..0573f2a50 100644 --- a/cardinal/message.go +++ b/cardinal/message.go @@ -31,10 +31,10 @@ type TxData[In any] struct { Tx *sign.Transaction } -type MessageOption[In, Out any] func(mt *MessageType[In, Out]) //nolint:revive // this is fine for now +type MessageOption[In, Out any] func(mt *MessageType[In, Out]) // MessageType manages a user defined state transition message struct. -type MessageType[In, Out any] struct { //nolint:revive // this is fine for now. +type MessageType[In, Out any] struct { id types.MessageID isIDSet bool name string diff --git a/e2e/testgames/game/query/location.go b/e2e/testgames/game/query/location.go index 1cf2d00cc..f1d4bbec4 100644 --- a/e2e/testgames/game/query/location.go +++ b/e2e/testgames/game/query/location.go @@ -7,7 +7,6 @@ import ( "github.com/argus-labs/world-engine/example/tester/game/sys" "pkg.world.dev/world-engine/cardinal" - "pkg.world.dev/world-engine/cardinal/query" ) type LocationRequest struct { @@ -40,5 +39,5 @@ func RegisterLocationQuery(world *cardinal.World) error { Y: loc.Y, }, nil }, - query.WithQueryEVMSupport[LocationRequest, LocationReply]()) + cardinal.WithQueryEVMSupport[LocationRequest, LocationReply]()) } diff --git a/e2e/testgames/game/sys/error.go b/e2e/testgames/game/sys/error.go index eb4461069..20d74b6fa 100644 --- a/e2e/testgames/game/sys/error.go +++ b/e2e/testgames/game/sys/error.go @@ -6,14 +6,13 @@ import ( "github.com/argus-labs/world-engine/example/tester/game/msg" "pkg.world.dev/world-engine/cardinal" - "pkg.world.dev/world-engine/cardinal/message" ) // Error is a system that will produce an error for any incoming Error messages. It's // used to test receipt errors. func Error(ctx cardinal.WorldContext) error { return cardinal.EachMessage[msg.ErrorInput, msg.ErrorOutput]( - ctx, func(m message.TxData[msg.ErrorInput]) (msg.ErrorOutput, error) { + ctx, func(m cardinal.TxData[msg.ErrorInput]) (msg.ErrorOutput, error) { err := errors.New(m.Msg.ErrorMsg) return msg.ErrorOutput{}, err }) diff --git a/e2e/testgames/game/sys/join.go b/e2e/testgames/game/sys/join.go index d176406be..6bddbdc29 100644 --- a/e2e/testgames/game/sys/join.go +++ b/e2e/testgames/game/sys/join.go @@ -7,7 +7,6 @@ import ( "github.com/argus-labs/world-engine/example/tester/game/msg" "pkg.world.dev/world-engine/cardinal" - "pkg.world.dev/world-engine/cardinal/message" "pkg.world.dev/world-engine/cardinal/types" ) @@ -16,7 +15,7 @@ var PlayerEntityID = make(map[string]types.EntityID) func Join(ctx cardinal.WorldContext) error { logger := ctx.Logger() return cardinal.EachMessage[msg.JoinInput, msg.JoinOutput]( - ctx, func(jtx message.TxData[msg.JoinInput]) (msg.JoinOutput, error) { + ctx, func(jtx cardinal.TxData[msg.JoinInput]) (msg.JoinOutput, error) { logger.Info().Msgf("got join transaction from: %s", jtx.Tx.PersonaTag) entityID, err := cardinal.Create(ctx, comp.Location{}, comp.Player{}) if err != nil { diff --git a/e2e/testgames/game/sys/move.go b/e2e/testgames/game/sys/move.go index 47dd1038a..7fd096ebc 100644 --- a/e2e/testgames/game/sys/move.go +++ b/e2e/testgames/game/sys/move.go @@ -7,13 +7,12 @@ import ( "github.com/argus-labs/world-engine/example/tester/game/msg" "pkg.world.dev/world-engine/cardinal" - "pkg.world.dev/world-engine/cardinal/message" ) func Move(ctx cardinal.WorldContext) error { logger := ctx.Logger() return cardinal.EachMessage[msg.MoveInput, msg.MoveOutput](ctx, - func(mtx message.TxData[msg.MoveInput]) (msg.MoveOutput, error) { + func(mtx cardinal.TxData[msg.MoveInput]) (msg.MoveOutput, error) { logger.Info().Msgf("got move transaction from: %s", mtx.Tx.PersonaTag) playerEntityID, ok := PlayerEntityID[mtx.Tx.PersonaTag] if !ok { From 14322eb14f1cdf14b096c44f412efa73b20173db Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Fri, 3 May 2024 10:58:36 -0700 Subject: [PATCH 03/76] place interface in front of message manager. --- cardinal/message_manager.go | 28 ++++++++++++++++++---------- cardinal/world.go | 2 +- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/cardinal/message_manager.go b/cardinal/message_manager.go index 86241ba14..3fd2fee69 100644 --- a/cardinal/message_manager.go +++ b/cardinal/message_manager.go @@ -9,22 +9,30 @@ import ( "pkg.world.dev/world-engine/cardinal/types" ) -type MessageManager struct { +type MessageManager interface { + RegisterMessage(msgType types.Message, msgReflectType reflect.Type) error + GetRegisteredMessages() []types.Message + GetMessageByID(id types.MessageID) types.Message + GetMessageByFullName(fullName string) (types.Message, bool) + GetMessageByType(mType reflect.Type) (types.Message, bool) +} + +type MessageManagerImpl struct { // registeredMessages maps message FullNames to a types.Message. registeredMessages map[string]types.Message registeredMessagesByType map[reflect.Type]types.Message nextMessageID types.MessageID } -func NewMessageManager() *MessageManager { - return &MessageManager{ +func NewMessageManager() MessageManager { + return &MessageManagerImpl{ registeredMessages: map[string]types.Message{}, registeredMessagesByType: map[reflect.Type]types.Message{}, nextMessageID: 1, } } -func (m *MessageManager) RegisterMessage(msgType types.Message, msgReflectType reflect.Type) error { +func (m *MessageManagerImpl) RegisterMessage(msgType types.Message, msgReflectType reflect.Type) error { fullName := msgType.FullName() // Checks if the message is already previously registered. if err := errors.Join(m.isMessageFullNameUnique(fullName), m.isMessageTypeUnique(msgReflectType)); err != nil { @@ -46,7 +54,7 @@ func (m *MessageManager) RegisterMessage(msgType types.Message, msgReflectType r } // GetRegisteredMessages returns the list of all registered messages -func (m *MessageManager) GetRegisteredMessages() []types.Message { +func (m *MessageManagerImpl) GetRegisteredMessages() []types.Message { msgs := make([]types.Message, 0, len(m.registeredMessages)) for _, msg := range m.registeredMessages { msgs = append(msgs, msg) @@ -56,7 +64,7 @@ func (m *MessageManager) GetRegisteredMessages() []types.Message { // GetMessageByID iterates over the all registered messages and returns the types.Message associated with the // MessageID. -func (m *MessageManager) GetMessageByID(id types.MessageID) types.Message { +func (m *MessageManagerImpl) GetMessageByID(id types.MessageID) types.Message { for _, msg := range m.registeredMessages { if id == msg.ID() { return msg @@ -66,18 +74,18 @@ func (m *MessageManager) GetMessageByID(id types.MessageID) types.Message { } // GetMessageByFullName returns the message with the given full name, if it exists. -func (m *MessageManager) GetMessageByFullName(fullName string) (types.Message, bool) { +func (m *MessageManagerImpl) GetMessageByFullName(fullName string) (types.Message, bool) { msg, ok := m.registeredMessages[fullName] return msg, ok } -func (m *MessageManager) GetMessageByType(mType reflect.Type) (types.Message, bool) { +func (m *MessageManagerImpl) GetMessageByType(mType reflect.Type) (types.Message, bool) { msg, ok := m.registeredMessagesByType[mType] return msg, ok } // isMessageFullNameUnique checks if the message name already exist in messages map. -func (m *MessageManager) isMessageFullNameUnique(fullName string) error { +func (m *MessageManagerImpl) isMessageFullNameUnique(fullName string) error { _, ok := m.registeredMessages[fullName] if ok { return eris.Errorf("message %q is already registered", fullName) @@ -86,7 +94,7 @@ func (m *MessageManager) isMessageFullNameUnique(fullName string) error { } // isMessageTypeUnique checks if the message type name already exist in messages map. -func (m *MessageManager) isMessageTypeUnique(msgReflectType reflect.Type) error { +func (m *MessageManagerImpl) isMessageTypeUnique(msgReflectType reflect.Type) error { _, ok := m.registeredMessagesByType[msgReflectType] if ok { return eris.Errorf("message type %q is already registered", msgReflectType) diff --git a/cardinal/world.go b/cardinal/world.go index f2218b64b..10ce2d62b 100644 --- a/cardinal/world.go +++ b/cardinal/world.go @@ -58,7 +58,7 @@ type World struct { // Core modules worldStage *worldstage.Manager - msgManager *MessageManager + msgManager MessageManager systemManager *system.Manager componentManager *component.Manager queryManager *QueryManager From 5665866aa4cceb3d9a16567d2998690b041f1e93 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Fri, 3 May 2024 11:11:54 -0700 Subject: [PATCH 04/76] place interface in front of query manager. --- cardinal/query_manager.go | 20 +++++++++++++------- cardinal/world.go | 2 +- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/cardinal/query_manager.go b/cardinal/query_manager.go index d825337c9..a2da084c9 100644 --- a/cardinal/query_manager.go +++ b/cardinal/query_manager.go @@ -6,19 +6,25 @@ import ( "pkg.world.dev/world-engine/cardinal/types/engine" ) -type QueryManager struct { +type QueryManager interface { + RegisterQuery(name string, query engine.Query) error + GetRegisteredQueries() []engine.Query + GetQueryByName(name string) (engine.Query, error) +} + +type QueryManagerImpl struct { registeredQueries map[string]engine.Query } -func NewQueryManager() *QueryManager { - return &QueryManager{ +func NewQueryManager() QueryManager { + return &QueryManagerImpl{ registeredQueries: make(map[string]engine.Query), } } // RegisterQuery registers a query with the query manager. // There can only be one query with a given name. -func (m *QueryManager) RegisterQuery(name string, query engine.Query) error { +func (m *QueryManagerImpl) RegisterQuery(name string, query engine.Query) error { // Check that the query is not already registered if err := m.isQueryNameUnique(name); err != nil { return err @@ -31,7 +37,7 @@ func (m *QueryManager) RegisterQuery(name string, query engine.Query) error { } // GetRegisteredQueries returns all the registered queries. -func (m *QueryManager) GetRegisteredQueries() []engine.Query { +func (m *QueryManagerImpl) GetRegisteredQueries() []engine.Query { registeredQueries := make([]engine.Query, 0, len(m.registeredQueries)) for _, query := range m.registeredQueries { registeredQueries = append(registeredQueries, query) @@ -40,7 +46,7 @@ func (m *QueryManager) GetRegisteredQueries() []engine.Query { } // GetQueryByName returns a query corresponding to its name. -func (m *QueryManager) GetQueryByName(name string) (engine.Query, error) { +func (m *QueryManagerImpl) GetQueryByName(name string) (engine.Query, error) { query, ok := m.registeredQueries[name] if !ok { return nil, eris.Errorf("query %q is not registered", name) @@ -48,7 +54,7 @@ func (m *QueryManager) GetQueryByName(name string) (engine.Query, error) { return query, nil } -func (m *QueryManager) isQueryNameUnique(name string) error { +func (m *QueryManagerImpl) isQueryNameUnique(name string) error { if _, ok := m.registeredQueries[name]; ok { return eris.Errorf("query %q is already registered", name) } diff --git a/cardinal/world.go b/cardinal/world.go index 10ce2d62b..e985e5e61 100644 --- a/cardinal/world.go +++ b/cardinal/world.go @@ -61,7 +61,7 @@ type World struct { msgManager MessageManager systemManager *system.Manager componentManager *component.Manager - queryManager *QueryManager + queryManager QueryManager router router.Router txPool *txpool.TxPool From 48dfe33d48cefda5aeefcf8d3186921c9b941f75 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Fri, 3 May 2024 14:09:47 -0700 Subject: [PATCH 05/76] use interface composition for query manager. --- cardinal/cardinal.go | 2 +- cardinal/world.go | 16 +++++----------- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/cardinal/cardinal.go b/cardinal/cardinal.go index c2e649109..331ac5f5f 100644 --- a/cardinal/cardinal.go +++ b/cardinal/cardinal.go @@ -170,7 +170,7 @@ func RegisterQuery[Request any, Reply any]( return err } - return w.queryManager.RegisterQuery(name, q) + return w.RegisterQuery(name, q) } // Create creates a single entity in the world, and returns the id of the newly created entity. diff --git a/cardinal/world.go b/cardinal/world.go index e985e5e61..17c24eedf 100644 --- a/cardinal/world.go +++ b/cardinal/world.go @@ -61,9 +61,9 @@ type World struct { msgManager MessageManager systemManager *system.Manager componentManager *component.Manager - queryManager QueryManager - router router.Router - txPool *txpool.TxPool + QueryManager + router router.Router + txPool *txpool.TxPool // Receipt receiptHistory *receipt.History @@ -128,7 +128,7 @@ func NewWorld(opts ...WorldOption) (*World, error) { msgManager: NewMessageManager(), systemManager: system.NewManager(), componentManager: component.NewManager(&redisMetaStore), - queryManager: NewQueryManager(), + QueryManager: NewQueryManager(), router: nil, // Will be set if run mode is production or its injected via options txPool: txpool.New(), @@ -346,7 +346,7 @@ func (w *World) StartGame() error { if len(w.msgManager.GetRegisteredMessages()) == 0 { log.Warn().Msg("No messages registered") } - if len(w.queryManager.GetRegisteredQueries()) == 0 { + if len(w.GetRegisteredQueries()) == 0 { log.Warn().Msg("No queries registered") } if len(w.systemManager.GetRegisteredSystemNames()) == 0 { @@ -596,9 +596,6 @@ func (w *World) StoreReader() gamestate.Reader { return w.entityStore.ToReadOnly() } -func (w *World) GetRegisteredQueries() []engine.Query { - return w.queryManager.GetRegisteredQueries() -} func (w *World) GetRegisteredMessages() []types.Message { return w.msgManager.GetRegisteredMessages() } @@ -612,9 +609,6 @@ func (w *World) GetRegisteredSystemNames() []string { func (w *World) GetReadOnlyCtx() engine.Context { return NewReadOnlyWorldContext(w) } -func (w *World) GetQueryByName(name string) (engine.Query, error) { - return w.queryManager.GetQueryByName(name) -} func (w *World) GetMessageByID(id types.MessageID) (types.Message, bool) { msg := w.msgManager.GetMessageByID(id) From d7847e8b64aff117ab6b9f090c338738aed4dc91 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Mon, 6 May 2024 17:06:21 -0700 Subject: [PATCH 06/76] changed. Issue with QUeries in world.go --- cardinal/benchmark/benchmark_test.go | 3 +- cardinal/cardinal.go | 23 +++--- cardinal/cardinal_test.go | 31 ++++--- cardinal/ecs_test.go | 3 +- cardinal/engine_test.go | 19 +++-- cardinal/errors_test.go | 59 +++++++------- cardinal/example_messagetype_test.go | 3 +- cardinal/imported.go | 7 -- cardinal/log/log_test.go | 5 +- cardinal/message.go | 11 ++- cardinal/persona/persona_test.go | 19 +++-- .../{persona/query => }/persona_signer.go | 5 +- cardinal/plugin_persona.go | 14 ++-- cardinal/query.go | 57 +++++++++++-- cardinal/query_manager.go | 20 +++-- cardinal/query_test.go | 9 +-- cardinal/search/composedsearch.go | 37 +++++---- cardinal/search/context.go | 49 ++++++++++++ cardinal/search/filtercomponent.go | 9 +-- cardinal/search/search.go | 25 +++--- cardinal/search/util.go | 3 +- cardinal/search_test.go | 7 +- cardinal/server/event_test.go | 11 ++- cardinal/server/handler/cql.go | 4 +- cardinal/server/handler/debug.go | 4 +- cardinal/server/handler/query.go | 8 +- cardinal/server/handler/receipts.go | 4 +- cardinal/server/handler/tx.go | 8 +- cardinal/server/handler/world.go | 4 +- cardinal/server/receipts_test.go | 2 +- cardinal/server/server.go | 20 +++-- cardinal/server/server_test.go | 7 +- cardinal/server/types/provider.go | 42 +++++++++- cardinal/state_test.go | 5 +- cardinal/system.go | 7 +- cardinal/system_test.go | 11 ++- cardinal/testutils/testutils.go | 3 +- cardinal/types/engine/context.go | 80 ++++++++----------- cardinal/types/engine/query.go | 46 +++++------ cardinal/util.go | 3 +- cardinal/world.go | 20 +++-- cardinal/world_context.go | 45 +++++++++-- cardinal/world_persona_test.go | 3 +- cardinal/world_test.go | 27 +++---- 44 files changed, 451 insertions(+), 331 deletions(-) delete mode 100644 cardinal/imported.go rename cardinal/{persona/query => }/persona_signer.go (89%) create mode 100644 cardinal/search/context.go diff --git a/cardinal/benchmark/benchmark_test.go b/cardinal/benchmark/benchmark_test.go index 29740ffb8..4327751b6 100644 --- a/cardinal/benchmark/benchmark_test.go +++ b/cardinal/benchmark/benchmark_test.go @@ -13,7 +13,6 @@ import ( "pkg.world.dev/world-engine/cardinal/search/filter" "pkg.world.dev/world-engine/cardinal/testutils" "pkg.world.dev/world-engine/cardinal/types" - "pkg.world.dev/world-engine/cardinal/types/engine" ) type Health struct { @@ -35,7 +34,7 @@ func setupWorld(t testing.TB, numOfEntities int, enableHealthSystem bool) *testu if enableHealthSystem { err := cardinal.RegisterSystems( world, - func(wCtx engine.Context) error { + func(wCtx cardinal.Context) error { q := cardinal.NewSearch().Entity(filter.Contains(filter.Component[Health]())) err := q.Each(wCtx, func(id types.EntityID) bool { diff --git a/cardinal/cardinal.go b/cardinal/cardinal.go index 7ffb70196..aba9bc163 100644 --- a/cardinal/cardinal.go +++ b/cardinal/cardinal.go @@ -11,7 +11,6 @@ import ( "pkg.world.dev/world-engine/cardinal/iterators" "pkg.world.dev/world-engine/cardinal/search" "pkg.world.dev/world-engine/cardinal/types" - "pkg.world.dev/world-engine/cardinal/types/engine" "pkg.world.dev/world-engine/cardinal/worldstage" ) @@ -55,7 +54,7 @@ type Search = search.Search // return true // })) -func FilterFunction[T types.Component](f func(comp T) bool) func(ctx engine.Context, id types.EntityID) (bool, error) { +func FilterFunction[T types.Component](f func(comp T) bool) func(ctx search.Context, id types.EntityID) (bool, error) { return search.ComponentFilter[T](f) } @@ -110,7 +109,7 @@ func MustRegisterComponent[T types.Component](w *World) { } } -func EachMessage[In any, Out any](wCtx engine.Context, fn func(TxData[In]) (Out, error)) error { +func EachMessage[In any, Out any](wCtx Context, fn func(TxData[In]) (Out, error)) error { var msg MessageType[In, Out] msgType := reflect.TypeOf(msg) tempRes, ok := wCtx.GetMessageByType(msgType) @@ -153,7 +152,7 @@ func RegisterMessage[In any, Out any](world *World, name string, opts ...Message func RegisterQuery[Request any, Reply any]( w *World, name string, - handler func(wCtx engine.Context, req *Request) (*Reply, error), + handler func(wCtx Context, req *Request) (*Reply, error), opts ...QueryOption[Request, Reply], ) (err error) { if w.worldStage.Current() != worldstage.Init { @@ -174,7 +173,7 @@ func RegisterQuery[Request any, Reply any]( // Create creates a single entity in the world, and returns the id of the newly created entity. // At least 1 component must be provided. -func Create(wCtx engine.Context, components ...types.Component) (_ types.EntityID, err error) { +func Create(wCtx Context, components ...types.Component) (_ types.EntityID, err error) { // We don't handle panics here because we let CreateMany handle it for us entityIDs, err := CreateMany(wCtx, 1, components...) if err != nil { @@ -185,7 +184,7 @@ func Create(wCtx engine.Context, components ...types.Component) (_ types.EntityI // CreateMany creates multiple entities in the world, and returns the slice of ids for the newly created // entities. At least 1 component must be provided. -func CreateMany(wCtx engine.Context, num int, components ...types.Component) (entityIDs []types.EntityID, err error) { +func CreateMany(wCtx Context, num int, components ...types.Component) (entityIDs []types.EntityID, err error) { defer func() { panicOnFatalError(wCtx, err) }() // Error if the context is read only @@ -233,7 +232,7 @@ func CreateMany(wCtx engine.Context, num int, components ...types.Component) (en } // SetComponent sets component data to the entity. -func SetComponent[T types.Component](wCtx engine.Context, id types.EntityID, component *T) (err error) { +func SetComponent[T types.Component](wCtx Context, id types.EntityID, component *T) (err error) { defer func() { panicOnFatalError(wCtx, err) }() // Error if the context is read only @@ -265,7 +264,7 @@ func SetComponent[T types.Component](wCtx engine.Context, id types.EntityID, com } // GetComponent returns component data from the entity. -func GetComponent[T types.Component](wCtx engine.Context, id types.EntityID) (comp *T, err error) { +func GetComponent[T types.Component](wCtx Context, id types.EntityID) (comp *T, err error) { defer func() { panicOnFatalError(wCtx, err) }() // Get the component metadata @@ -295,7 +294,7 @@ func GetComponent[T types.Component](wCtx engine.Context, id types.EntityID) (co return comp, nil } -func UpdateComponent[T types.Component](wCtx engine.Context, id types.EntityID, fn func(*T) *T) (err error) { +func UpdateComponent[T types.Component](wCtx Context, id types.EntityID, fn func(*T) *T) (err error) { defer func() { panicOnFatalError(wCtx, err) }() // Error if the context is read only @@ -321,7 +320,7 @@ func UpdateComponent[T types.Component](wCtx engine.Context, id types.EntityID, return nil } -func AddComponentTo[T types.Component](wCtx engine.Context, id types.EntityID) (err error) { +func AddComponentTo[T types.Component](wCtx Context, id types.EntityID) (err error) { defer func() { panicOnFatalError(wCtx, err) }() // Error if the context is read only @@ -346,7 +345,7 @@ func AddComponentTo[T types.Component](wCtx engine.Context, id types.EntityID) ( } // RemoveComponentFrom removes a component from an entity. -func RemoveComponentFrom[T types.Component](wCtx engine.Context, id types.EntityID) (err error) { +func RemoveComponentFrom[T types.Component](wCtx Context, id types.EntityID) (err error) { defer func() { panicOnFatalError(wCtx, err) }() // Error if the context is read only @@ -371,7 +370,7 @@ func RemoveComponentFrom[T types.Component](wCtx engine.Context, id types.Entity } // Remove removes the given Entity from the world. -func Remove(wCtx engine.Context, id types.EntityID) (err error) { +func Remove(wCtx Context, id types.EntityID) (err error) { defer func() { panicOnFatalError(wCtx, err) }() // Error if the context is read only diff --git a/cardinal/cardinal_test.go b/cardinal/cardinal_test.go index 07215e4be..cdbf08b1c 100644 --- a/cardinal/cardinal_test.go +++ b/cardinal/cardinal_test.go @@ -23,7 +23,6 @@ import ( "pkg.world.dev/world-engine/cardinal/search/filter" "pkg.world.dev/world-engine/cardinal/testutils" "pkg.world.dev/world-engine/cardinal/types" - "pkg.world.dev/world-engine/cardinal/types/engine" "pkg.world.dev/world-engine/sign" ) @@ -70,7 +69,7 @@ func TestForEachTransaction(t *testing.T) { someMsgName := "some_msg" assert.NilError(t, cardinal.RegisterMessage[SomeMsgRequest, SomeMsgResponse](world, someMsgName)) - err := cardinal.RegisterSystems(world, func(wCtx engine.Context) error { + err := cardinal.RegisterSystems(world, func(wCtx cardinal.Context) error { return cardinal.EachMessage[SomeMsgRequest, SomeMsgResponse](wCtx, func(t cardinal.TxData[SomeMsgRequest]) (result SomeMsgResponse, err error) { if t.Msg.GenerateError { @@ -146,7 +145,7 @@ func TestSystemsAreExecutedDuringGameTick(t *testing.T) { err := cardinal.RegisterSystems( world, - func(wCtx engine.Context) error { + func(wCtx cardinal.Context) error { search := cardinal.NewSearch().Entity(filter.Exact(filter.Component[CounterComponent]())) id := search.MustFirst(wCtx) return cardinal.UpdateComponent[CounterComponent]( @@ -180,7 +179,7 @@ func TestTransactionAreAppliedToSomeEntities(t *testing.T) { err := cardinal.RegisterSystems( world, - func(wCtx engine.Context) error { + func(wCtx cardinal.Context) error { return cardinal.EachMessage[*ModifyScoreMsg, *EmptyMsgResult](wCtx, func(msData cardinal.TxData[*ModifyScoreMsg]) (*EmptyMsgResult, error) { ms := msData.Msg @@ -256,7 +255,7 @@ func TestAddToPoolDuringTickDoesNotTimeout(t *testing.T) { // to verify that the addition of more transactions doesn't block. err := cardinal.RegisterSystems( world, - func(engine.Context) error { + func(cardinal.Context) error { <-inSystemCh <-inSystemCh return nil @@ -324,7 +323,7 @@ func TestTransactionsAreExecutedAtNextTick(t *testing.T) { // commands mid-tick. err := cardinal.RegisterSystems( world, - func(wCtx engine.Context) error { + func(wCtx cardinal.Context) error { modScoreMsg, err := testutils.GetMessage[*ModifyScoreMsg, *EmptyMsgResult](wCtx) if err != nil { return err @@ -338,7 +337,7 @@ func TestTransactionsAreExecutedAtNextTick(t *testing.T) { err = cardinal.RegisterSystems( world, - func(wCtx engine.Context) error { + func(wCtx cardinal.Context) error { modScoreMsg, err := testutils.GetMessage[*ModifyScoreMsg, *EmptyMsgResult](wCtx) if err != nil { return err @@ -442,7 +441,7 @@ func TestCanGetTransactionErrorsAndResults(t *testing.T) { err := cardinal.RegisterSystems( world, - func(wCtx engine.Context) error { + func(wCtx cardinal.Context) error { // This new In function returns a triplet of information: // 1) The transaction input // 2) An EntityID that uniquely identifies this specific transaction @@ -505,7 +504,7 @@ func TestSystemCanFindErrorsFromEarlierSystem(t *testing.T) { systemCalls := 0 err := cardinal.RegisterSystems( world, - func(wCtx engine.Context) error { + func(wCtx cardinal.Context) error { systemCalls++ numTx, err := testutils.GetMessage[MsgIn, MsgOut](wCtx) if err != nil { @@ -524,7 +523,7 @@ func TestSystemCanFindErrorsFromEarlierSystem(t *testing.T) { err = cardinal.RegisterSystems( world, - func(wCtx engine.Context) error { + func(wCtx cardinal.Context) error { systemCalls++ numTx, err := testutils.GetMessage[MsgIn, MsgOut](wCtx) if err != nil { @@ -567,7 +566,7 @@ func TestSystemCanClobberTransactionResult(t *testing.T) { secondResult := MsgOut{5678} err := cardinal.RegisterSystems( world, - func(wCtx engine.Context) error { + func(wCtx cardinal.Context) error { systemCalls++ numTx, err := testutils.GetMessage[MsgIn, MsgOut](wCtx) assert.NilError(t, err) @@ -584,7 +583,7 @@ func TestSystemCanClobberTransactionResult(t *testing.T) { err = cardinal.RegisterSystems( world, - func(wCtx engine.Context) error { + func(wCtx cardinal.Context) error { systemCalls++ numTx, err := testutils.GetMessage[MsgIn, MsgOut](wCtx) if err != nil { @@ -627,7 +626,7 @@ func TestTransactionExample(t *testing.T) { assert.NilError(t, cardinal.RegisterComponent[Health](world)) msgName := "add_health" assert.NilError(t, cardinal.RegisterMessage[AddHealthToEntityTx, AddHealthToEntityResult](world, msgName)) - err := cardinal.RegisterSystems(world, func(wCtx engine.Context) error { + err := cardinal.RegisterSystems(world, func(wCtx cardinal.Context) error { // test "In" method addHealthToEntity, err := testutils.GetMessage[AddHealthToEntityTx, AddHealthToEntityResult](wCtx) if err != nil { @@ -744,7 +743,7 @@ func TestCanQueryInsideSystem(t *testing.T) { assert.NilError(t, cardinal.RegisterComponent[Foo](world)) gotNumOfEntities := 0 - err := cardinal.RegisterSystems(world, func(wCtx engine.Context) error { + err := cardinal.RegisterSystems(world, func(wCtx cardinal.Context) error { err := cardinal.NewSearch().Entity(filter.Exact(filter.Component[Foo]())).Each(wCtx, func(types.EntityID) bool { gotNumOfEntities++ return true @@ -768,7 +767,7 @@ func TestCanGetTimestampFromWorldContext(t *testing.T) { var ts uint64 tf := testutils.NewTestFixture(t, nil) world := tf.World - err := cardinal.RegisterSystems(world, func(context engine.Context) error { + err := cardinal.RegisterSystems(world, func(context cardinal.Context) error { ts = context.Timestamp() return nil }) @@ -789,7 +788,7 @@ func TestShutdownViaSignal(t *testing.T) { httpBaseURL := "http://" + addr assert.NilError(t, cardinal.RegisterComponent[Foo](world)) wantNumOfEntities := 10 - err := cardinal.RegisterInitSystems(world, func(wCtx engine.Context) error { + err := cardinal.RegisterInitSystems(world, func(wCtx cardinal.Context) error { _, err := cardinal.CreateMany(wCtx, wantNumOfEntities/2, Foo{}) if err != nil { return err diff --git a/cardinal/ecs_test.go b/cardinal/ecs_test.go index f968e5aff..232b79ad6 100644 --- a/cardinal/ecs_test.go +++ b/cardinal/ecs_test.go @@ -11,7 +11,6 @@ import ( "pkg.world.dev/world-engine/cardinal/search/filter" "pkg.world.dev/world-engine/cardinal/testutils" "pkg.world.dev/world-engine/cardinal/types" - "pkg.world.dev/world-engine/cardinal/types/engine" ) type EnergyComponent struct { @@ -75,7 +74,7 @@ func (WeaponEnergy) Name() string { return "weaponsEnergy" } -func UpdateEnergySystem(wCtx engine.Context) error { +func UpdateEnergySystem(wCtx cardinal.Context) error { var errs []error q := cardinal.NewSearch().Entity(filter.Contains(filter.Component[EnergyComponent]())) err := q.Each(wCtx, diff --git a/cardinal/engine_test.go b/cardinal/engine_test.go index aeb50d546..b478c6b2f 100644 --- a/cardinal/engine_test.go +++ b/cardinal/engine_test.go @@ -13,7 +13,6 @@ import ( "pkg.world.dev/world-engine/cardinal/router/iterator" "pkg.world.dev/world-engine/cardinal/router/mocks" "pkg.world.dev/world-engine/cardinal/testutils" - "pkg.world.dev/world-engine/cardinal/types/engine" "pkg.world.dev/world-engine/cardinal/types/txpool" "pkg.world.dev/world-engine/sign" ) @@ -140,7 +139,7 @@ func TestCannotWaitForNextTickAfterEngineIsShutDown(t *testing.T) { var returnErr error err := cardinal.RegisterSystems( world, - func(wCtx engine.Context) error { + func(wCtx cardinal.Context) error { return cardinal.EachMessage[FooIn, FooOut]( wCtx, func(cardinal.TxData[FooIn]) (FooOut, error) { return returnVal, returnErr @@ -202,7 +201,7 @@ func TestEVMTxConsume(t *testing.T) { var returnVal FooOut var returnErr error err = cardinal.RegisterSystems(world, - func(eCtx cardinal.WorldContext) error { + func(eCtx cardinal.Context) error { return cardinal.EachMessage[FooIn, FooOut]( eCtx, func(cardinal.TxData[FooIn]) (FooOut, error) { return returnVal, returnErr @@ -251,15 +250,15 @@ func TestEVMTxConsume(t *testing.T) { func TestAddSystems(t *testing.T) { count := 0 - sys1 := func(engine.Context) error { + sys1 := func(cardinal.Context) error { count++ return nil } - sys2 := func(engine.Context) error { + sys2 := func(cardinal.Context) error { count++ return nil } - sys3 := func(engine.Context) error { + sys3 := func(cardinal.Context) error { count++ return nil } @@ -283,13 +282,13 @@ func TestSystemExecutionOrder(t *testing.T) { order := make([]int, 0, 3) err := cardinal.RegisterSystems( world, - func(engine.Context) error { + func(cardinal.Context) error { order = append(order, 1) return nil - }, func(engine.Context) error { + }, func(cardinal.Context) error { order = append(order, 2) return nil - }, func(engine.Context) error { + }, func(cardinal.Context) error { order = append(order, 3) return nil }, @@ -447,7 +446,7 @@ func TestRecoverFromChain(t *testing.T) { assert.NilError(t, cardinal.RegisterMessage[fooMsg, fooMsgRes](world, fooMsgName)) fooMessages := 0 - err := cardinal.RegisterSystems(world, func(engineContext cardinal.WorldContext) error { + err := cardinal.RegisterSystems(world, func(engineContext cardinal.Context) error { return cardinal.EachMessage[fooMsg, fooMsgRes](engineContext, func(cardinal.TxData[fooMsg]) (fooMsgRes, error) { fooMessages++ return fooMsgRes{}, nil diff --git a/cardinal/errors_test.go b/cardinal/errors_test.go index 3a8df6686..2326328e7 100644 --- a/cardinal/errors_test.go +++ b/cardinal/errors_test.go @@ -11,7 +11,6 @@ import ( "pkg.world.dev/world-engine/cardinal/component" "pkg.world.dev/world-engine/cardinal/search/filter" "pkg.world.dev/world-engine/cardinal/testutils" - "pkg.world.dev/world-engine/cardinal/types/engine" ) // TestSystemsReturnNonFatalErrors ensures system will surface non-fatal read and write errors to the user. @@ -19,19 +18,19 @@ func TestSystemsReturnNonFatalErrors(t *testing.T) { const nonExistentEntityID = 999 testCases := []struct { name string - testFn func(engine.Context) error + testFn func(cardinal.Context) error wantErr error }{ { name: "AddComponentTo_BadEntity", - testFn: func(wCtx engine.Context) error { + testFn: func(wCtx cardinal.Context) error { return cardinal.AddComponentTo[Foo](wCtx, nonExistentEntityID) }, wantErr: cardinal.ErrEntityDoesNotExist, }, { name: "AddComponentTo_ComponentAlreadyOnEntity", - testFn: func(wCtx engine.Context) error { + testFn: func(wCtx cardinal.Context) error { id, err := cardinal.Create(wCtx, Foo{}) assert.Check(t, err == nil) return cardinal.AddComponentTo[Foo](wCtx, id) @@ -40,14 +39,14 @@ func TestSystemsReturnNonFatalErrors(t *testing.T) { }, { name: "RemoveComponentFrom_BadEntity", - testFn: func(wCtx engine.Context) error { + testFn: func(wCtx cardinal.Context) error { return cardinal.RemoveComponentFrom[Foo](wCtx, nonExistentEntityID) }, wantErr: cardinal.ErrEntityDoesNotExist, }, { name: "RemoveComponentFrom_ComponentNotOnEntity", - testFn: func(wCtx engine.Context) error { + testFn: func(wCtx cardinal.Context) error { id, err := cardinal.Create(wCtx, Foo{}) assert.Check(t, err == nil) return cardinal.RemoveComponentFrom[Bar](wCtx, id) @@ -56,7 +55,7 @@ func TestSystemsReturnNonFatalErrors(t *testing.T) { }, { name: "RemoveComponentFrom_EntityMustHaveAtLeastOneComponent", - testFn: func(wCtx engine.Context) error { + testFn: func(wCtx cardinal.Context) error { id, err := cardinal.Create(wCtx, Foo{}) assert.Check(t, err == nil) return cardinal.RemoveComponentFrom[Foo](wCtx, id) @@ -65,7 +64,7 @@ func TestSystemsReturnNonFatalErrors(t *testing.T) { }, { name: "cardinal.GetComponent_BadEntity", - testFn: func(wCtx engine.Context) error { + testFn: func(wCtx cardinal.Context) error { _, err := cardinal.GetComponent[Foo](wCtx, nonExistentEntityID) return err }, @@ -73,7 +72,7 @@ func TestSystemsReturnNonFatalErrors(t *testing.T) { }, { name: "cardinal.GetComponent_ComponentNotOnEntity", - testFn: func(wCtx engine.Context) error { + testFn: func(wCtx cardinal.Context) error { id, err := cardinal.Create(wCtx, Foo{}) assert.Check(t, err == nil) _, err = cardinal.GetComponent[Bar](wCtx, id) @@ -83,14 +82,14 @@ func TestSystemsReturnNonFatalErrors(t *testing.T) { }, { name: "SetComponent_BadEntity", - testFn: func(wCtx engine.Context) error { + testFn: func(wCtx cardinal.Context) error { return cardinal.SetComponent[Foo](wCtx, nonExistentEntityID, &Foo{}) }, wantErr: cardinal.ErrEntityDoesNotExist, }, { name: "SetComponent_ComponentNotOnEntity", - testFn: func(wCtx engine.Context) error { + testFn: func(wCtx cardinal.Context) error { id, err := cardinal.Create(wCtx, Foo{}) assert.Check(t, err == nil) return cardinal.SetComponent[Bar](wCtx, id, &Bar{}) @@ -99,7 +98,7 @@ func TestSystemsReturnNonFatalErrors(t *testing.T) { }, { name: "UpdateComponent_BadEntity", - testFn: func(wCtx engine.Context) error { + testFn: func(wCtx cardinal.Context) error { return cardinal.UpdateComponent[Foo](wCtx, nonExistentEntityID, func(f *Foo) *Foo { return f }) @@ -108,7 +107,7 @@ func TestSystemsReturnNonFatalErrors(t *testing.T) { }, { name: "UpdateComponent_ComponentNotOnEntity", - testFn: func(wCtx engine.Context) error { + testFn: func(wCtx cardinal.Context) error { id, err := cardinal.Create(wCtx, Foo{}) assert.Check(t, err == nil) return cardinal.UpdateComponent[Bar](wCtx, id, func(b *Bar) *Bar { @@ -119,7 +118,7 @@ func TestSystemsReturnNonFatalErrors(t *testing.T) { }, { name: "Remove_EntityDoesNotExist", - testFn: func(wCtx engine.Context) error { + testFn: func(wCtx cardinal.Context) error { return cardinal.Remove(wCtx, nonExistentEntityID) }, wantErr: cardinal.ErrEntityDoesNotExist, @@ -132,7 +131,7 @@ func TestSystemsReturnNonFatalErrors(t *testing.T) { world, tick := tf.World, tf.DoTick assert.NilError(t, cardinal.RegisterComponent[Foo](world)) assert.NilError(t, cardinal.RegisterComponent[Bar](world)) - err := cardinal.RegisterInitSystems(world, func(wCtx engine.Context) error { + err := cardinal.RegisterInitSystems(world, func(wCtx cardinal.Context) error { defer func() { // In systems, Cardinal is designed to panic when a fatal error is encountered. // This test is not supposed to panic, but if it does panic it happens in a non-main thread which @@ -164,11 +163,11 @@ func TestSystemsPanicOnComponentHasNotBeenRegistered(t *testing.T) { testCases := []struct { name string // Every test is expected to panic, so no return error is needed - panicFn func(engine.Context) + panicFn func(cardinal.Context) }{ { name: "cardinal.AddComponentTo", - panicFn: func(wCtx engine.Context) { + panicFn: func(wCtx cardinal.Context) { id, err := cardinal.Create(wCtx, Foo{}) assert.Check(t, err == nil) _ = cardinal.AddComponentTo[UnregisteredComp](wCtx, id) @@ -176,7 +175,7 @@ func TestSystemsPanicOnComponentHasNotBeenRegistered(t *testing.T) { }, { name: "cardinal.RemoveComponentFrom", - panicFn: func(wCtx engine.Context) { + panicFn: func(wCtx cardinal.Context) { id, err := cardinal.Create(wCtx, Foo{}, Bar{}) assert.Check(t, err == nil) _ = cardinal.RemoveComponentFrom[UnregisteredComp](wCtx, id) @@ -184,7 +183,7 @@ func TestSystemsPanicOnComponentHasNotBeenRegistered(t *testing.T) { }, { name: "cardinal.GetComponent", - panicFn: func(wCtx engine.Context) { + panicFn: func(wCtx cardinal.Context) { id, err := cardinal.Create(wCtx, Foo{}) assert.Check(t, err == nil) _, _ = cardinal.GetComponent[UnregisteredComp](wCtx, id) @@ -192,7 +191,7 @@ func TestSystemsPanicOnComponentHasNotBeenRegistered(t *testing.T) { }, { name: "cardinal.SetComponent", - panicFn: func(wCtx engine.Context) { + panicFn: func(wCtx cardinal.Context) { id, err := cardinal.Create(wCtx, Foo{}) assert.Check(t, err == nil) _ = cardinal.SetComponent[UnregisteredComp](wCtx, id, &UnregisteredComp{}) @@ -200,7 +199,7 @@ func TestSystemsPanicOnComponentHasNotBeenRegistered(t *testing.T) { }, { name: "cardinal.UpdateComponent", - panicFn: func(wCtx engine.Context) { + panicFn: func(wCtx cardinal.Context) { id, err := cardinal.Create(wCtx, Foo{}) assert.Check(t, err == nil) _ = cardinal.UpdateComponent[UnregisteredComp](wCtx, id, @@ -211,13 +210,13 @@ func TestSystemsPanicOnComponentHasNotBeenRegistered(t *testing.T) { }, { name: "cardinal.Create", - panicFn: func(wCtx engine.Context) { + panicFn: func(wCtx cardinal.Context) { _, _ = cardinal.Create(wCtx, Foo{}, UnregisteredComp{}) }, }, { name: "cardinal.CreateMany", - panicFn: func(wCtx engine.Context) { + panicFn: func(wCtx cardinal.Context) { _, _ = cardinal.CreateMany(wCtx, 10, Foo{}, UnregisteredComp{}) }, }, @@ -228,7 +227,7 @@ func TestSystemsPanicOnComponentHasNotBeenRegistered(t *testing.T) { tf := testutils.NewTestFixture(t, nil) world, tick := tf.World, tf.DoTick assert.NilError(t, cardinal.RegisterComponent[Foo](world)) - err := cardinal.RegisterInitSystems(world, func(wCtx engine.Context) error { + err := cardinal.RegisterInitSystems(world, func(wCtx cardinal.Context) error { defer func() { err := recover() // assert.Check is required here because this is happening in a non-main thread. @@ -260,11 +259,11 @@ type QueryResponse struct{} func TestQueriesDoNotPanicOnComponentHasNotBeenRegistered(t *testing.T) { testCases := []struct { name string - testFn func(engine.Context) error + testFn func(cardinal.Context) error }{ { name: "cardinal.GetComponent", - testFn: func(wCtx engine.Context) error { + testFn: func(wCtx cardinal.Context) error { // Get a valid entity to ensure the error we find is related to the component and NOT // due to an invalid entity. id, err := cardinal.NewSearch().Entity(filter.Exact(filter.Component[Foo]())).First(wCtx) @@ -288,7 +287,7 @@ func TestQueriesDoNotPanicOnComponentHasNotBeenRegistered(t *testing.T) { tf := testutils.NewTestFixture(t, nil) world, tick := tf.World, tf.DoTick assert.NilError(t, cardinal.RegisterComponent[Foo](world)) - err := cardinal.RegisterInitSystems(world, func(wCtx engine.Context) error { + err := cardinal.RegisterInitSystems(world, func(wCtx cardinal.Context) error { // Make an entity so the test functions are operating on a valid entity. _, err := cardinal.Create(wCtx, Foo{}) assert.Check(t, err == nil) @@ -298,7 +297,7 @@ func TestQueriesDoNotPanicOnComponentHasNotBeenRegistered(t *testing.T) { err = cardinal.RegisterQuery[QueryRequest, QueryResponse]( world, queryName, - func(wCtx engine.Context, _ *QueryRequest) (*QueryResponse, error) { + func(wCtx cardinal.Context, _ *QueryRequest) (*QueryResponse, error) { return nil, tc.testFn(wCtx) }) assert.Check(t, err == nil) @@ -323,7 +322,7 @@ func TestGetComponentInQueryDoesNotPanicOnRedisError(t *testing.T) { world, tick := tf.World, tf.DoTick assert.NilError(t, cardinal.RegisterComponent[Foo](world)) - err := cardinal.RegisterSystems(world, func(wCtx engine.Context) error { + err := cardinal.RegisterSystems(world, func(wCtx cardinal.Context) error { _, err := cardinal.Create(wCtx, Foo{}) assert.Check(t, err == nil) return nil @@ -334,7 +333,7 @@ func TestGetComponentInQueryDoesNotPanicOnRedisError(t *testing.T) { assert.NilError(t, cardinal.RegisterQuery[QueryRequest, QueryResponse]( world, queryName, - func(wCtx engine.Context, _ *QueryRequest) (*QueryResponse, error) { + func(wCtx cardinal.Context, _ *QueryRequest) (*QueryResponse, error) { id, err := cardinal.NewSearch().Entity(filter.Exact(filter.Component[Foo]())).First(wCtx) assert.Check(t, err == nil) _, err = cardinal.GetComponent[Foo](wCtx, id) diff --git a/cardinal/example_messagetype_test.go b/cardinal/example_messagetype_test.go index ab313a262..29cb9cb3d 100644 --- a/cardinal/example_messagetype_test.go +++ b/cardinal/example_messagetype_test.go @@ -6,7 +6,6 @@ import ( "fmt" "pkg.world.dev/world-engine/cardinal" - "pkg.world.dev/world-engine/cardinal/types/engine" ) type MovePlayerMsg struct { @@ -30,7 +29,7 @@ func ExampleMessageType() { panic(err) } - err = cardinal.RegisterSystems(world, func(wCtx engine.Context) error { + err = cardinal.RegisterSystems(world, func(wCtx cardinal.Context) error { return cardinal.EachMessage[MovePlayerMsg, MovePlayerResult](wCtx, func(txData cardinal.TxData[MovePlayerMsg]) (MovePlayerResult, error) { // handle the transaction diff --git a/cardinal/imported.go b/cardinal/imported.go deleted file mode 100644 index f21419dfb..000000000 --- a/cardinal/imported.go +++ /dev/null @@ -1,7 +0,0 @@ -package cardinal - -import ( - "pkg.world.dev/world-engine/cardinal/types/engine" -) - -type WorldContext = engine.Context diff --git a/cardinal/log/log_test.go b/cardinal/log/log_test.go index e25b18e09..d29f6d3ca 100644 --- a/cardinal/log/log_test.go +++ b/cardinal/log/log_test.go @@ -15,7 +15,6 @@ import ( "pkg.world.dev/world-engine/cardinal/search/filter" "pkg.world.dev/world-engine/cardinal/testutils" "pkg.world.dev/world-engine/cardinal/types" - "pkg.world.dev/world-engine/cardinal/types/engine" ) type SendEnergyTx struct { @@ -33,7 +32,7 @@ func (EnergyComp) Name() string { return "EnergyComp" } -func testSystem(wCtx engine.Context) error { +func testSystem(wCtx cardinal.Context) error { wCtx.Logger().Log().Msg("test") q := cardinal.NewSearch().Entity(filter.Contains(filter.Component[EnergyComp]())) err := q.Each(wCtx, @@ -54,7 +53,7 @@ func testSystem(wCtx engine.Context) error { return nil } -func testSystemWarningTrigger(wCtx engine.Context) error { +func testSystemWarningTrigger(wCtx cardinal.Context) error { time.Sleep(time.Millisecond * 400) return testSystem(wCtx) } diff --git a/cardinal/message.go b/cardinal/message.go index 0573f2a50..3c3f17cc0 100644 --- a/cardinal/message.go +++ b/cardinal/message.go @@ -12,7 +12,6 @@ import ( "pkg.world.dev/world-engine/cardinal/abi" "pkg.world.dev/world-engine/cardinal/codec" "pkg.world.dev/world-engine/cardinal/types" - "pkg.world.dev/world-engine/cardinal/types/engine" "pkg.world.dev/world-engine/sign" ) @@ -104,15 +103,15 @@ func (t *MessageType[In, Out]) SetID(id types.MessageID) error { return nil } -func (t *MessageType[In, Out]) AddError(wCtx engine.Context, hash types.TxHash, err error) { +func (t *MessageType[In, Out]) AddError(wCtx Context, hash types.TxHash, err error) { wCtx.AddMessageError(hash, err) } -func (t *MessageType[In, Out]) SetResult(wCtx engine.Context, hash types.TxHash, result Out) { +func (t *MessageType[In, Out]) SetResult(wCtx Context, hash types.TxHash, result Out) { wCtx.SetMessageResult(hash, result) } -func (t *MessageType[In, Out]) GetReceipt(wCtx engine.Context, hash types.TxHash) ( +func (t *MessageType[In, Out]) GetReceipt(wCtx Context, hash types.TxHash) ( v Out, errs []error, ok bool, ) { iface, errs, ok := wCtx.GetTransactionReceipt(hash) @@ -130,7 +129,7 @@ func (t *MessageType[In, Out]) GetReceipt(wCtx engine.Context, hash types.TxHash return value, errs, true } -func (t *MessageType[In, Out]) Each(wCtx engine.Context, fn func(TxData[In]) (Out, error)) { +func (t *MessageType[In, Out]) Each(wCtx Context, fn func(TxData[In]) (Out, error)) { for _, txData := range t.In(wCtx) { if result, err := fn(txData); err != nil { err = eris.Wrap(err, "") @@ -148,7 +147,7 @@ func (t *MessageType[In, Out]) Each(wCtx engine.Context, fn func(TxData[In]) (Ou } // In extracts all the TxData in the tx pool that match this MessageType's ID. -func (t *MessageType[In, Out]) In(wCtx engine.Context) []TxData[In] { +func (t *MessageType[In, Out]) In(wCtx Context) []TxData[In] { tq := wCtx.GetTxPool() var txs []TxData[In] for _, txData := range tq.ForID(t.ID()) { diff --git a/cardinal/persona/persona_test.go b/cardinal/persona/persona_test.go index 4ff4b327c..f25ef5c53 100644 --- a/cardinal/persona/persona_test.go +++ b/cardinal/persona/persona_test.go @@ -10,7 +10,6 @@ import ( "pkg.world.dev/world-engine/cardinal/persona" "pkg.world.dev/world-engine/cardinal/persona/component" "pkg.world.dev/world-engine/cardinal/persona/msg" - personaQuery "pkg.world.dev/world-engine/cardinal/persona/query" "pkg.world.dev/world-engine/cardinal/search/filter" "pkg.world.dev/world-engine/cardinal/testutils" "pkg.world.dev/world-engine/cardinal/types" @@ -237,15 +236,15 @@ func TestQuerySigner(t *testing.T) { query, err := world.GetQueryByName("signer") assert.NilError(t, err) - res, err := query.HandleQuery(cardinal.NewReadOnlyWorldContext(world), &personaQuery.PersonaSignerQueryRequest{ + res, err := query.HandleQuery(cardinal.NewReadOnlyWorldContext(world), &cardinal.PersonaSignerQueryRequest{ PersonaTag: personaTag, }) assert.NilError(t, err) - response, ok := res.(*personaQuery.PersonaSignerQueryResponse) + response, ok := res.(*cardinal.PersonaSignerQueryResponse) assert.True(t, ok) assert.Equal(t, response.SignerAddress, signerAddr) - assert.Equal(t, response.Status, personaQuery.PersonaStatusAssigned) + assert.Equal(t, response.Status, cardinal.PersonaStatusAssigned) } func TestQuerySignerAvailable(t *testing.T) { @@ -255,14 +254,14 @@ func TestQuerySignerAvailable(t *testing.T) { query, err := world.GetQueryByName("signer") assert.NilError(t, err) - res, err := query.HandleQuery(cardinal.NewReadOnlyWorldContext(world), &personaQuery.PersonaSignerQueryRequest{ + res, err := query.HandleQuery(cardinal.NewReadOnlyWorldContext(world), &cardinal.PersonaSignerQueryRequest{ PersonaTag: "some-random-nonexistent-persona-tag", }) assert.NilError(t, err) - response, ok := res.(*personaQuery.PersonaSignerQueryResponse) + response, ok := res.(*cardinal.PersonaSignerQueryResponse) assert.True(t, ok) - assert.Equal(t, response.Status, personaQuery.PersonaStatusAvailable) + assert.Equal(t, response.Status, cardinal.PersonaStatusAvailable) } func TestQuerySignerUnknown(t *testing.T) { @@ -272,15 +271,15 @@ func TestQuerySignerUnknown(t *testing.T) { query, err := engine.GetQueryByName("signer") assert.NilError(t, err) - res, err := query.HandleQuery(cardinal.NewReadOnlyWorldContext(engine), &personaQuery.PersonaSignerQueryRequest{ + res, err := query.HandleQuery(cardinal.NewReadOnlyWorldContext(engine), &cardinal.PersonaSignerQueryRequest{ PersonaTag: "doesnt_matter", Tick: engine.CurrentTick(), }) assert.NilError(t, err) - response, ok := res.(*personaQuery.PersonaSignerQueryResponse) + response, ok := res.(*cardinal.PersonaSignerQueryResponse) assert.True(t, ok) - assert.Equal(t, response.Status, personaQuery.PersonaStatusUnknown) + assert.Equal(t, response.Status, cardinal.PersonaStatusUnknown) } func getSigners(t *testing.T, world *cardinal.World) []*component.SignerComponent { diff --git a/cardinal/persona/query/persona_signer.go b/cardinal/persona_signer.go similarity index 89% rename from cardinal/persona/query/persona_signer.go rename to cardinal/persona_signer.go index e333064ae..dda0ea1d1 100644 --- a/cardinal/persona/query/persona_signer.go +++ b/cardinal/persona_signer.go @@ -1,10 +1,9 @@ -package query +package cardinal import ( "errors" "pkg.world.dev/world-engine/cardinal/persona" - "pkg.world.dev/world-engine/cardinal/types/engine" ) const ( @@ -28,7 +27,7 @@ type PersonaSignerQueryResponse struct { SignerAddress string `json:"signerAddress"` } -func PersonaSignerQuery(wCtx engine.Context, req *PersonaSignerQueryRequest) (*PersonaSignerQueryResponse, error) { +func PersonaSignerQuery(wCtx Context, req *PersonaSignerQueryRequest) (*PersonaSignerQueryResponse, error) { var status string addr, err := wCtx.GetSignerForPersonaTag(req.PersonaTag, req.Tick) diff --git a/cardinal/plugin_persona.go b/cardinal/plugin_persona.go index 371baa0e2..6b8765444 100644 --- a/cardinal/plugin_persona.go +++ b/cardinal/plugin_persona.go @@ -10,11 +10,9 @@ import ( "pkg.world.dev/world-engine/cardinal/persona" "pkg.world.dev/world-engine/cardinal/persona/component" "pkg.world.dev/world-engine/cardinal/persona/msg" - "pkg.world.dev/world-engine/cardinal/persona/query" "pkg.world.dev/world-engine/cardinal/search" "pkg.world.dev/world-engine/cardinal/search/filter" "pkg.world.dev/world-engine/cardinal/types" - "pkg.world.dev/world-engine/cardinal/types/engine" ) var ( @@ -69,9 +67,9 @@ func (p *personaPlugin) Register(world *World) error { } func (p *personaPlugin) RegisterQueries(world *World) error { - err := RegisterQuery[query.PersonaSignerQueryRequest, query.PersonaSignerQueryResponse](world, "signer", - query.PersonaSignerQuery, - WithCustomQueryGroup[query.PersonaSignerQueryRequest, query.PersonaSignerQueryResponse]("persona")) + err := RegisterQuery[PersonaSignerQueryRequest, PersonaSignerQueryResponse](world, "signer", + PersonaSignerQuery, + WithCustomQueryGroup[PersonaSignerQueryRequest, PersonaSignerQueryResponse]("persona")) if err != nil { return err } @@ -114,7 +112,7 @@ func (p *personaPlugin) RegisterMessages(world *World) error { // authorizePersonaAddressSystem enables users to authorize an address to a persona tag. This is mostly used so that // users who want to interact with the game via smart contract can link their EVM address to their persona tag, enabling // them to mutate their owned state from the context of the EVM. -func authorizePersonaAddressSystem(wCtx engine.Context) error { +func authorizePersonaAddressSystem(wCtx Context) error { if err := buildGlobalPersonaIndex(wCtx); err != nil { return err } @@ -167,7 +165,7 @@ func authorizePersonaAddressSystem(wCtx engine.Context) error { // createPersonaSystem is a system that will associate persona tags with signature addresses. Each persona tag // may have at most 1 signer, so additional attempts to register a signer with a persona tag will be ignored. -func createPersonaSystem(wCtx engine.Context) error { +func createPersonaSystem(wCtx Context) error { if err := buildGlobalPersonaIndex(wCtx); err != nil { return err } @@ -220,7 +218,7 @@ func createPersonaSystem(wCtx engine.Context) error { // Persona Index // ----------------------------------------------------------------------------- -func buildGlobalPersonaIndex(wCtx engine.Context) error { +func buildGlobalPersonaIndex(wCtx Context) error { // Rebuild the index if we haven't built it yet OR if we're in test and the CurrentTick has been reset. if globalPersonaTagToAddressIndex != nil && tickOfPersonaTagToAddressIndex < wCtx.CurrentTick() { return nil diff --git a/cardinal/query.go b/cardinal/query.go index 200c509cd..26b57b75e 100644 --- a/cardinal/query.go +++ b/cardinal/query.go @@ -8,18 +8,42 @@ import ( "github.com/rotisserie/eris" "pkg.world.dev/world-engine/cardinal/abi" + servertypes "pkg.world.dev/world-engine/cardinal/server/types" "pkg.world.dev/world-engine/cardinal/types" - "pkg.world.dev/world-engine/cardinal/types/engine" ) -var _ engine.Query = &queryType[struct{}, struct{}]{} +type Query interface { + // Name returns the name of the query. + Name() string + // Group returns the group of the query. + Group() string + // HandleQuery handles queries with concrete types, rather than encoded bytes. + HandleQuery(Context, any) (any, error) + // HandleQueryRaw is given a reference to the engine, json encoded bytes that represent a query request + // and is expected to return a json encoded response struct. + HandleQueryRaw(Context, []byte) ([]byte, error) + // DecodeEVMRequest decodes bytes originating from the evm into the request type, which will be ABI encoded. + DecodeEVMRequest([]byte) (any, error) + // EncodeEVMReply encodes the reply as an abi encoded struct. + EncodeEVMReply(any) ([]byte, error) + // DecodeEVMReply decodes EVM reply bytes, into the concrete go reply type. + DecodeEVMReply([]byte) (any, error) + // EncodeAsABI encodes a go struct in abi format. This is mostly used for testing. + EncodeAsABI(any) ([]byte, error) + // IsEVMCompatible reports if the query is able to be sent from the EVM. + IsEVMCompatible() bool + // GetRequestFieldInformation returns a map of the fields of the query's request type and their types. + GetRequestFieldInformation() map[string]any +} + +var _ Query = &queryType[struct{}, struct{}]{} type QueryOption[Request, Reply any] func(qt *queryType[Request, Reply]) type queryType[Request any, Reply any] struct { name string group string - handler func(wCtx engine.Context, req *Request) (*Reply, error) + handler func(wCtx Context, req *Request) (*Reply, error) requestABI *ethereumAbi.Type replyABI *ethereumAbi.Type } @@ -44,9 +68,9 @@ func WithCustomQueryGroup[Request, Reply any](group string) QueryOption[Request, func NewQueryType[Request any, Reply any]( name string, - handler func(wCtx engine.Context, req *Request) (*Reply, error), + handler func(wCtx Context, req *Request) (*Reply, error), opts ...QueryOption[Request, Reply], -) (engine.Query, error) { +) (Query, error) { err := validateQuery[Request, Reply](name, handler) if err != nil { return nil, err @@ -91,7 +115,7 @@ func (r *queryType[req, rep]) Group() string { return r.group } -func (r *queryType[req, rep]) HandleQuery(wCtx engine.Context, a any) (any, error) { +func (r *queryType[req, rep]) HandleQuery(wCtx Context, a any) (any, error) { var request *req if reflect.TypeOf(a).Kind() == reflect.Pointer { ptrRequest, ok := a.(*req) @@ -110,7 +134,24 @@ func (r *queryType[req, rep]) HandleQuery(wCtx engine.Context, a any) (any, erro return reply, err } -func (r *queryType[req, rep]) HandleQueryRaw(wCtx engine.Context, bz []byte) ([]byte, error) { +func (r *queryType[req, rep]) HandleQueryRaw(wCtx Context, bz []byte) ([]byte, error) { + request := new(req) + err := json.Unmarshal(bz, request) + if err != nil { + return nil, eris.Wrapf(err, "unable to unmarshal query request into type %T", *request) + } + res, err := r.handler(wCtx, request) + if err != nil { + return nil, err + } + bz, err = json.Marshal(res) + if err != nil { + return nil, eris.Wrapf(err, "unable to marshal response %T", res) + } + return bz, nil +} + +func (r *queryType[req, rep]) HandleProviderQueryRaw(wCtx servertypes.ProviderContext, bz []byte) ([]byte, error) { request := new(req) err := json.Unmarshal(bz, request) if err != nil { @@ -208,7 +249,7 @@ func (r *queryType[Request, Reply]) GetRequestFieldInformation() map[string]any func validateQuery[Request any, Reply any]( name string, - handler func(wCtx engine.Context, req *Request) (*Reply, error), + handler func(wCtx Context, req *Request) (*Reply, error), ) error { if name == "" { return eris.New("cannot create query without name") diff --git a/cardinal/query_manager.go b/cardinal/query_manager.go index a2da084c9..d7fb70875 100644 --- a/cardinal/query_manager.go +++ b/cardinal/query_manager.go @@ -2,29 +2,27 @@ package cardinal import ( "github.com/rotisserie/eris" - - "pkg.world.dev/world-engine/cardinal/types/engine" ) type QueryManager interface { - RegisterQuery(name string, query engine.Query) error - GetRegisteredQueries() []engine.Query - GetQueryByName(name string) (engine.Query, error) + RegisterQuery(name string, query Query) error + GetRegisteredQueries() []Query + GetQueryByName(name string) (Query, error) } type QueryManagerImpl struct { - registeredQueries map[string]engine.Query + registeredQueries map[string]Query } func NewQueryManager() QueryManager { return &QueryManagerImpl{ - registeredQueries: make(map[string]engine.Query), + registeredQueries: make(map[string]Query), } } // RegisterQuery registers a query with the query manager. // There can only be one query with a given name. -func (m *QueryManagerImpl) RegisterQuery(name string, query engine.Query) error { +func (m *QueryManagerImpl) RegisterQuery(name string, query Query) error { // Check that the query is not already registered if err := m.isQueryNameUnique(name); err != nil { return err @@ -37,8 +35,8 @@ func (m *QueryManagerImpl) RegisterQuery(name string, query engine.Query) error } // GetRegisteredQueries returns all the registered queries. -func (m *QueryManagerImpl) GetRegisteredQueries() []engine.Query { - registeredQueries := make([]engine.Query, 0, len(m.registeredQueries)) +func (m *QueryManagerImpl) GetRegisteredQueries() []Query { + registeredQueries := make([]Query, 0, len(m.registeredQueries)) for _, query := range m.registeredQueries { registeredQueries = append(registeredQueries, query) } @@ -46,7 +44,7 @@ func (m *QueryManagerImpl) GetRegisteredQueries() []engine.Query { } // GetQueryByName returns a query corresponding to its name. -func (m *QueryManagerImpl) GetQueryByName(name string) (engine.Query, error) { +func (m *QueryManagerImpl) GetQueryByName(name string) (Query, error) { query, ok := m.registeredQueries[name] if !ok { return nil, eris.Errorf("query %q is not registered", name) diff --git a/cardinal/query_test.go b/cardinal/query_test.go index 1fea4efb7..19678fd7b 100644 --- a/cardinal/query_test.go +++ b/cardinal/query_test.go @@ -9,7 +9,6 @@ import ( "pkg.world.dev/world-engine/cardinal/search/filter" "pkg.world.dev/world-engine/cardinal/testutils" "pkg.world.dev/world-engine/cardinal/types" - "pkg.world.dev/world-engine/cardinal/types/engine" ) type Health struct { @@ -29,7 +28,7 @@ type QueryHealthResponse struct { } func handleQueryHealth( - wCtx engine.Context, + wCtx cardinal.Context, request *QueryHealthRequest, ) (*QueryHealthResponse, error) { resp := &QueryHealthResponse{} @@ -65,7 +64,7 @@ func TestNewQueryTypeWithEVMSupport(t *testing.T) { testutils.NewTestFixture(t, nil).World, "query_health", func( - _ engine.Context, + _ cardinal.Context, _ *FooReq, ) (*FooReply, error) { return &FooReply{}, errors.New("this function should never get called") @@ -122,7 +121,7 @@ func TestQueryTypeNotStructs(t *testing.T) { err := cardinal.RegisterQuery[string, string]( testutils.NewTestFixture(t, nil).World, "foo", - func(engine.Context, *string) (*string, error) { + func(cardinal.Context, *string) (*string, error) { return &str, nil }, ) @@ -148,7 +147,7 @@ func TestQueryEVM(t *testing.T) { world, "foo", func( - _ engine.Context, _ *FooRequest, + _ cardinal.Context, _ *FooRequest, ) (*FooReply, error) { return &expectedReply, nil }, diff --git a/cardinal/search/composedsearch.go b/cardinal/search/composedsearch.go index 50e35f09a..5e2c6716e 100644 --- a/cardinal/search/composedsearch.go +++ b/cardinal/search/composedsearch.go @@ -5,7 +5,6 @@ import ( "pkg.world.dev/world-engine/cardinal/search/filter" "pkg.world.dev/world-engine/cardinal/types" - "pkg.world.dev/world-engine/cardinal/types/engine" ) type OrSearch struct { @@ -20,7 +19,7 @@ type NotSearch struct { search Searchable } -func (orSearch *OrSearch) evaluateSearch(eCtx engine.Context) []types.ArchetypeID { +func (orSearch *OrSearch) evaluateSearch(eCtx Context) []types.ArchetypeID { acc := make([]types.ArchetypeID, 0) for _, search := range orSearch.searches { acc = append(acc, search.evaluateSearch(eCtx)...) @@ -28,7 +27,7 @@ func (orSearch *OrSearch) evaluateSearch(eCtx engine.Context) []types.ArchetypeI return acc } -func (orSearch *OrSearch) Each(eCtx engine.Context, callback CallbackFn) error { +func (orSearch *OrSearch) Each(eCtx Context, callback CallbackFn) error { // deduplicate idCount := make(map[types.EntityID]int) for _, search := range orSearch.searches { @@ -57,7 +56,7 @@ func (orSearch *OrSearch) Each(eCtx engine.Context, callback CallbackFn) error { return nil } -func (orSearch *OrSearch) Collect(eCtx engine.Context) ([]types.EntityID, error) { +func (orSearch *OrSearch) Collect(eCtx Context) ([]types.EntityID, error) { // deduplicate idExists := make(map[types.EntityID]bool) res := make([]types.EntityID, 0) @@ -80,7 +79,7 @@ func (orSearch *OrSearch) Collect(eCtx engine.Context) ([]types.EntityID, error) return res, nil } -func (orSearch *OrSearch) First(eCtx engine.Context) (types.EntityID, error) { +func (orSearch *OrSearch) First(eCtx Context) (types.EntityID, error) { ids, err := orSearch.Collect(eCtx) if err != nil { return 0, err @@ -91,7 +90,7 @@ func (orSearch *OrSearch) First(eCtx engine.Context) (types.EntityID, error) { return ids[0], nil } -func (orSearch *OrSearch) MustFirst(eCtx engine.Context) types.EntityID { +func (orSearch *OrSearch) MustFirst(eCtx Context) types.EntityID { id, err := orSearch.First(eCtx) if err != nil { panic("no search results") @@ -99,7 +98,7 @@ func (orSearch *OrSearch) MustFirst(eCtx engine.Context) types.EntityID { return id } -func (orSearch *OrSearch) Count(eCtx engine.Context) (int, error) { +func (orSearch *OrSearch) Count(eCtx Context) (int, error) { ids, err := orSearch.Collect(eCtx) if err != nil { return 0, err @@ -107,7 +106,7 @@ func (orSearch *OrSearch) Count(eCtx engine.Context) (int, error) { return len(ids), nil } -func (andSearch *AndSearch) Each(eCtx engine.Context, callback CallbackFn) error { +func (andSearch *AndSearch) Each(eCtx Context, callback CallbackFn) error { // count idCount := make(map[types.EntityID]int) for _, search := range andSearch.searches { @@ -140,7 +139,7 @@ func (andSearch *AndSearch) Each(eCtx engine.Context, callback CallbackFn) error return nil } -func (andSearch *AndSearch) Collect(eCtx engine.Context) ([]types.EntityID, error) { +func (andSearch *AndSearch) Collect(eCtx Context) ([]types.EntityID, error) { // filter results := make([]types.EntityID, 0) err := andSearch.Each(eCtx, func(id types.EntityID) bool { @@ -157,7 +156,7 @@ func (andSearch *AndSearch) Collect(eCtx engine.Context) ([]types.EntityID, erro return results, nil } -func (andSearch *AndSearch) First(eCtx engine.Context) (types.EntityID, error) { +func (andSearch *AndSearch) First(eCtx Context) (types.EntityID, error) { ids, err := andSearch.Collect(eCtx) if err != nil { return 0, err @@ -168,7 +167,7 @@ func (andSearch *AndSearch) First(eCtx engine.Context) (types.EntityID, error) { return ids[0], nil } -func (andSearch *AndSearch) MustFirst(eCtx engine.Context) types.EntityID { +func (andSearch *AndSearch) MustFirst(eCtx Context) types.EntityID { id, err := andSearch.First(eCtx) if err != nil { panic("No search results") @@ -176,7 +175,7 @@ func (andSearch *AndSearch) MustFirst(eCtx engine.Context) types.EntityID { return id } -func (andSearch *AndSearch) Count(eCtx engine.Context) (int, error) { +func (andSearch *AndSearch) Count(eCtx Context) (int, error) { ids, err := andSearch.Collect(eCtx) if err != nil { return 0, err @@ -184,7 +183,7 @@ func (andSearch *AndSearch) Count(eCtx engine.Context) (int, error) { return len(ids), nil } -func (andSearch *AndSearch) evaluateSearch(eCtx engine.Context) []types.ArchetypeID { +func (andSearch *AndSearch) evaluateSearch(eCtx Context) []types.ArchetypeID { searchCounts := make(map[types.ArchetypeID]int) for _, search := range andSearch.searches { ids := search.evaluateSearch(eCtx) @@ -201,7 +200,7 @@ func (andSearch *AndSearch) evaluateSearch(eCtx engine.Context) []types.Archetyp return acc } -func (notSearch *NotSearch) Each(eCtx engine.Context, callback CallbackFn) error { +func (notSearch *NotSearch) Each(eCtx Context, callback CallbackFn) error { // sort ids, err := notSearch.Collect(eCtx) if err != nil { @@ -218,7 +217,7 @@ func (notSearch *NotSearch) Each(eCtx engine.Context, callback CallbackFn) error return nil } -func (notSearch *NotSearch) Collect(eCtx engine.Context) ([]types.EntityID, error) { +func (notSearch *NotSearch) Collect(eCtx Context) ([]types.EntityID, error) { // Get all ids allsearch := NewSearch().Entity(filter.All()) allids, err := allsearch.Collect(eCtx) @@ -250,7 +249,7 @@ func (notSearch *NotSearch) Collect(eCtx engine.Context) ([]types.EntityID, erro return result, nil } -func (notSearch *NotSearch) First(eCtx engine.Context) (types.EntityID, error) { +func (notSearch *NotSearch) First(eCtx Context) (types.EntityID, error) { ids, err := notSearch.Collect(eCtx) if err != nil { return 0, err @@ -261,7 +260,7 @@ func (notSearch *NotSearch) First(eCtx engine.Context) (types.EntityID, error) { return ids[0], nil } -func (notSearch *NotSearch) MustFirst(eCtx engine.Context) types.EntityID { +func (notSearch *NotSearch) MustFirst(eCtx Context) types.EntityID { id, err := notSearch.First(eCtx) if err != nil { panic("No search results") @@ -269,7 +268,7 @@ func (notSearch *NotSearch) MustFirst(eCtx engine.Context) types.EntityID { return id } -func (notSearch *NotSearch) Count(eCtx engine.Context) (int, error) { +func (notSearch *NotSearch) Count(eCtx Context) (int, error) { ids, err := notSearch.Collect(eCtx) if err != nil { return 0, err @@ -277,7 +276,7 @@ func (notSearch *NotSearch) Count(eCtx engine.Context) (int, error) { return len(ids), nil } -func (notSearch *NotSearch) evaluateSearch(eCtx engine.Context) []types.ArchetypeID { +func (notSearch *NotSearch) evaluateSearch(eCtx Context) []types.ArchetypeID { searchBuilder := NewSearch() allResults := searchBuilder.Entity(filter.All()).evaluateSearch(eCtx) allResultsMap := make(map[types.ArchetypeID]bool) diff --git a/cardinal/search/context.go b/cardinal/search/context.go new file mode 100644 index 000000000..d89fa7f29 --- /dev/null +++ b/cardinal/search/context.go @@ -0,0 +1,49 @@ +package search + +import ( + "reflect" + + "github.com/rs/zerolog" + + "pkg.world.dev/world-engine/cardinal/gamestate" + "pkg.world.dev/world-engine/cardinal/receipt" + "pkg.world.dev/world-engine/cardinal/types" + "pkg.world.dev/world-engine/cardinal/types/txpool" + "pkg.world.dev/world-engine/sign" +) + +//go:generate mockgen -source=context.go -package mocks -destination=mocks/context.go +type Context interface { + // Timestamp returns the UNIX timestamp of the tick. + Timestamp() uint64 + // CurrentTick returns the current tick. + CurrentTick() uint64 + // Logger returns the logger that can be used to log messages from within system or query. + Logger() *zerolog.Logger + // EmitEvent emits an event that will be broadcast to all websocket subscribers. + EmitEvent(map[string]any) error + // EmitStringEvent emits a string event that will be broadcast to all websocket subscribers. + // This method is provided for backwards compatability. EmitEvent should be used for most cases. + EmitStringEvent(string) error + // Namespace returns the namespace of the world. + Namespace() string + + // For internal use. + + // SetLogger is used to inject a new logger configuration to an engine context that is already created. + SetLogger(logger zerolog.Logger) + AddMessageError(id types.TxHash, err error) + SetMessageResult(id types.TxHash, a any) + GetComponentByName(name string) (types.ComponentMetadata, error) + GetMessageByType(mType reflect.Type) (types.Message, bool) + GetTransactionReceipt(id types.TxHash) (any, []error, bool) + GetSignerForPersonaTag(personaTag string, tick uint64) (addr string, err error) + GetTransactionReceiptsForTick(tick uint64) ([]receipt.Receipt, error) + ReceiptHistorySize() uint64 + AddTransaction(id types.MessageID, v any, sig *sign.Transaction) (uint64, types.TxHash) + IsWorldReady() bool + StoreReader() gamestate.Reader + StoreManager() gamestate.Manager + GetTxPool() *txpool.TxPool + IsReadOnly() bool +} diff --git a/cardinal/search/filtercomponent.go b/cardinal/search/filtercomponent.go index e3c646b32..74fac9419 100644 --- a/cardinal/search/filtercomponent.go +++ b/cardinal/search/filtercomponent.go @@ -4,18 +4,17 @@ import ( "github.com/rotisserie/eris" "pkg.world.dev/world-engine/cardinal/types" - "pkg.world.dev/world-engine/cardinal/types/engine" ) // This package involves primitives for search. // It involves creating and combining primitives that represent // filtering properties on components. -type filterFn func(wCtx engine.Context, id types.EntityID) (bool, error) +type filterFn func(wCtx Context, id types.EntityID) (bool, error) //revive:disable-next-line:unexported-return func ComponentFilter[T types.Component](f func(comp T) bool) filterFn { - return func(wCtx engine.Context, id types.EntityID) (bool, error) { + return func(wCtx Context, id types.EntityID) (bool, error) { var t T c, err := wCtx.GetComponentByName(t.Name()) if err != nil { @@ -44,7 +43,7 @@ func ComponentFilter[T types.Component](f func(comp T) bool) filterFn { //revive:disable-next-line:unexported-return func AndFilter(fns ...filterFn) filterFn { - return func(wCtx engine.Context, id types.EntityID) (bool, error) { + return func(wCtx Context, id types.EntityID) (bool, error) { var result = true var errCount = 0 for _, fn := range fns { @@ -64,7 +63,7 @@ func AndFilter(fns ...filterFn) filterFn { //revive:disable-next-line:unexported-return func OrFilter(fns ...filterFn) filterFn { - return func(wCtx engine.Context, id types.EntityID) (bool, error) { + return func(wCtx Context, id types.EntityID) (bool, error) { var result = false var errCount = 0 for _, fn := range fns { diff --git a/cardinal/search/search.go b/cardinal/search/search.go index 69ed67dda..1914a74e9 100644 --- a/cardinal/search/search.go +++ b/cardinal/search/search.go @@ -8,7 +8,6 @@ import ( "pkg.world.dev/world-engine/cardinal/iterators" "pkg.world.dev/world-engine/cardinal/search/filter" "pkg.world.dev/world-engine/cardinal/types" - "pkg.world.dev/world-engine/cardinal/types/engine" ) type CallbackFn func(types.EntityID) bool @@ -93,12 +92,12 @@ type EntitySearch interface { } type Searchable interface { - evaluateSearch(eCtx engine.Context) []types.ArchetypeID - Each(eCtx engine.Context, callback CallbackFn) error - First(eCtx engine.Context) (types.EntityID, error) - MustFirst(eCtx engine.Context) types.EntityID - Count(eCtx engine.Context) (int, error) - Collect(eCtx engine.Context) ([]types.EntityID, error) + evaluateSearch(eCtx Context) []types.ArchetypeID + Each(eCtx Context, callback CallbackFn) error + First(eCtx Context) (types.EntityID, error) + MustFirst(eCtx Context) types.EntityID + Count(eCtx Context) (int, error) + Collect(eCtx Context) ([]types.EntityID, error) } // NewSearch creates a new search. @@ -139,7 +138,7 @@ func (s *Search) Where(componentFilter filterFn) EntitySearch { // Each iterates over all entities that match the search. // If you would like to stop the iteration, return false to the callback. To continue iterating, return true. -func (s *Search) Each(eCtx engine.Context, callback CallbackFn) (err error) { +func (s *Search) Each(eCtx Context, callback CallbackFn) (err error) { defer func() { defer panicOnFatalError(eCtx, err) }() result := s.evaluateSearch(eCtx) @@ -175,7 +174,7 @@ func fastSortIDs(ids []types.EntityID) { slices.Sort(ids) } -func (s *Search) Collect(eCtx engine.Context) ([]types.EntityID, error) { +func (s *Search) Collect(eCtx Context) ([]types.EntityID, error) { acc := make([]types.EntityID, 0) err := s.Each(eCtx, func(id types.EntityID) bool { acc = append(acc, id) @@ -189,7 +188,7 @@ func (s *Search) Collect(eCtx engine.Context) ([]types.EntityID, error) { } // Count returns the number of entities that match the search. -func (s *Search) Count(eCtx engine.Context) (ret int, err error) { +func (s *Search) Count(eCtx Context) (ret int, err error) { defer func() { defer panicOnFatalError(eCtx, err) }() result := s.evaluateSearch(eCtx) @@ -218,7 +217,7 @@ func (s *Search) Count(eCtx engine.Context) (ret int, err error) { } // First returns the first entity that matches the search. -func (s *Search) First(eCtx engine.Context) (id types.EntityID, err error) { +func (s *Search) First(eCtx Context) (id types.EntityID, err error) { defer func() { defer panicOnFatalError(eCtx, err) }() result := s.evaluateSearch(eCtx) @@ -249,7 +248,7 @@ func (s *Search) First(eCtx engine.Context) (id types.EntityID, err error) { return iterators.BadID, eris.Wrap(err, "") } -func (s *Search) MustFirst(eCtx engine.Context) types.EntityID { +func (s *Search) MustFirst(eCtx Context) types.EntityID { id, err := s.First(eCtx) if err != nil { panic("no entity matches the search") @@ -257,7 +256,7 @@ func (s *Search) MustFirst(eCtx engine.Context) types.EntityID { return id } -func (s *Search) evaluateSearch(eCtx engine.Context) []types.ArchetypeID { +func (s *Search) evaluateSearch(eCtx Context) []types.ArchetypeID { cache := s.archMatches for it := eCtx.StoreReader().SearchFrom(s.filter, cache.seen); it.HasNext(); { cache.archetypes = append(cache.archetypes, it.Next()) diff --git a/cardinal/search/util.go b/cardinal/search/util.go index 4f9bd4b1b..5d07827cc 100644 --- a/cardinal/search/util.go +++ b/cardinal/search/util.go @@ -4,7 +4,6 @@ import ( "github.com/rotisserie/eris" "pkg.world.dev/world-engine/cardinal/iterators" - "pkg.world.dev/world-engine/cardinal/types/engine" ) var NonFatalError = []error{ @@ -15,7 +14,7 @@ var NonFatalError = []error{ } // panicOnFatalError is a helper function to panic on non-deterministic errors (i.e. Redis error). -func panicOnFatalError(wCtx engine.Context, err error) { +func panicOnFatalError(wCtx Context, err error) { if err != nil && !wCtx.IsReadOnly() && isFatalError(err) { wCtx.Logger().Panic().Err(err).Msgf("fatal error: %v", eris.ToString(err, true)) panic(err) diff --git a/cardinal/search_test.go b/cardinal/search_test.go index a4526631b..0838126e7 100644 --- a/cardinal/search_test.go +++ b/cardinal/search_test.go @@ -9,7 +9,6 @@ import ( "pkg.world.dev/world-engine/cardinal/search/filter" "pkg.world.dev/world-engine/cardinal/testutils" "pkg.world.dev/world-engine/cardinal/types" - "pkg.world.dev/world-engine/cardinal/types/engine" ) var _ types.Component @@ -90,7 +89,7 @@ func TestSearchUsingAllMethods(t *testing.T) { filter.Contains(filter.Component[AlphaTest]()), filter.Contains(filter.Component[BetaTest]()), filter.Contains(filter.Component[GammaTest]())), - )).Where(func(_ engine.Context, _ types.EntityID) (bool, error) { + )).Where(func(_ search.Context, _ types.EntityID) (bool, error) { return true, nil }).Count(worldCtx) assert.NilError(t, err) @@ -99,7 +98,7 @@ func TestSearchUsingAllMethods(t *testing.T) { filter.Contains(filter.Component[AlphaTest]()), filter.Contains(filter.Component[BetaTest]()), filter.Contains(filter.Component[GammaTest]())), - )).Where(func(wCtx engine.Context, id types.EntityID) (bool, error) { + )).Where(func(wCtx search.Context, id types.EntityID) (bool, error) { c, err := cardinal.GetComponent[HP](wCtx, id) if err != nil { return false, err @@ -487,7 +486,7 @@ func TestWhereClauseOnSearch(t *testing.T) { _, err = cardinal.CreateMany(worldCtx, 10, AlphaTest{}, BetaTest{}, GammaTest{}) assert.NilError(t, err) - q1 := cardinal.NewSearch().Entity(filter.All()).Where(func(wCtx engine.Context, id types.EntityID) (bool, error) { + q1 := cardinal.NewSearch().Entity(filter.All()).Where(func(wCtx search.Context, id types.EntityID) (bool, error) { _, err := cardinal.GetComponent[AlphaTest](wCtx, id) if err != nil { return false, err diff --git a/cardinal/server/event_test.go b/cardinal/server/event_test.go index 7906c36e6..f6f92ce7b 100644 --- a/cardinal/server/event_test.go +++ b/cardinal/server/event_test.go @@ -12,7 +12,6 @@ import ( "pkg.world.dev/world-engine/assert" "pkg.world.dev/world-engine/cardinal" "pkg.world.dev/world-engine/cardinal/testutils" - "pkg.world.dev/world-engine/cardinal/types/engine" ) type SendEnergyTx struct { @@ -42,31 +41,31 @@ func TestEventsThroughSystems(t *testing.T) { counter1 := atomic.Int32{} counter1.Store(0) event := map[string]any{"message": "test"} - sys1 := func(wCtx engine.Context) error { + sys1 := func(wCtx cardinal.Context) error { err := wCtx.EmitEvent(event) assert.Check(t, err == nil, "emit event encountered error is system 1: %v", err) counter1.Add(1) return nil } - sys2 := func(wCtx engine.Context) error { + sys2 := func(wCtx cardinal.Context) error { err := wCtx.EmitEvent(event) assert.Check(t, err == nil, "emit event encountered error is system 2: %v", err) counter1.Add(1) return nil } - sys3 := func(wCtx engine.Context) error { + sys3 := func(wCtx cardinal.Context) error { err := wCtx.EmitEvent(event) assert.Check(t, err == nil, "emit event encountered error is system 3: %v", err) counter1.Add(1) return nil } - sys4 := func(wCtx engine.Context) error { + sys4 := func(wCtx cardinal.Context) error { err := wCtx.EmitEvent(event) assert.Check(t, err == nil, "emit event encountered error is system 4: %v", err) counter1.Add(1) return nil } - sys5 := func(wCtx engine.Context) error { + sys5 := func(wCtx cardinal.Context) error { err := wCtx.EmitEvent(event) assert.Check(t, err == nil, "emit event encountered error is system 5: %v", err) counter1.Add(1) diff --git a/cardinal/server/handler/cql.go b/cardinal/server/handler/cql.go index e9d502cc4..58ee67845 100644 --- a/cardinal/server/handler/cql.go +++ b/cardinal/server/handler/cql.go @@ -34,7 +34,7 @@ type CQLQueryResponse struct { // @Success 200 {object} CQLQueryResponse "Results of the executed CQL query" // @Failure 400 {string} string "Invalid request parameters" // @Router /cql [post] -func PostCQL(provider servertypes.Provider) func(*fiber.Ctx) error { //nolint:gocognit // to refactor later +func PostCQL(provider servertypes.ProviderWorld, wCtx servertypes.ProviderContext) func(*fiber.Ctx) error { //nolint:gocognit // to refactor later return func(ctx *fiber.Ctx) error { req := new(CQLQueryRequest) if err := ctx.BodyParser(req); err != nil { @@ -59,7 +59,7 @@ func PostCQL(provider servertypes.Provider) func(*fiber.Ctx) error { //nolint:go result := make([]cqlData, 0) var eachError error - searchErr := provider.Search(resultFilter).Each(provider.GetReadOnlyCtx(), + searchErr := provider.Search(resultFilter).Each(wCtx, func(id types.EntityID) bool { components, err := provider.StoreReader().GetComponentTypesForEntity(id) if err != nil { diff --git a/cardinal/server/handler/debug.go b/cardinal/server/handler/debug.go index 1a8288722..3ced28a7f 100644 --- a/cardinal/server/handler/debug.go +++ b/cardinal/server/handler/debug.go @@ -26,12 +26,12 @@ type DebugStateResponse []debugStateElement // @Produce application/json // @Success 200 {object} DebugStateResponse "List of all entities" // @Router /debug/state [post] -func GetDebugState(provider servertypes.Provider) func(*fiber.Ctx) error { +func GetDebugState(provider servertypes.ProviderWorld, wCtx servertypes.ProviderContext) func(*fiber.Ctx) error { return func(ctx *fiber.Ctx) error { result := make(DebugStateResponse, 0) s := provider.Search(filter.All()) var eachClosureErr error - searchEachErr := s.Each(provider.GetReadOnlyCtx(), + searchEachErr := s.Each(wCtx, func(id types.EntityID) bool { var components []types.ComponentMetadata components, eachClosureErr = provider.StoreReader().GetComponentTypesForEntity(id) diff --git a/cardinal/server/handler/query.go b/cardinal/server/handler/query.go index 6c12bdc0e..ab308ae9d 100644 --- a/cardinal/server/handler/query.go +++ b/cardinal/server/handler/query.go @@ -3,7 +3,7 @@ package handler import ( "github.com/gofiber/fiber/v2" - "pkg.world.dev/world-engine/cardinal/types/engine" + "pkg.world.dev/world-engine/cardinal/server/types" ) // PostQuery godoc @@ -18,7 +18,7 @@ import ( // @Success 200 {object} object "Results of the executed query" // @Failure 400 {string} string "Invalid request parameters" // @Router /query/{queryGroup}/{queryName} [post] -func PostQuery(queries map[string]map[string]engine.Query, wCtx engine.Context) func(*fiber.Ctx) error { +func PostQuery(queries map[string]map[string]types.ProviderQuery, wCtx types.ProviderContext) func(*fiber.Ctx) error { return func(ctx *fiber.Ctx) error { query, ok := queries[ctx.Params("group")][ctx.Params("name")] if !ok { @@ -26,7 +26,7 @@ func PostQuery(queries map[string]map[string]engine.Query, wCtx engine.Context) } ctx.Set("Content-Type", "application/json") - resBz, err := query.HandleQueryRaw(wCtx, ctx.Body()) + resBz, err := query.HandleProviderQueryRaw(wCtx, ctx.Body()) if err != nil { return fiber.NewError(fiber.StatusBadRequest, "encountered an error in query: "+err.Error()) } @@ -47,6 +47,6 @@ func PostQuery(queries map[string]map[string]engine.Query, wCtx engine.Context) // @Success 200 {object} object "Results of the executed query" // @Failure 400 {string} string "Invalid request parameters" // @Router /query/game/{queryName} [post] -func PostGameQuery(queries map[string]map[string]engine.Query, wCtx engine.Context) func(*fiber.Ctx) error { +func PostGameQuery(queries map[string]map[string]types.ProviderQuery, wCtx types.ProviderContext) func(*fiber.Ctx) error { return PostQuery(queries, wCtx) } diff --git a/cardinal/server/handler/receipts.go b/cardinal/server/handler/receipts.go index 14dfb6d49..efbe6f59d 100644 --- a/cardinal/server/handler/receipts.go +++ b/cardinal/server/handler/receipts.go @@ -3,7 +3,7 @@ package handler import ( "github.com/gofiber/fiber/v2" - "pkg.world.dev/world-engine/cardinal/types/engine" + "pkg.world.dev/world-engine/cardinal/server/types" ) type ListTxReceiptsRequest struct { @@ -38,7 +38,7 @@ type ReceiptEntry struct { // @Success 200 {object} ListTxReceiptsResponse "List of receipts" // @Failure 400 {string} string "Invalid request body" // @Router /query/receipts/list [post] -func GetReceipts(wCtx engine.Context) func(*fiber.Ctx) error { +func GetReceipts(wCtx types.ProviderContext) func(*fiber.Ctx) error { return func(ctx *fiber.Ctx) error { req := new(ListTxReceiptsRequest) if err := ctx.BodyParser(req); err != nil { diff --git a/cardinal/server/handler/tx.go b/cardinal/server/handler/tx.go index 1a63d640a..3c0b55a4b 100644 --- a/cardinal/server/handler/tx.go +++ b/cardinal/server/handler/tx.go @@ -41,7 +41,7 @@ type Transaction = sign.Transaction // @Failure 400 {string} string "Invalid request parameter" // @Router /tx/{txGroup}/{txName} [post] func PostTransaction( - provider servertypes.Provider, msgs map[string]map[string]types.Message, disableSigVerification bool, + provider servertypes.ProviderWorld, msgs map[string]map[string]types.Message, disableSigVerification bool, ) func(*fiber.Ctx) error { return func(ctx *fiber.Ctx) error { msgType, ok := msgs[ctx.Params("group")][ctx.Params("name")] @@ -104,7 +104,7 @@ func PostTransaction( // @Failure 400 {string} string "Invalid request parameter" // @Router /tx/game/{txName} [post] func PostGameTransaction( - provider servertypes.Provider, msgs map[string]map[string]types.Message, disableSigVerification bool, + provider servertypes.ProviderWorld, msgs map[string]map[string]types.Message, disableSigVerification bool, ) func(*fiber.Ctx) error { return PostTransaction(provider, msgs, disableSigVerification) } @@ -121,12 +121,12 @@ func PostGameTransaction( // @Failure 400 {string} string "Invalid request parameter" // @Router /tx/persona/create-persona [post] func PostPersonaTransaction( - provider servertypes.Provider, msgs map[string]map[string]types.Message, disableSigVerification bool, + provider servertypes.ProviderWorld, msgs map[string]map[string]types.Message, disableSigVerification bool, ) func(*fiber.Ctx) error { return PostTransaction(provider, msgs, disableSigVerification) } -func lookupSignerAndValidateSignature(provider servertypes.Provider, signerAddress string, tx *Transaction) error { +func lookupSignerAndValidateSignature(provider servertypes.ProviderWorld, signerAddress string, tx *Transaction) error { var err error if signerAddress == "" { signerAddress, err = provider.GetSignerForPersonaTag(tx.PersonaTag, 0) diff --git a/cardinal/server/handler/world.go b/cardinal/server/handler/world.go index 48d05605e..12bfd2ded 100644 --- a/cardinal/server/handler/world.go +++ b/cardinal/server/handler/world.go @@ -5,9 +5,9 @@ import ( "github.com/gofiber/fiber/v2" + servertypes "pkg.world.dev/world-engine/cardinal/server/types" "pkg.world.dev/world-engine/cardinal/server/utils" "pkg.world.dev/world-engine/cardinal/types" - "pkg.world.dev/world-engine/cardinal/types/engine" ) type GetWorldResponse struct { @@ -34,7 +34,7 @@ type FieldDetail struct { // @Router /world [get] func GetWorld( components []types.ComponentMetadata, messages []types.Message, - queries []engine.Query, namespace string, + queries []servertypes.ProviderQuery, namespace string, ) func(*fiber.Ctx) error { // Collecting name of all registered components comps := make([]FieldDetail, 0, len(components)) diff --git a/cardinal/server/receipts_test.go b/cardinal/server/receipts_test.go index f2f76da4c..9312ed2da 100644 --- a/cardinal/server/receipts_test.go +++ b/cardinal/server/receipts_test.go @@ -19,7 +19,7 @@ func (s *ServerTestSuite) TestReceiptsQuery() { err := cardinal.RegisterMessage[fooIn, fooOut](world, msgName) s.Require().NoError(err) wantErrorMessage := "THIS_ERROR_MESSAGE_SHOULD_BE_IN_THE_RECEIPT" - err = cardinal.RegisterSystems(world, func(ctx cardinal.WorldContext) error { + err = cardinal.RegisterSystems(world, func(ctx cardinal.Context) error { return cardinal.EachMessage[fooIn, fooOut](ctx, func(cardinal.TxData[fooIn]) (fooOut, error) { if ctx.CurrentTick()%2 == 0 { return fooOut{Y: 4}, nil diff --git a/cardinal/server/server.go b/cardinal/server/server.go index 3f8df9328..df98257d1 100644 --- a/cardinal/server/server.go +++ b/cardinal/server/server.go @@ -11,12 +11,10 @@ import ( "github.com/rotisserie/eris" "github.com/rs/zerolog/log" + _ "pkg.world.dev/world-engine/cardinal/server/docs" // for swagger. "pkg.world.dev/world-engine/cardinal/server/handler" servertypes "pkg.world.dev/world-engine/cardinal/server/types" "pkg.world.dev/world-engine/cardinal/types" - "pkg.world.dev/world-engine/cardinal/types/engine" - - _ "pkg.world.dev/world-engine/cardinal/server/docs" // for swagger. ) const ( @@ -36,8 +34,8 @@ type Server struct { // New returns an HTTP server with handlers for all QueryTypes and MessageTypes. func New( - provider servertypes.Provider, wCtx engine.Context, components []types.ComponentMetadata, - messages []types.Message, queries []engine.Query, opts ...Option, + provider servertypes.ProviderWorld, wCtx servertypes.ProviderContext, components []types.ComponentMetadata, + messages []types.Message, queries []servertypes.ProviderQuery, opts ...Option, ) (*Server, error) { app := fiber.New(fiber.Config{ Network: "tcp", // Enable server listening on both ipv4 & ipv6 (default: ipv4 only) @@ -116,14 +114,14 @@ func (s *Server) Shutdown() error { // @consumes application/json // @produces application/json func (s *Server) setupRoutes( - provider servertypes.Provider, wCtx engine.Context, messages []types.Message, - queries []engine.Query, components []types.ComponentMetadata, + provider servertypes.ProviderWorld, wCtx servertypes.ProviderContext, messages []types.Message, + queries []servertypes.ProviderQuery, components []types.ComponentMetadata, ) { // TODO(scott): we should refactor this such that we only dependency inject these maps // instead of having to dependency inject the entire engine. // /query/:group/:queryType // maps group -> queryType -> query - queryIndex := make(map[string]map[string]engine.Query) + queryIndex := make(map[string]map[string]servertypes.ProviderQuery) // /tx/:group/:txType // maps group -> txType -> tx @@ -133,7 +131,7 @@ func (s *Server) setupRoutes( for _, query := range queries { // Initialize inner map if it doesn't exist if _, ok := queryIndex[query.Group()]; !ok { - queryIndex[query.Group()] = make(map[string]engine.Query) + queryIndex[query.Group()] = make(map[string]servertypes.ProviderQuery) } queryIndex[query.Group()][query.Name()] = query } @@ -172,8 +170,8 @@ func (s *Server) setupRoutes( tx.Post("/:group/:name", handler.PostTransaction(provider, msgIndex, s.config.isSignatureVerificationDisabled)) // Route: /cql - s.app.Post("/cql", handler.PostCQL(provider)) + s.app.Post("/cql", handler.PostCQL(provider, wCtx)) // Route: /debug/state - s.app.Post("/debug/state", handler.GetDebugState(provider)) + s.app.Post("/debug/state", handler.GetDebugState(provider, wCtx)) } diff --git a/cardinal/server/server_test.go b/cardinal/server/server_test.go index 5927736be..52485be65 100644 --- a/cardinal/server/server_test.go +++ b/cardinal/server/server_test.go @@ -24,7 +24,6 @@ import ( "pkg.world.dev/world-engine/cardinal/server/utils" "pkg.world.dev/world-engine/cardinal/testutils" "pkg.world.dev/world-engine/cardinal/types" - "pkg.world.dev/world-engine/cardinal/types/engine" "pkg.world.dev/world-engine/sign" ) @@ -203,7 +202,7 @@ func (s *ServerTestSuite) TestQueryCustomGroup() { err := cardinal.RegisterQuery[SomeRequest, SomeResponse]( s.world, name, - func(_ engine.Context, _ *SomeRequest) (*SomeResponse, error) { + func(_ cardinal.Context, _ *SomeRequest) (*SomeResponse, error) { called = true return &SomeResponse{}, nil }, @@ -279,7 +278,7 @@ func (s *ServerTestSuite) setupWorld(opts ...cardinal.WorldOption) { err = cardinal.RegisterMessage[MoveMsgInput, MoveMessageOutput](s.world, moveMsgName) s.Require().NoError(err) personaToPosition := make(map[string]types.EntityID) - err = cardinal.RegisterSystems(s.world, func(context engine.Context) error { + err = cardinal.RegisterSystems(s.world, func(context cardinal.Context) error { return cardinal.EachMessage[MoveMsgInput, MoveMessageOutput](context, func(tx cardinal.TxData[MoveMsgInput]) (MoveMessageOutput, error) { posID, exists := personaToPosition[tx.Tx.PersonaTag] @@ -313,7 +312,7 @@ func (s *ServerTestSuite) setupWorld(opts ...cardinal.WorldOption) { err = cardinal.RegisterQuery[QueryLocationRequest, QueryLocationResponse]( s.world, "location", - func(wCtx engine.Context, req *QueryLocationRequest) (*QueryLocationResponse, error) { + func(wCtx cardinal.Context, req *QueryLocationRequest) (*QueryLocationResponse, error) { locID, exists := personaToPosition[req.Persona] if !exists { return nil, fmt.Errorf("location for %q does not exists", req.Persona) diff --git a/cardinal/server/types/provider.go b/cardinal/server/types/provider.go index 6345f1bf8..fc1853401 100644 --- a/cardinal/server/types/provider.go +++ b/cardinal/server/types/provider.go @@ -1,15 +1,20 @@ package types import ( + "reflect" + + "github.com/rs/zerolog" + "pkg.world.dev/world-engine/cardinal/gamestate" + "pkg.world.dev/world-engine/cardinal/receipt" "pkg.world.dev/world-engine/cardinal/search" "pkg.world.dev/world-engine/cardinal/search/filter" "pkg.world.dev/world-engine/cardinal/types" - "pkg.world.dev/world-engine/cardinal/types/engine" + "pkg.world.dev/world-engine/cardinal/types/txpool" "pkg.world.dev/world-engine/sign" ) -type Provider interface { +type ProviderWorld interface { UseNonce(signerAddress string, nonce uint64) error GetSignerForPersonaTag(personaTag string, tick uint64) (addr string, err error) AddTransaction(id types.MessageID, v any, sig *sign.Transaction) (uint64, types.TxHash) @@ -17,5 +22,36 @@ type Provider interface { GetComponentByName(name string) (types.ComponentMetadata, error) Search(filter filter.ComponentFilter) search.EntitySearch StoreReader() gamestate.Reader - GetReadOnlyCtx() engine.Context + //GetReadOnlyCtx() engine.Context +} + +type ProviderQuery interface { + Name() string + HandleProviderQueryRaw(wCtx ProviderContext, bz []byte) ([]byte, error) + GetRequestFieldInformation() map[string]any + Group() string +} + +type ProviderContext interface { + CurrentTick() uint64 + ReceiptHistorySize() uint64 + GetTransactionReceiptsForTick(tick uint64) ([]receipt.Receipt, error) + Namespace() string + Timestamp() uint64 + Logger() *zerolog.Logger + EmitEvent(map[string]any) error + EmitStringEvent(string) error + SetLogger(logger zerolog.Logger) + AddMessageError(id types.TxHash, err error) + SetMessageResult(id types.TxHash, a any) + GetComponentByName(name string) (types.ComponentMetadata, error) + GetMessageByType(mType reflect.Type) (types.Message, bool) + GetTransactionReceipt(id types.TxHash) (any, []error, bool) + GetSignerForPersonaTag(personaTag string, tick uint64) (addr string, err error) + AddTransaction(id types.MessageID, v any, sig *sign.Transaction) (uint64, types.TxHash) + IsWorldReady() bool + StoreReader() gamestate.Reader + StoreManager() gamestate.Manager + GetTxPool() *txpool.TxPool + IsReadOnly() bool } diff --git a/cardinal/state_test.go b/cardinal/state_test.go index 141b9f971..f4492837a 100644 --- a/cardinal/state_test.go +++ b/cardinal/state_test.go @@ -11,7 +11,6 @@ import ( "pkg.world.dev/world-engine/cardinal/search/filter" "pkg.world.dev/world-engine/cardinal/testutils" "pkg.world.dev/world-engine/cardinal/types" - "pkg.world.dev/world-engine/cardinal/types/engine" ) // comps reduces the typing needed to create a slice of IComponentTypes @@ -232,7 +231,7 @@ func TestCanReloadState(t *testing.T) { err := cardinal.RegisterSystems( world1, - func(wCtx engine.Context) error { + func(wCtx cardinal.Context) error { q := cardinal.NewSearch().Entity(filter.Contains(filter.Component[oneAlphaNumComp]())) assert.NilError( t, q.Each(wCtx, @@ -309,7 +308,7 @@ func TestCanFindTransactionsAfterReloadingEngine(t *testing.T) { assert.NilError(t, cardinal.RegisterMessage[Msg, Result](world, msgName)) err := cardinal.RegisterSystems( world, - func(wCtx engine.Context) error { + func(wCtx cardinal.Context) error { someTx, err := testutils.GetMessage[Msg, Result](wCtx) return cardinal.EachMessage[Msg, Result](wCtx, func(tx cardinal.TxData[Msg]) (Result, error) { someTx.SetResult(wCtx, tx.Hash, Result{}) diff --git a/cardinal/system.go b/cardinal/system.go index 70eebaf9c..a220807b4 100644 --- a/cardinal/system.go +++ b/cardinal/system.go @@ -10,7 +10,6 @@ import ( "github.com/rotisserie/eris" "pkg.world.dev/world-engine/cardinal/statsd" - "pkg.world.dev/world-engine/cardinal/types/engine" ) const ( @@ -20,7 +19,7 @@ const ( var _ SystemManager = &systemManager{} // System is a user-defined function that is executed at every tick. -type System func(ctx engine.Context) error +type System func(ctx Context) error // systemType is an internal entry used to track registered systems. type systemType struct { @@ -39,7 +38,7 @@ type SystemManager interface { // These methods are intentionally made private to avoid other // packages from trying to modify the system manager in the middle of a tick. registerSystems(isInit bool, systems ...System) error - runSystems(wCtx engine.Context) error + runSystems(wCtx Context) error } type systemManager struct { @@ -106,7 +105,7 @@ func (m *systemManager) registerSystems(isInit bool, systemFuncs ...System) erro } // RunSystems runs all the registered system in the order that they were registered. -func (m *systemManager) runSystems(wCtx engine.Context) error { +func (m *systemManager) runSystems(wCtx Context) error { var systemsToRun []systemType if wCtx.CurrentTick() == 0 { systemsToRun = slices.Concat(m.registeredInitSystems, m.registeredSystems) diff --git a/cardinal/system_test.go b/cardinal/system_test.go index bfc3d702f..d737c9d18 100644 --- a/cardinal/system_test.go +++ b/cardinal/system_test.go @@ -9,10 +9,9 @@ import ( "pkg.world.dev/world-engine/cardinal/search/filter" "pkg.world.dev/world-engine/cardinal/testutils" "pkg.world.dev/world-engine/cardinal/types" - "pkg.world.dev/world-engine/cardinal/types/engine" ) -func HealthSystem(wCtx engine.Context) error { +func HealthSystem(wCtx cardinal.Context) error { var errs []error errs = append(errs, cardinal.NewSearch().Entity(filter. Exact(filter.Component[Health]())). @@ -67,11 +66,11 @@ func TestCanRegisterMultipleSystem(t *testing.T) { var firstSystemCalled bool var secondSystemCalled bool - firstSystem := func(engine.Context) error { + firstSystem := func(cardinal.Context) error { firstSystemCalled = true return nil } - secondSystem := func(engine.Context) error { + secondSystem := func(cardinal.Context) error { secondSystemCalled = true return nil } @@ -90,10 +89,10 @@ func TestInitSystemRunsOnce(t *testing.T) { w := tf.World count := 0 count2 := 0 - err := cardinal.RegisterInitSystems(w, func(_ engine.Context) error { + err := cardinal.RegisterInitSystems(w, func(_ cardinal.Context) error { count++ return nil - }, func(_ engine.Context) error { + }, func(_ cardinal.Context) error { count2 += 2 return nil }) diff --git a/cardinal/testutils/testutils.go b/cardinal/testutils/testutils.go index 45691c18d..a907ecfa4 100644 --- a/cardinal/testutils/testutils.go +++ b/cardinal/testutils/testutils.go @@ -11,7 +11,6 @@ import ( "pkg.world.dev/world-engine/cardinal" "pkg.world.dev/world-engine/cardinal/types" - "pkg.world.dev/world-engine/cardinal/types/engine" "pkg.world.dev/world-engine/sign" ) @@ -61,7 +60,7 @@ func UniqueSignature() *sign.Transaction { return UniqueSignatureWithName("some_persona_tag") } -func GetMessage[In any, Out any](wCtx engine.Context) (*cardinal.MessageType[In, Out], error) { +func GetMessage[In any, Out any](wCtx cardinal.Context) (*cardinal.MessageType[In, Out], error) { var msg cardinal.MessageType[In, Out] msgType := reflect.TypeOf(msg) tempRes, ok := wCtx.GetMessageByType(msgType) diff --git a/cardinal/types/engine/context.go b/cardinal/types/engine/context.go index 07a9db9a5..f46d27fb3 100644 --- a/cardinal/types/engine/context.go +++ b/cardinal/types/engine/context.go @@ -1,49 +1,37 @@ package engine -import ( - "reflect" - - "github.com/rs/zerolog" - - "pkg.world.dev/world-engine/cardinal/gamestate" - "pkg.world.dev/world-engine/cardinal/receipt" - "pkg.world.dev/world-engine/cardinal/types" - "pkg.world.dev/world-engine/cardinal/types/txpool" - "pkg.world.dev/world-engine/sign" -) - //go:generate mockgen -source=context.go -package mocks -destination=mocks/context.go -type Context interface { - // Timestamp returns the UNIX timestamp of the tick. - Timestamp() uint64 - // CurrentTick returns the current tick. - CurrentTick() uint64 - // Logger returns the logger that can be used to log messages from within system or query. - Logger() *zerolog.Logger - // EmitEvent emits an event that will be broadcast to all websocket subscribers. - EmitEvent(map[string]any) error - // EmitStringEvent emits a string event that will be broadcast to all websocket subscribers. - // This method is provided for backwards compatability. EmitEvent should be used for most cases. - EmitStringEvent(string) error - // Namespace returns the namespace of the world. - Namespace() string - - // For internal use. - - // SetLogger is used to inject a new logger configuration to an engine context that is already created. - SetLogger(logger zerolog.Logger) - AddMessageError(id types.TxHash, err error) - SetMessageResult(id types.TxHash, a any) - GetComponentByName(name string) (types.ComponentMetadata, error) - GetMessageByType(mType reflect.Type) (types.Message, bool) - GetTransactionReceipt(id types.TxHash) (any, []error, bool) - GetSignerForPersonaTag(personaTag string, tick uint64) (addr string, err error) - GetTransactionReceiptsForTick(tick uint64) ([]receipt.Receipt, error) - ReceiptHistorySize() uint64 - AddTransaction(id types.MessageID, v any, sig *sign.Transaction) (uint64, types.TxHash) - IsWorldReady() bool - StoreReader() gamestate.Reader - StoreManager() gamestate.Manager - GetTxPool() *txpool.TxPool - IsReadOnly() bool -} +//type Context interface { +// // Timestamp returns the UNIX timestamp of the tick. +// Timestamp() uint64 +// // CurrentTick returns the current tick. +// CurrentTick() uint64 +// // Logger returns the logger that can be used to log messages from within system or query. +// Logger() *zerolog.Logger +// // EmitEvent emits an event that will be broadcast to all websocket subscribers. +// EmitEvent(map[string]any) error +// // EmitStringEvent emits a string event that will be broadcast to all websocket subscribers. +// // This method is provided for backwards compatability. EmitEvent should be used for most cases. +// EmitStringEvent(string) error +// // Namespace returns the namespace of the world. +// Namespace() string +// +// // For internal use. +// +// // SetLogger is used to inject a new logger configuration to an engine context that is already created. +// SetLogger(logger zerolog.Logger) +// AddMessageError(id types.TxHash, err error) +// SetMessageResult(id types.TxHash, a any) +// GetComponentByName(name string) (types.ComponentMetadata, error) +// GetMessageByType(mType reflect.Type) (types.Message, bool) +// GetTransactionReceipt(id types.TxHash) (any, []error, bool) +// GetSignerForPersonaTag(personaTag string, tick uint64) (addr string, err error) +// GetTransactionReceiptsForTick(tick uint64) ([]receipt.Receipt, error) +// ReceiptHistorySize() uint64 +// AddTransaction(id types.MessageID, v any, sig *sign.Transaction) (uint64, types.TxHash) +// IsWorldReady() bool +// StoreReader() gamestate.Reader +// StoreManager() gamestate.Manager +// GetTxPool() *txpool.TxPool +// IsReadOnly() bool +//} diff --git a/cardinal/types/engine/query.go b/cardinal/types/engine/query.go index 5180d2706..a098f29c7 100644 --- a/cardinal/types/engine/query.go +++ b/cardinal/types/engine/query.go @@ -1,25 +1,25 @@ package engine -type Query interface { - // Name returns the name of the query. - Name() string - // Group returns the group of the query. - Group() string - // HandleQuery handles queries with concrete types, rather than encoded bytes. - HandleQuery(Context, any) (any, error) - // HandleQueryRaw is given a reference to the engine, json encoded bytes that represent a query request - // and is expected to return a json encoded response struct. - HandleQueryRaw(Context, []byte) ([]byte, error) - // DecodeEVMRequest decodes bytes originating from the evm into the request type, which will be ABI encoded. - DecodeEVMRequest([]byte) (any, error) - // EncodeEVMReply encodes the reply as an abi encoded struct. - EncodeEVMReply(any) ([]byte, error) - // DecodeEVMReply decodes EVM reply bytes, into the concrete go reply type. - DecodeEVMReply([]byte) (any, error) - // EncodeAsABI encodes a go struct in abi format. This is mostly used for testing. - EncodeAsABI(any) ([]byte, error) - // IsEVMCompatible reports if the query is able to be sent from the EVM. - IsEVMCompatible() bool - // GetRequestFieldInformation returns a map of the fields of the query's request type and their types. - GetRequestFieldInformation() map[string]any -} +//type Query interface { +// // Name returns the name of the query. +// Name() string +// // Group returns the group of the query. +// Group() string +// // HandleQuery handles queries with concrete types, rather than encoded bytes. +// HandleQuery(Context, any) (any, error) +// // HandleQueryRaw is given a reference to the engine, json encoded bytes that represent a query request +// // and is expected to return a json encoded response struct. +// HandleQueryRaw(Context, []byte) ([]byte, error) +// // DecodeEVMRequest decodes bytes originating from the evm into the request type, which will be ABI encoded. +// DecodeEVMRequest([]byte) (any, error) +// // EncodeEVMReply encodes the reply as an abi encoded struct. +// EncodeEVMReply(any) ([]byte, error) +// // DecodeEVMReply decodes EVM reply bytes, into the concrete go reply type. +// DecodeEVMReply([]byte) (any, error) +// // EncodeAsABI encodes a go struct in abi format. This is mostly used for testing. +// EncodeAsABI(any) ([]byte, error) +// // IsEVMCompatible reports if the query is able to be sent from the EVM. +// IsEVMCompatible() bool +// // GetRequestFieldInformation returns a map of the fields of the query's request type and their types. +// GetRequestFieldInformation() map[string]any +//} diff --git a/cardinal/util.go b/cardinal/util.go index 6518c4d7a..faec93b1a 100644 --- a/cardinal/util.go +++ b/cardinal/util.go @@ -4,7 +4,6 @@ import ( "github.com/rotisserie/eris" "pkg.world.dev/world-engine/cardinal/server" - "pkg.world.dev/world-engine/cardinal/types/engine" ) var NonFatalError = []error{ @@ -33,7 +32,7 @@ func separateOptions(opts []WorldOption) ( } // panicOnFatalError is a helper function to panic on non-deterministic errors (i.e. Redis error). -func panicOnFatalError(wCtx engine.Context, err error) { +func panicOnFatalError(wCtx Context, err error) { if err != nil && !wCtx.IsReadOnly() && isFatalError(err) { wCtx.Logger().Panic().Err(err).Msgf("fatal error: %v", eris.ToString(err, true)) panic(err) diff --git a/cardinal/world.go b/cardinal/world.go index 30676c1bb..dccdb1c72 100644 --- a/cardinal/world.go +++ b/cardinal/world.go @@ -29,7 +29,6 @@ import ( "pkg.world.dev/world-engine/cardinal/statsd" "pkg.world.dev/world-engine/cardinal/storage/redis" "pkg.world.dev/world-engine/cardinal/types" - "pkg.world.dev/world-engine/cardinal/types/engine" "pkg.world.dev/world-engine/cardinal/types/txpool" "pkg.world.dev/world-engine/cardinal/worldstage" "pkg.world.dev/world-engine/sign" @@ -40,8 +39,8 @@ const ( RedisDialTimeOut = 15 ) -var _ router.Provider = &World{} //nolint:exhaustruct -var _ servertypes.Provider = &World{} //nolint:exhaustruct +var _ router.Provider = &World{} //nolint:exhaustruct +var _ servertypes.ProviderWorld = &World{} //nolint:exhaustruct type World struct { SystemManager @@ -329,12 +328,23 @@ func (w *World) StartGame() error { // receiptHistory tick separately. w.receiptHistory.SetTick(w.CurrentTick()) + //BELOW CODE CANNOT WORK. we may have to move server down to cardinal. + queries := w.GetRegisteredQueries() + providerQueries := make([]servertypes.ProviderQuery, len(queries)) + for _, q := range queries { + pq, success := q.(servertypes.ProviderQuery) + if !success { + return eris.New("failed to cast into provider") + } + providerQueries = append(providerQueries, pq) + } + // Create server // We can't do this is in NewWorld() because the server needs to know the registered messages // and register queries first. We can probably refactor this though. w.server, err = server.New(w, NewReadOnlyWorldContext(w), w.GetRegisteredComponents(), w.GetRegisteredMessages(), - w.GetRegisteredQueries(), w.serverOptions...) + providerQueries, w.serverOptions...) if err != nil { return err } @@ -604,7 +614,7 @@ func (w *World) GetRegisteredComponents() []types.ComponentMetadata { return w.componentManager.GetComponents() } -func (w *World) GetReadOnlyCtx() engine.Context { +func (w *World) GetReadOnlyCtx() Context { return NewReadOnlyWorldContext(w) } diff --git a/cardinal/world_context.go b/cardinal/world_context.go index 7ed0a82d2..2bafba240 100644 --- a/cardinal/world_context.go +++ b/cardinal/world_context.go @@ -9,14 +9,49 @@ import ( "pkg.world.dev/world-engine/cardinal/gamestate" "pkg.world.dev/world-engine/cardinal/receipt" "pkg.world.dev/world-engine/cardinal/types" - "pkg.world.dev/world-engine/cardinal/types/engine" "pkg.world.dev/world-engine/cardinal/types/txpool" "pkg.world.dev/world-engine/cardinal/worldstage" "pkg.world.dev/world-engine/sign" ) +//go:generate mockgen -source=context.go -package mocks -destination=mocks/context.go +type Context interface { + // Timestamp returns the UNIX timestamp of the tick. + Timestamp() uint64 + // CurrentTick returns the current tick. + CurrentTick() uint64 + // Logger returns the logger that can be used to log messages from within system or query. + Logger() *zerolog.Logger + // EmitEvent emits an event that will be broadcast to all websocket subscribers. + EmitEvent(map[string]any) error + // EmitStringEvent emits a string event that will be broadcast to all websocket subscribers. + // This method is provided for backwards compatability. EmitEvent should be used for most cases. + EmitStringEvent(string) error + // Namespace returns the namespace of the world. + Namespace() string + + // For internal use. + + // SetLogger is used to inject a new logger configuration to an engine context that is already created. + SetLogger(logger zerolog.Logger) + AddMessageError(id types.TxHash, err error) + SetMessageResult(id types.TxHash, a any) + GetComponentByName(name string) (types.ComponentMetadata, error) + GetMessageByType(mType reflect.Type) (types.Message, bool) + GetTransactionReceipt(id types.TxHash) (any, []error, bool) + GetSignerForPersonaTag(personaTag string, tick uint64) (addr string, err error) + GetTransactionReceiptsForTick(tick uint64) ([]receipt.Receipt, error) + ReceiptHistorySize() uint64 + AddTransaction(id types.MessageID, v any, sig *sign.Transaction) (uint64, types.TxHash) + IsWorldReady() bool + StoreReader() gamestate.Reader + StoreManager() gamestate.Manager + GetTxPool() *txpool.TxPool + IsReadOnly() bool +} + // interface guard -var _ engine.Context = (*worldContext)(nil) +var _ Context = (*worldContext)(nil) type worldContext struct { world *World @@ -25,7 +60,7 @@ type worldContext struct { readOnly bool } -func newWorldContextForTick(world *World, txPool *txpool.TxPool) engine.Context { +func newWorldContextForTick(world *World, txPool *txpool.TxPool) Context { return &worldContext{ world: world, txPool: txPool, @@ -34,7 +69,7 @@ func newWorldContextForTick(world *World, txPool *txpool.TxPool) engine.Context } } -func NewWorldContext(world *World) engine.Context { +func NewWorldContext(world *World) Context { return &worldContext{ world: world, txPool: nil, @@ -43,7 +78,7 @@ func NewWorldContext(world *World) engine.Context { } } -func NewReadOnlyWorldContext(world *World) engine.Context { +func NewReadOnlyWorldContext(world *World) Context { return &worldContext{ world: world, txPool: nil, diff --git a/cardinal/world_persona_test.go b/cardinal/world_persona_test.go index 7c06f1fe4..4b618001f 100644 --- a/cardinal/world_persona_test.go +++ b/cardinal/world_persona_test.go @@ -14,7 +14,6 @@ import ( "pkg.world.dev/world-engine/cardinal/search/filter" "pkg.world.dev/world-engine/cardinal/testutils" "pkg.world.dev/world-engine/cardinal/types" - "pkg.world.dev/world-engine/cardinal/types/engine" "pkg.world.dev/world-engine/sign" ) @@ -99,7 +98,7 @@ func TestCreatePersonaSystem_WhenCardinalIsRestarted_PersonaTagsAreStillRegister // emitNumberOfPersonaTagsSystem is a system that finds all the registered persona tags and sends them // across a channel. - emitNumberOfPersonaTagsSystem := func(wCtx engine.Context) error { + emitNumberOfPersonaTagsSystem := func(wCtx cardinal.Context) error { result := countPersonaTagsResult{personaTags: map[string]bool{}} err := search.NewSearch(). Entity(filter.Exact(filter.Component[component.SignerComponent]())). diff --git a/cardinal/world_test.go b/cardinal/world_test.go index e45e6030f..4fb5f7a69 100644 --- a/cardinal/world_test.go +++ b/cardinal/world_test.go @@ -20,7 +20,6 @@ import ( "pkg.world.dev/world-engine/cardinal/iterators" "pkg.world.dev/world-engine/cardinal/search/filter" "pkg.world.dev/world-engine/cardinal/types" - "pkg.world.dev/world-engine/cardinal/types/engine" "pkg.world.dev/world-engine/cardinal/worldstage" "pkg.world.dev/world-engine/sign" ) @@ -48,7 +47,7 @@ func TestIfPanicMessageLogged(t *testing.T) { errorTxt := "BIG ERROR OH NO" err = RegisterSystems( world, - func(engine.Context) error { + func(Context) error { panic(errorTxt) }, ) @@ -120,7 +119,7 @@ func TestCanRecoverStateAfterFailedArchetypeChange(t *testing.T) { errorToggleComponent := errors.New("problem with toggle component") err = RegisterSystems( world, - func(wCtx engine.Context) error { + func(wCtx Context) error { // Get the one and only entity ID q := NewSearch().Entity(filter.Contains(filter.Component[ScalarComponentStatic]())) id, err := q.First(wCtx) @@ -213,7 +212,7 @@ func TestCanRecoverTransactionsFromFailedSystemRun(t *testing.T) { err = RegisterSystems( world, - func(wCtx engine.Context) error { + func(wCtx Context) error { q := NewSearch().Entity(filter.Contains(filter.Component[PowerComp]())) id := q.MustFirst(wCtx) entityPower, err := GetComponent[PowerComp](wCtx, id) @@ -318,7 +317,7 @@ func TestCanIdentifyAndFixSystemError(t *testing.T) { // In this test, our "buggy" system fails once Power reaches 3 err = RegisterSystems( world, - func(wCtx engine.Context) error { + func(wCtx Context) error { searchObject := NewSearch().Entity(filter.Exact(filter.Component[onePowerComponent]())) id := searchObject.MustFirst(wCtx) p, err := GetComponent[onePowerComponent](wCtx, id) @@ -362,7 +361,7 @@ func TestCanIdentifyAndFixSystemError(t *testing.T) { // this is our fixed system that can handle Power levels of 3 and higher err = RegisterSystems( world2, - func(wCtx engine.Context) error { + func(wCtx Context) error { p, err := GetComponent[onePowerComponent](wCtx, id) if err != nil { return err @@ -412,35 +411,35 @@ func TestSystemsPanicOnRedisError(t *testing.T) { testCases := []struct { name string // the failFn will be called at a time when the ECB is empty of cached data and redis is down. - failFn func(wCtx engine.Context, goodID types.EntityID) + failFn func(wCtx Context, goodID types.EntityID) }{ { name: "AddComponentTo", - failFn: func(wCtx engine.Context, goodID types.EntityID) { + failFn: func(wCtx Context, goodID types.EntityID) { _ = AddComponentTo[Qux](wCtx, goodID) }, }, { name: "RemoveComponentFrom", - failFn: func(wCtx engine.Context, goodID types.EntityID) { + failFn: func(wCtx Context, goodID types.EntityID) { _ = RemoveComponentFrom[Bar](wCtx, goodID) }, }, { name: "GetComponent", - failFn: func(wCtx engine.Context, goodID types.EntityID) { + failFn: func(wCtx Context, goodID types.EntityID) { _, _ = GetComponent[Foo](wCtx, goodID) }, }, { name: "SetComponent", - failFn: func(wCtx engine.Context, goodID types.EntityID) { + failFn: func(wCtx Context, goodID types.EntityID) { _ = SetComponent[Foo](wCtx, goodID, &Foo{}) }, }, { name: "UpdateComponent", - failFn: func(wCtx engine.Context, goodID types.EntityID) { + failFn: func(wCtx Context, goodID types.EntityID) { _ = UpdateComponent[Foo](wCtx, goodID, func(f *Foo) *Foo { return f }) @@ -465,7 +464,7 @@ func TestSystemsPanicOnRedisError(t *testing.T) { // This system will be called 2 times. The first time, a single entity is Created. The second time, // the previously Created entity is fetched, and then miniRedis is closed. Subsequent attempts to access // data should panic. - assert.NilError(t, RegisterSystems(world, func(wCtx engine.Context) error { + assert.NilError(t, RegisterSystems(world, func(wCtx Context) error { // Set up the entity in the first tick if wCtx.CurrentTick() == 0 { _, err := Create(wCtx, Foo{}, Bar{}) @@ -537,7 +536,7 @@ func doTickCapturePanic(ctx context.Context, world *World) (err error) { return nil } -func getMessage[In any, Out any](wCtx engine.Context) (*MessageType[In, Out], error) { +func getMessage[In any, Out any](wCtx Context) (*MessageType[In, Out], error) { var msg MessageType[In, Out] msgType := reflect.TypeOf(msg) tempRes, ok := wCtx.GetMessageByType(msgType) From 2d5aaaa1b78196a73ee4477f3e2e67f0535c689b Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Mon, 6 May 2024 17:27:34 -0700 Subject: [PATCH 07/76] changed. Issue with QUeries in world.go --- cardinal/world.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cardinal/world.go b/cardinal/world.go index dccdb1c72..f4ba1f549 100644 --- a/cardinal/world.go +++ b/cardinal/world.go @@ -338,13 +338,13 @@ func (w *World) StartGame() error { } providerQueries = append(providerQueries, pq) } - + q := w.GetRegisteredQueries() // Create server // We can't do this is in NewWorld() because the server needs to know the registered messages // and register queries first. We can probably refactor this though. w.server, err = server.New(w, NewReadOnlyWorldContext(w), w.GetRegisteredComponents(), w.GetRegisteredMessages(), - providerQueries, w.serverOptions...) + queries, w.serverOptions...) if err != nil { return err } From bf065fa09dcaef6861abf49a501717c354ab4bc1 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Mon, 6 May 2024 17:28:17 -0700 Subject: [PATCH 08/76] changed. Issue with QUeries in world.go --- cardinal/world.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cardinal/world.go b/cardinal/world.go index f4ba1f549..acc556ac3 100644 --- a/cardinal/world.go +++ b/cardinal/world.go @@ -338,7 +338,7 @@ func (w *World) StartGame() error { } providerQueries = append(providerQueries, pq) } - q := w.GetRegisteredQueries() + queries := w.GetRegisteredQueries() // Create server // We can't do this is in NewWorld() because the server needs to know the registered messages // and register queries first. We can probably refactor this though. From cf8f6d8a5ad3d9315c3137a06ffa1c53a833d936 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Mon, 6 May 2024 17:30:11 -0700 Subject: [PATCH 09/76] not working. --- cardinal/query.go | 18 ------------------ cardinal/server/handler/query.go | 2 +- cardinal/server/types/provider.go | 2 +- cardinal/world.go | 3 +-- 4 files changed, 3 insertions(+), 22 deletions(-) diff --git a/cardinal/query.go b/cardinal/query.go index 26b57b75e..5a761038b 100644 --- a/cardinal/query.go +++ b/cardinal/query.go @@ -8,7 +8,6 @@ import ( "github.com/rotisserie/eris" "pkg.world.dev/world-engine/cardinal/abi" - servertypes "pkg.world.dev/world-engine/cardinal/server/types" "pkg.world.dev/world-engine/cardinal/types" ) @@ -151,23 +150,6 @@ func (r *queryType[req, rep]) HandleQueryRaw(wCtx Context, bz []byte) ([]byte, e return bz, nil } -func (r *queryType[req, rep]) HandleProviderQueryRaw(wCtx servertypes.ProviderContext, bz []byte) ([]byte, error) { - request := new(req) - err := json.Unmarshal(bz, request) - if err != nil { - return nil, eris.Wrapf(err, "unable to unmarshal query request into type %T", *request) - } - res, err := r.handler(wCtx, request) - if err != nil { - return nil, err - } - bz, err = json.Marshal(res) - if err != nil { - return nil, eris.Wrapf(err, "unable to marshal response %T", res) - } - return bz, nil -} - func (r *queryType[req, rep]) DecodeEVMRequest(bz []byte) (any, error) { if r.requestABI == nil { return nil, eris.Wrap(ErrEVMTypeNotSet, "") diff --git a/cardinal/server/handler/query.go b/cardinal/server/handler/query.go index ab308ae9d..e68d900ba 100644 --- a/cardinal/server/handler/query.go +++ b/cardinal/server/handler/query.go @@ -26,7 +26,7 @@ func PostQuery(queries map[string]map[string]types.ProviderQuery, wCtx types.Pro } ctx.Set("Content-Type", "application/json") - resBz, err := query.HandleProviderQueryRaw(wCtx, ctx.Body()) + resBz, err := query.HandleQueryRaw(wCtx, ctx.Body()) if err != nil { return fiber.NewError(fiber.StatusBadRequest, "encountered an error in query: "+err.Error()) } diff --git a/cardinal/server/types/provider.go b/cardinal/server/types/provider.go index fc1853401..f161cbb8e 100644 --- a/cardinal/server/types/provider.go +++ b/cardinal/server/types/provider.go @@ -27,7 +27,7 @@ type ProviderWorld interface { type ProviderQuery interface { Name() string - HandleProviderQueryRaw(wCtx ProviderContext, bz []byte) ([]byte, error) + HandleQueryRaw(wCtx ProviderContext, bz []byte) ([]byte, error) GetRequestFieldInformation() map[string]any Group() string } diff --git a/cardinal/world.go b/cardinal/world.go index acc556ac3..f241747a4 100644 --- a/cardinal/world.go +++ b/cardinal/world.go @@ -338,13 +338,12 @@ func (w *World) StartGame() error { } providerQueries = append(providerQueries, pq) } - queries := w.GetRegisteredQueries() // Create server // We can't do this is in NewWorld() because the server needs to know the registered messages // and register queries first. We can probably refactor this though. w.server, err = server.New(w, NewReadOnlyWorldContext(w), w.GetRegisteredComponents(), w.GetRegisteredMessages(), - queries, w.serverOptions...) + w.GetRegisteredQueries(), w.serverOptions...) if err != nil { return err } From e7781af812a785ac6251068db395deead83cd600 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Tue, 7 May 2024 13:43:51 -0700 Subject: [PATCH 10/76] minor lint stuff. --- cardinal/server/handler/cql.go | 4 +++- cardinal/server/handler/query.go | 4 +++- cardinal/types/engine/context.go | 2 +- cardinal/types/engine/query.go | 2 +- cardinal/world.go | 10 ---------- 5 files changed, 8 insertions(+), 14 deletions(-) diff --git a/cardinal/server/handler/cql.go b/cardinal/server/handler/cql.go index 58ee67845..76d5f44b6 100644 --- a/cardinal/server/handler/cql.go +++ b/cardinal/server/handler/cql.go @@ -34,7 +34,9 @@ type CQLQueryResponse struct { // @Success 200 {object} CQLQueryResponse "Results of the executed CQL query" // @Failure 400 {string} string "Invalid request parameters" // @Router /cql [post] -func PostCQL(provider servertypes.ProviderWorld, wCtx servertypes.ProviderContext) func(*fiber.Ctx) error { //nolint:gocognit // to refactor later +func PostCQL( + provider servertypes.ProviderWorld, + wCtx servertypes.ProviderContext) func(*fiber.Ctx) error { //nolint:gocognit // to refactor later return func(ctx *fiber.Ctx) error { req := new(CQLQueryRequest) if err := ctx.BodyParser(req); err != nil { diff --git a/cardinal/server/handler/query.go b/cardinal/server/handler/query.go index e68d900ba..f476a6fe8 100644 --- a/cardinal/server/handler/query.go +++ b/cardinal/server/handler/query.go @@ -47,6 +47,8 @@ func PostQuery(queries map[string]map[string]types.ProviderQuery, wCtx types.Pro // @Success 200 {object} object "Results of the executed query" // @Failure 400 {string} string "Invalid request parameters" // @Router /query/game/{queryName} [post] -func PostGameQuery(queries map[string]map[string]types.ProviderQuery, wCtx types.ProviderContext) func(*fiber.Ctx) error { +func PostGameQuery( + queries map[string]map[string]types.ProviderQuery, + wCtx types.ProviderContext) func(*fiber.Ctx) error { return PostQuery(queries, wCtx) } diff --git a/cardinal/types/engine/context.go b/cardinal/types/engine/context.go index f46d27fb3..a1879ac17 100644 --- a/cardinal/types/engine/context.go +++ b/cardinal/types/engine/context.go @@ -1,7 +1,7 @@ package engine //go:generate mockgen -source=context.go -package mocks -destination=mocks/context.go -//type Context interface { +// type Context interface { // // Timestamp returns the UNIX timestamp of the tick. // Timestamp() uint64 // // CurrentTick returns the current tick. diff --git a/cardinal/types/engine/query.go b/cardinal/types/engine/query.go index a098f29c7..53062eeba 100644 --- a/cardinal/types/engine/query.go +++ b/cardinal/types/engine/query.go @@ -1,6 +1,6 @@ package engine -//type Query interface { +// type Query interface { // // Name returns the name of the query. // Name() string // // Group returns the group of the query. diff --git a/cardinal/world.go b/cardinal/world.go index f241747a4..46aa1f2b4 100644 --- a/cardinal/world.go +++ b/cardinal/world.go @@ -328,16 +328,6 @@ func (w *World) StartGame() error { // receiptHistory tick separately. w.receiptHistory.SetTick(w.CurrentTick()) - //BELOW CODE CANNOT WORK. we may have to move server down to cardinal. - queries := w.GetRegisteredQueries() - providerQueries := make([]servertypes.ProviderQuery, len(queries)) - for _, q := range queries { - pq, success := q.(servertypes.ProviderQuery) - if !success { - return eris.New("failed to cast into provider") - } - providerQueries = append(providerQueries, pq) - } // Create server // We can't do this is in NewWorld() because the server needs to know the registered messages // and register queries first. We can probably refactor this though. From 7e2db70cba33312bd75be59ac3ac82a6435ce2e2 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Tue, 7 May 2024 17:34:26 -0700 Subject: [PATCH 11/76] tests passing work on clean up later. --- cardinal/query.go | 45 ++++++++++++++++++++++++++++++++ cardinal/server/handler/query.go | 31 +++++----------------- cardinal/server/handler/world.go | 38 ++++++--------------------- cardinal/server/server.go | 39 ++++++++++++--------------- cardinal/server/server_test.go | 9 ++++--- cardinal/types/engine/info.go | 14 ++++++++++ cardinal/types/engine/query.go | 24 +---------------- cardinal/world.go | 5 +++- 8 files changed, 100 insertions(+), 105 deletions(-) create mode 100644 cardinal/types/engine/info.go diff --git a/cardinal/query.go b/cardinal/query.go index 5a761038b..9aac7b4fa 100644 --- a/cardinal/query.go +++ b/cardinal/query.go @@ -8,7 +8,9 @@ import ( "github.com/rotisserie/eris" "pkg.world.dev/world-engine/cardinal/abi" + "pkg.world.dev/world-engine/cardinal/server/utils" "pkg.world.dev/world-engine/cardinal/types" + "pkg.world.dev/world-engine/cardinal/types/engine" ) type Query interface { @@ -265,3 +267,46 @@ func validateQuery[Request any, Reply any]( } return nil } + +type QueryHandler = func(name string, group string, bz []byte) ([]byte, error) + +func BuildUniversalQueryHandler(world *World) QueryHandler { + queries := world.GetRegisteredQueries() + queryIndex := make(map[string]map[string]Query) + wCtx := NewReadOnlyWorldContext(world) + // Create query index + for _, query := range queries { + // Initialize inner map if it doesn't exist + if _, ok := queryIndex[query.Group()]; !ok { + queryIndex[query.Group()] = make(map[string]Query) + } + queryIndex[query.Group()][query.Name()] = query + } + + return func(name string, group string, bz []byte) ([]byte, error) { + first, ok := queryIndex[group] + if !ok { + return nil, eris.Errorf("query with name %s not found", name) + } + query, ok := first[name] + if !ok { + return nil, eris.Errorf("query with group %s not found", group) + } + return query.HandleQueryRaw(wCtx, bz) + } +} + +func BuildQueryFields(world *World) []engine.FieldDetail { + // Collecting the structure of all queries + queries := world.GetRegisteredQueries() + queriesFields := make([]engine.FieldDetail, 0, len(queries)) + for _, query := range queries { + // Extracting the fields of the query + queriesFields = append(queriesFields, engine.FieldDetail{ + Name: query.Name(), + Fields: query.GetRequestFieldInformation(), + URL: utils.GetQueryURL(query.Group(), query.Name()), + }) + } + return queriesFields +} diff --git a/cardinal/server/handler/query.go b/cardinal/server/handler/query.go index f476a6fe8..fcd28283b 100644 --- a/cardinal/server/handler/query.go +++ b/cardinal/server/handler/query.go @@ -4,6 +4,7 @@ import ( "github.com/gofiber/fiber/v2" "pkg.world.dev/world-engine/cardinal/server/types" + "pkg.world.dev/world-engine/cardinal/types/engine" ) // PostQuery godoc @@ -18,15 +19,13 @@ import ( // @Success 200 {object} object "Results of the executed query" // @Failure 400 {string} string "Invalid request parameters" // @Router /query/{queryGroup}/{queryName} [post] -func PostQuery(queries map[string]map[string]types.ProviderQuery, wCtx types.ProviderContext) func(*fiber.Ctx) error { +func PostQuery(queryHandler engine.QueryHandler, wCtx types.ProviderContext) func(*fiber.Ctx) error { return func(ctx *fiber.Ctx) error { - query, ok := queries[ctx.Params("group")][ctx.Params("name")] - if !ok { - return fiber.NewError(fiber.StatusNotFound, "query name not found") - } - ctx.Set("Content-Type", "application/json") - resBz, err := query.HandleQueryRaw(wCtx, ctx.Body()) + resBz, err := queryHandler(ctx.Params("name"), ctx.Params("group"), ctx.Body()) + if err != nil { + return fiber.NewError(fiber.StatusNotFound, "query not found") + } if err != nil { return fiber.NewError(fiber.StatusBadRequest, "encountered an error in query: "+err.Error()) } @@ -34,21 +33,3 @@ func PostQuery(queries map[string]map[string]types.ProviderQuery, wCtx types.Pro return ctx.Send(resBz) } } - -// NOTE: duplication for cleaner swagger docs -// PostQuery godoc -// -// @Summary Executes a query -// @Description Executes a query -// @Accept application/json -// @Produce application/json -// @Param queryName path string true "Name of a registered query" -// @Param queryBody body object true "Query to be executed" -// @Success 200 {object} object "Results of the executed query" -// @Failure 400 {string} string "Invalid request parameters" -// @Router /query/game/{queryName} [post] -func PostGameQuery( - queries map[string]map[string]types.ProviderQuery, - wCtx types.ProviderContext) func(*fiber.Ctx) error { - return PostQuery(queries, wCtx) -} diff --git a/cardinal/server/handler/world.go b/cardinal/server/handler/world.go index 12bfd2ded..30aa2f8bd 100644 --- a/cardinal/server/handler/world.go +++ b/cardinal/server/handler/world.go @@ -5,24 +5,11 @@ import ( "github.com/gofiber/fiber/v2" - servertypes "pkg.world.dev/world-engine/cardinal/server/types" "pkg.world.dev/world-engine/cardinal/server/utils" "pkg.world.dev/world-engine/cardinal/types" + "pkg.world.dev/world-engine/cardinal/types/engine" ) -type GetWorldResponse struct { - Namespace string `json:"namespace"` - Components []FieldDetail `json:"components"` // list of component names - Messages []FieldDetail `json:"messages"` - Queries []FieldDetail `json:"queries"` -} - -type FieldDetail struct { - Name string `json:"name"` // name of the message or query - Fields map[string]any `json:"fields"` // variable name and type - URL string `json:"url,omitempty"` -} - // GetWorld godoc // // @Summary Retrieves details of the game world @@ -34,23 +21,23 @@ type FieldDetail struct { // @Router /world [get] func GetWorld( components []types.ComponentMetadata, messages []types.Message, - queries []servertypes.ProviderQuery, namespace string, + queryFields []engine.FieldDetail, namespace string, ) func(*fiber.Ctx) error { // Collecting name of all registered components - comps := make([]FieldDetail, 0, len(components)) + comps := make([]engine.FieldDetail, 0, len(components)) for _, component := range components { c, _ := component.Decode(component.GetSchema()) - comps = append(comps, FieldDetail{ + comps = append(comps, engine.FieldDetail{ Name: component.Name(), Fields: types.GetFieldInformation(reflect.TypeOf(c)), }) } // Collecting the structure of all messages - messagesFields := make([]FieldDetail, 0, len(messages)) + messagesFields := make([]engine.FieldDetail, 0, len(messages)) for _, message := range messages { // Extracting the fields of the message - messagesFields = append(messagesFields, FieldDetail{ + messagesFields = append(messagesFields, engine.FieldDetail{ Name: message.Name(), Fields: message.GetInFieldInformation(), URL: utils.GetTxURL(message.Group(), message.Name()), @@ -58,22 +45,13 @@ func GetWorld( } // Collecting the structure of all queries - queriesFields := make([]FieldDetail, 0, len(queries)) - for _, query := range queries { - // Extracting the fields of the query - queriesFields = append(queriesFields, FieldDetail{ - Name: query.Name(), - Fields: query.GetRequestFieldInformation(), - URL: utils.GetQueryURL(query.Group(), query.Name()), - }) - } return func(ctx *fiber.Ctx) error { - return ctx.JSON(GetWorldResponse{ + return ctx.JSON(engine.GetWorldResponse{ Namespace: namespace, Components: comps, Messages: messagesFields, - Queries: queriesFields, + Queries: queryFields, }) } } diff --git a/cardinal/server/server.go b/cardinal/server/server.go index df98257d1..a81ff3009 100644 --- a/cardinal/server/server.go +++ b/cardinal/server/server.go @@ -15,6 +15,7 @@ import ( "pkg.world.dev/world-engine/cardinal/server/handler" servertypes "pkg.world.dev/world-engine/cardinal/server/types" "pkg.world.dev/world-engine/cardinal/types" + "pkg.world.dev/world-engine/cardinal/types/engine" ) const ( @@ -34,8 +35,13 @@ type Server struct { // New returns an HTTP server with handlers for all QueryTypes and MessageTypes. func New( - provider servertypes.ProviderWorld, wCtx servertypes.ProviderContext, components []types.ComponentMetadata, - messages []types.Message, queries []servertypes.ProviderQuery, opts ...Option, + provider servertypes.ProviderWorld, + wCtx servertypes.ProviderContext, + components []types.ComponentMetadata, + messages []types.Message, + queryHandler engine.QueryHandler, + queryFields []engine.FieldDetail, + opts ...Option, ) (*Server, error) { app := fiber.New(fiber.Config{ Network: "tcp", // Enable server listening on both ipv4 & ipv6 (default: ipv4 only) @@ -57,7 +63,7 @@ func New( app.Use(cors.New()) // Register routes - s.setupRoutes(provider, wCtx, messages, queries, components) + s.setupRoutes(provider, wCtx, messages, queryHandler, queryFields, components) return s, nil } @@ -114,28 +120,17 @@ func (s *Server) Shutdown() error { // @consumes application/json // @produces application/json func (s *Server) setupRoutes( - provider servertypes.ProviderWorld, wCtx servertypes.ProviderContext, messages []types.Message, - queries []servertypes.ProviderQuery, components []types.ComponentMetadata, + provider servertypes.ProviderWorld, + wCtx servertypes.ProviderContext, + messages []types.Message, + queryHandler engine.QueryHandler, + queryFields []engine.FieldDetail, + components []types.ComponentMetadata, ) { - // TODO(scott): we should refactor this such that we only dependency inject these maps - // instead of having to dependency inject the entire engine. - // /query/:group/:queryType - // maps group -> queryType -> query - queryIndex := make(map[string]map[string]servertypes.ProviderQuery) - // /tx/:group/:txType // maps group -> txType -> tx msgIndex := make(map[string]map[string]types.Message) - // Create query index - for _, query := range queries { - // Initialize inner map if it doesn't exist - if _, ok := queryIndex[query.Group()]; !ok { - queryIndex[query.Group()] = make(map[string]servertypes.ProviderQuery) - } - queryIndex[query.Group()][query.Name()] = query - } - // Create tx index for _, msg := range messages { // Initialize inner map if it doesn't exist @@ -155,7 +150,7 @@ func (s *Server) setupRoutes( s.app.Get("/events", handler.WebSocketEvents()) // Route: /world - s.app.Get("/world", handler.GetWorld(components, messages, queries, wCtx.Namespace())) + s.app.Get("/world", handler.GetWorld(components, messages, queryFields, wCtx.Namespace())) // Route: /... s.app.Get("/health", handler.GetHealth()) @@ -163,7 +158,7 @@ func (s *Server) setupRoutes( // Route: /query/... query := s.app.Group("/query") query.Post("/receipts/list", handler.GetReceipts(wCtx)) - query.Post("/:group/:name", handler.PostQuery(queryIndex, wCtx)) + query.Post("/:group/:name", handler.PostQuery(queryHandler, wCtx)) // Route: /tx/... tx := s.app.Group("/tx") diff --git a/cardinal/server/server_test.go b/cardinal/server/server_test.go index 52485be65..3db2fd1a8 100644 --- a/cardinal/server/server_test.go +++ b/cardinal/server/server_test.go @@ -24,6 +24,7 @@ import ( "pkg.world.dev/world-engine/cardinal/server/utils" "pkg.world.dev/world-engine/cardinal/testutils" "pkg.world.dev/world-engine/cardinal/types" + "pkg.world.dev/world-engine/cardinal/types/engine" "pkg.world.dev/world-engine/sign" ) @@ -95,7 +96,7 @@ func (s *ServerTestSuite) TestGetWorld() { s.setupWorld() s.fixture.DoTick() res := s.fixture.Get("/world") - var result handler.GetWorldResponse + var result engine.GetWorldResponse err := json.Unmarshal([]byte(s.readBody(res.Body)), &result) s.Require().NoError(err) comps := s.world.GetRegisteredComponents() @@ -108,17 +109,17 @@ func (s *ServerTestSuite) TestGetWorld() { // check that the component, message, query name are in the list for _, comp := range comps { - assert.True(s.T(), slices.ContainsFunc(result.Components, func(field handler.FieldDetail) bool { + assert.True(s.T(), slices.ContainsFunc(result.Components, func(field engine.FieldDetail) bool { return comp.Name() == field.Name })) } for _, msg := range msgs { - assert.True(s.T(), slices.ContainsFunc(result.Messages, func(field handler.FieldDetail) bool { + assert.True(s.T(), slices.ContainsFunc(result.Messages, func(field engine.FieldDetail) bool { return msg.Name() == field.Name })) } for _, query := range queries { - assert.True(s.T(), slices.ContainsFunc(result.Queries, func(field handler.FieldDetail) bool { + assert.True(s.T(), slices.ContainsFunc(result.Queries, func(field engine.FieldDetail) bool { return query.Name() == field.Name })) } diff --git a/cardinal/types/engine/info.go b/cardinal/types/engine/info.go new file mode 100644 index 000000000..0ee8bd1b5 --- /dev/null +++ b/cardinal/types/engine/info.go @@ -0,0 +1,14 @@ +package engine + +type GetWorldResponse struct { + Namespace string `json:"namespace"` + Components []FieldDetail `json:"components"` // list of component names + Messages []FieldDetail `json:"messages"` + Queries []FieldDetail `json:"queries"` +} + +type FieldDetail struct { + Name string `json:"name"` // name of the message or query + Fields map[string]any `json:"fields"` // variable name and type + URL string `json:"url,omitempty"` +} diff --git a/cardinal/types/engine/query.go b/cardinal/types/engine/query.go index 53062eeba..c2b333560 100644 --- a/cardinal/types/engine/query.go +++ b/cardinal/types/engine/query.go @@ -1,25 +1,3 @@ package engine -// type Query interface { -// // Name returns the name of the query. -// Name() string -// // Group returns the group of the query. -// Group() string -// // HandleQuery handles queries with concrete types, rather than encoded bytes. -// HandleQuery(Context, any) (any, error) -// // HandleQueryRaw is given a reference to the engine, json encoded bytes that represent a query request -// // and is expected to return a json encoded response struct. -// HandleQueryRaw(Context, []byte) ([]byte, error) -// // DecodeEVMRequest decodes bytes originating from the evm into the request type, which will be ABI encoded. -// DecodeEVMRequest([]byte) (any, error) -// // EncodeEVMReply encodes the reply as an abi encoded struct. -// EncodeEVMReply(any) ([]byte, error) -// // DecodeEVMReply decodes EVM reply bytes, into the concrete go reply type. -// DecodeEVMReply([]byte) (any, error) -// // EncodeAsABI encodes a go struct in abi format. This is mostly used for testing. -// EncodeAsABI(any) ([]byte, error) -// // IsEVMCompatible reports if the query is able to be sent from the EVM. -// IsEVMCompatible() bool -// // GetRequestFieldInformation returns a map of the fields of the query's request type and their types. -// GetRequestFieldInformation() map[string]any -//} +type QueryHandler = func(name string, group string, bz []byte) ([]byte, error) diff --git a/cardinal/world.go b/cardinal/world.go index 58666ecf9..4741f3de5 100644 --- a/cardinal/world.go +++ b/cardinal/world.go @@ -329,12 +329,15 @@ func (w *World) StartGame() error { // receiptHistory tick separately. w.receiptHistory.SetTick(w.CurrentTick()) + queryHandler := BuildUniversalQueryHandler(w) + queryFields := BuildQueryFields(w) + // Create server // We can't do this is in NewWorld() because the server needs to know the registered messages // and register queries first. We can probably refactor this though. w.server, err = server.New(w, NewReadOnlyWorldContext(w), w.GetRegisteredComponents(), w.GetRegisteredMessages(), - w.GetRegisteredQueries(), w.serverOptions...) + queryHandler, queryFields, w.serverOptions...) if err != nil { return err } From 8fa31c63049df55da4f10c03b7968fe04c795421 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Tue, 7 May 2024 17:37:09 -0700 Subject: [PATCH 12/76] refine error messages. --- cardinal/query.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cardinal/query.go b/cardinal/query.go index 9aac7b4fa..673ceca8f 100644 --- a/cardinal/query.go +++ b/cardinal/query.go @@ -284,13 +284,13 @@ func BuildUniversalQueryHandler(world *World) QueryHandler { } return func(name string, group string, bz []byte) ([]byte, error) { - first, ok := queryIndex[group] + groupIndex, ok := queryIndex[group] if !ok { - return nil, eris.Errorf("query with name %s not found", name) + return nil, eris.Errorf("query with group %s not found", group) } - query, ok := first[name] + query, ok := groupIndex[name] if !ok { - return nil, eris.Errorf("query with group %s not found", group) + return nil, eris.Errorf("query with name %s not found", name) } return query.HandleQueryRaw(wCtx, bz) } From 4831cf9c1d8cf3005b3cab14969722ff579533d9 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Thu, 9 May 2024 16:02:10 -0700 Subject: [PATCH 13/76] removed context requirement for queries. --- cardinal/cardinal.go | 4 +- cardinal/query.go | 43 ------------ cardinal/query_manager.go | 35 +++++++++- cardinal/server/debug_test.go | 10 +-- cardinal/server/handler/cql.go | 39 +---------- cardinal/server/handler/debug.go | 43 +----------- cardinal/server/handler/query.go | 7 +- cardinal/server/handler/receipts.go | 8 +-- cardinal/server/handler/world.go | 9 ++- cardinal/server/server.go | 19 ++---- cardinal/server/types/provider.go | 40 ++--------- cardinal/types/cql.go | 8 +++ cardinal/types/debug.go | 12 ++++ cardinal/types/engine/context.go | 4 +- cardinal/types/engine/mocks/context.go | 6 +- cardinal/world.go | 93 +++++++++++++++++++++++--- 16 files changed, 182 insertions(+), 198 deletions(-) create mode 100644 cardinal/types/cql.go create mode 100644 cardinal/types/debug.go diff --git a/cardinal/cardinal.go b/cardinal/cardinal.go index 3946a3dcb..278345476 100644 --- a/cardinal/cardinal.go +++ b/cardinal/cardinal.go @@ -168,7 +168,9 @@ func RegisterQuery[Request any, Reply any]( return err } - return w.RegisterQuery(name, q) + res := w.RegisterQuery(name, q) + w.BuildQueryIndex(w) + return res } // Create creates a single entity in the world, and returns the id of the newly created entity. diff --git a/cardinal/query.go b/cardinal/query.go index 673ceca8f..41ab5aa68 100644 --- a/cardinal/query.go +++ b/cardinal/query.go @@ -8,9 +8,7 @@ import ( "github.com/rotisserie/eris" "pkg.world.dev/world-engine/cardinal/abi" - "pkg.world.dev/world-engine/cardinal/server/utils" "pkg.world.dev/world-engine/cardinal/types" - "pkg.world.dev/world-engine/cardinal/types/engine" ) type Query interface { @@ -269,44 +267,3 @@ func validateQuery[Request any, Reply any]( } type QueryHandler = func(name string, group string, bz []byte) ([]byte, error) - -func BuildUniversalQueryHandler(world *World) QueryHandler { - queries := world.GetRegisteredQueries() - queryIndex := make(map[string]map[string]Query) - wCtx := NewReadOnlyWorldContext(world) - // Create query index - for _, query := range queries { - // Initialize inner map if it doesn't exist - if _, ok := queryIndex[query.Group()]; !ok { - queryIndex[query.Group()] = make(map[string]Query) - } - queryIndex[query.Group()][query.Name()] = query - } - - return func(name string, group string, bz []byte) ([]byte, error) { - groupIndex, ok := queryIndex[group] - if !ok { - return nil, eris.Errorf("query with group %s not found", group) - } - query, ok := groupIndex[name] - if !ok { - return nil, eris.Errorf("query with name %s not found", name) - } - return query.HandleQueryRaw(wCtx, bz) - } -} - -func BuildQueryFields(world *World) []engine.FieldDetail { - // Collecting the structure of all queries - queries := world.GetRegisteredQueries() - queriesFields := make([]engine.FieldDetail, 0, len(queries)) - for _, query := range queries { - // Extracting the fields of the query - queriesFields = append(queriesFields, engine.FieldDetail{ - Name: query.Name(), - Fields: query.GetRequestFieldInformation(), - URL: utils.GetQueryURL(query.Group(), query.Name()), - }) - } - return queriesFields -} diff --git a/cardinal/query_manager.go b/cardinal/query_manager.go index 407eee540..41244b814 100644 --- a/cardinal/query_manager.go +++ b/cardinal/query_manager.go @@ -8,10 +8,13 @@ type QueryManager interface { RegisterQuery(name string, query Query) error GetRegisteredQueries() []Query GetQueryByName(name string) (Query, error) + BuildQueryIndex(world *World) + GetQueryIndex() map[string]map[string]Query } type queryManager struct { registeredQueries map[string]Query + queryIndex map[string]map[string]Query } func newQueryManager() QueryManager { @@ -20,6 +23,10 @@ func newQueryManager() QueryManager { } } +func (m *queryManager) GetQueryIndex() map[string]map[string]Query { + return m.queryIndex +} + // RegisterQuery registers a query with the query manager. // There can only be one query with a given name. func (m *queryManager) RegisterQuery(name string, query Query) error { @@ -30,7 +37,6 @@ func (m *queryManager) RegisterQuery(name string, query Query) error { // Register the query m.registeredQueries[name] = query - return nil } @@ -43,6 +49,33 @@ func (m *queryManager) GetRegisteredQueries() []Query { return registeredQueries } +func (m *queryManager) BuildQueryIndex(world *World) { + queries := world.GetRegisteredQueries() + m.queryIndex = make(map[string]map[string]Query) + // Create query index + for _, query := range queries { + // Initialize inner map if it doesn't exist + if _, ok := m.queryIndex[query.Group()]; !ok { + m.queryIndex[query.Group()] = make(map[string]Query) + } + m.queryIndex[query.Group()][query.Name()] = query + } +} +func (w *World) QueryHandler(name string, group string, bz []byte) ([]byte, error) { + index := w.QueryManager.GetQueryIndex() + groupIndex, ok := index[group] + + if !ok { + return nil, eris.Errorf("query with group %s not found", group) + } + query, ok := groupIndex[name] + if !ok { + return nil, eris.Errorf("query with name %s not found", name) + } + wCtx := NewReadOnlyWorldContext(w) + return query.HandleQueryRaw(wCtx, bz) +} + // GetQueryByName returns a query corresponding to its name. func (m *queryManager) GetQueryByName(name string) (Query, error) { query, ok := m.registeredQueries[name] diff --git a/cardinal/server/debug_test.go b/cardinal/server/debug_test.go index 6e3e436e8..ced02b44b 100644 --- a/cardinal/server/debug_test.go +++ b/cardinal/server/debug_test.go @@ -4,7 +4,7 @@ import ( "encoding/json" "pkg.world.dev/world-engine/cardinal" - "pkg.world.dev/world-engine/cardinal/server/handler" + "pkg.world.dev/world-engine/cardinal/types" ) func (s *ServerTestSuite) TestDebugStateQuery() { @@ -20,11 +20,11 @@ func (s *ServerTestSuite) TestDebugStateQuery() { // This will create 1 additional location for this particular persona tag s.runTx(personaTag, moveMessage, MoveMsgInput{Direction: "up"}) - res := s.fixture.Post("debug/state", handler.DebugStateRequest{}) + res := s.fixture.Post("debug/state", types.DebugStateRequest{}) s.Require().NoError(err) s.Require().Equal(res.StatusCode, 200) - var results handler.DebugStateResponse + var results types.DebugStateResponse s.Require().NoError(json.NewDecoder(res.Body).Decode(&results)) numOfZeroLocation := 0 @@ -50,10 +50,10 @@ func (s *ServerTestSuite) TestDebugStateQuery_NoState() { s.setupWorld() s.fixture.DoTick() - res := s.fixture.Post("debug/state", handler.DebugStateRequest{}) + res := s.fixture.Post("debug/state", types.DebugStateRequest{}) s.Require().Equal(res.StatusCode, 200) - var results handler.DebugStateResponse + var results types.DebugStateResponse s.Require().NoError(json.NewDecoder(res.Body).Decode(&results)) s.Require().Equal(len(results), 0) diff --git a/cardinal/server/handler/cql.go b/cardinal/server/handler/cql.go index 76d5f44b6..c1df0905d 100644 --- a/cardinal/server/handler/cql.go +++ b/cardinal/server/handler/cql.go @@ -3,7 +3,6 @@ package handler import "C" import ( - "github.com/goccy/go-json" "github.com/gofiber/fiber/v2" "pkg.world.dev/world-engine/cardinal/server/handler/cql" @@ -15,13 +14,8 @@ type CQLQueryRequest struct { CQL string } -type cqlData struct { - ID types.EntityID `json:"id"` - Data []json.RawMessage `json:"data" swaggertype:"object"` -} - type CQLQueryResponse struct { - Results []cqlData `json:"results"` + Results []types.CqlData `json:"results"` } // PostCQL godoc @@ -35,8 +29,7 @@ type CQLQueryResponse struct { // @Failure 400 {string} string "Invalid request parameters" // @Router /cql [post] func PostCQL( - provider servertypes.ProviderWorld, - wCtx servertypes.ProviderContext) func(*fiber.Ctx) error { //nolint:gocognit // to refactor later + provider servertypes.ProviderWorld) func(*fiber.Ctx) error { //nolint:gocognit // to refactor later return func(ctx *fiber.Ctx) error { req := new(CQLQueryRequest) if err := ctx.BodyParser(req); err != nil { @@ -58,33 +51,7 @@ func PostCQL( if err != nil { return fiber.NewError(fiber.StatusBadRequest, err.Error()) } - - result := make([]cqlData, 0) - var eachError error - searchErr := provider.Search(resultFilter).Each(wCtx, - func(id types.EntityID) bool { - components, err := provider.StoreReader().GetComponentTypesForEntity(id) - if err != nil { - eachError = err - return false - } - resultElement := cqlData{ - ID: id, - Data: make([]json.RawMessage, 0), - } - - for _, c := range components { - data, err := provider.StoreReader().GetComponentForEntityInRawJSON(c, id) - if err != nil { - eachError = err - return false - } - resultElement.Data = append(resultElement.Data, data) - } - result = append(result, resultElement) - return true - }, - ) + result, eachError, searchErr := provider.RunCQLSearch(resultFilter) if searchErr != nil { return fiber.NewError(fiber.StatusInternalServerError, searchErr.Error()) } diff --git a/cardinal/server/handler/debug.go b/cardinal/server/handler/debug.go index 3ced28a7f..78b746b37 100644 --- a/cardinal/server/handler/debug.go +++ b/cardinal/server/handler/debug.go @@ -1,24 +1,11 @@ package handler import ( - "encoding/json" - "github.com/gofiber/fiber/v2" - "pkg.world.dev/world-engine/cardinal/search/filter" servertypes "pkg.world.dev/world-engine/cardinal/server/types" - "pkg.world.dev/world-engine/cardinal/types" ) -type DebugStateRequest struct{} - -type debugStateElement struct { - ID types.EntityID `json:"id"` - Components map[string]json.RawMessage `json:"components" swaggertype:"object"` -} - -type DebugStateResponse []debugStateElement - // GetDebugState godoc // // @Summary Retrieves a list of all entities in the game state @@ -26,41 +13,15 @@ type DebugStateResponse []debugStateElement // @Produce application/json // @Success 200 {object} DebugStateResponse "List of all entities" // @Router /debug/state [post] -func GetDebugState(provider servertypes.ProviderWorld, wCtx servertypes.ProviderContext) func(*fiber.Ctx) error { +func GetDebugState(provider servertypes.ProviderWorld) func(*fiber.Ctx) error { return func(ctx *fiber.Ctx) error { - result := make(DebugStateResponse, 0) - s := provider.Search(filter.All()) - var eachClosureErr error - searchEachErr := s.Each(wCtx, - func(id types.EntityID) bool { - var components []types.ComponentMetadata - components, eachClosureErr = provider.StoreReader().GetComponentTypesForEntity(id) - if eachClosureErr != nil { - return false - } - resultElement := debugStateElement{ - ID: id, - Components: make(map[string]json.RawMessage), - } - for _, c := range components { - var data json.RawMessage - data, eachClosureErr = provider.StoreReader().GetComponentForEntityInRawJSON(c, id) - if eachClosureErr != nil { - return false - } - resultElement.Components[c.Name()] = data - } - result = append(result, resultElement) - return true - }, - ) + result, eachClosureErr, searchEachErr := provider.GetDebugState() if eachClosureErr != nil { return eachClosureErr } if searchEachErr != nil { return searchEachErr } - return ctx.JSON(&result) } } diff --git a/cardinal/server/handler/query.go b/cardinal/server/handler/query.go index fcd28283b..89c2e6a5f 100644 --- a/cardinal/server/handler/query.go +++ b/cardinal/server/handler/query.go @@ -3,8 +3,7 @@ package handler import ( "github.com/gofiber/fiber/v2" - "pkg.world.dev/world-engine/cardinal/server/types" - "pkg.world.dev/world-engine/cardinal/types/engine" + servertypes "pkg.world.dev/world-engine/cardinal/server/types" ) // PostQuery godoc @@ -19,10 +18,10 @@ import ( // @Success 200 {object} object "Results of the executed query" // @Failure 400 {string} string "Invalid request parameters" // @Router /query/{queryGroup}/{queryName} [post] -func PostQuery(queryHandler engine.QueryHandler, wCtx types.ProviderContext) func(*fiber.Ctx) error { +func PostQuery(world servertypes.ProviderWorld) func(*fiber.Ctx) error { return func(ctx *fiber.Ctx) error { ctx.Set("Content-Type", "application/json") - resBz, err := queryHandler(ctx.Params("name"), ctx.Params("group"), ctx.Body()) + resBz, err := world.QueryHandler(ctx.Params("name"), ctx.Params("group"), ctx.Body()) if err != nil { return fiber.NewError(fiber.StatusNotFound, "query not found") } diff --git a/cardinal/server/handler/receipts.go b/cardinal/server/handler/receipts.go index efbe6f59d..206f7521a 100644 --- a/cardinal/server/handler/receipts.go +++ b/cardinal/server/handler/receipts.go @@ -38,15 +38,15 @@ type ReceiptEntry struct { // @Success 200 {object} ListTxReceiptsResponse "List of receipts" // @Failure 400 {string} string "Invalid request body" // @Router /query/receipts/list [post] -func GetReceipts(wCtx types.ProviderContext) func(*fiber.Ctx) error { +func GetReceipts(world types.ProviderWorld) func(*fiber.Ctx) error { return func(ctx *fiber.Ctx) error { req := new(ListTxReceiptsRequest) if err := ctx.BodyParser(req); err != nil { return err } reply := ListTxReceiptsResponse{} - reply.EndTick = wCtx.CurrentTick() - size := wCtx.ReceiptHistorySize() + reply.EndTick = world.CurrentTick() + size := world.ReceiptHistorySize() if size > reply.EndTick { reply.StartTick = 0 } else { @@ -62,7 +62,7 @@ func GetReceipts(wCtx types.ProviderContext) func(*fiber.Ctx) error { } for t := reply.StartTick; t < reply.EndTick; t++ { - currReceipts, err := wCtx.GetTransactionReceiptsForTick(t) + currReceipts, err := world.GetTransactionReceiptsForTick(t) if err != nil || len(currReceipts) == 0 { continue } diff --git a/cardinal/server/handler/world.go b/cardinal/server/handler/world.go index 30aa2f8bd..88e57b698 100644 --- a/cardinal/server/handler/world.go +++ b/cardinal/server/handler/world.go @@ -5,6 +5,7 @@ import ( "github.com/gofiber/fiber/v2" + servertypes "pkg.world.dev/world-engine/cardinal/server/types" "pkg.world.dev/world-engine/cardinal/server/utils" "pkg.world.dev/world-engine/cardinal/types" "pkg.world.dev/world-engine/cardinal/types/engine" @@ -20,8 +21,10 @@ import ( // @Failure 400 {string} string "Invalid request parameters" // @Router /world [get] func GetWorld( - components []types.ComponentMetadata, messages []types.Message, - queryFields []engine.FieldDetail, namespace string, + world servertypes.ProviderWorld, + components []types.ComponentMetadata, + messages []types.Message, + namespace string, ) func(*fiber.Ctx) error { // Collecting name of all registered components comps := make([]engine.FieldDetail, 0, len(components)) @@ -51,7 +54,7 @@ func GetWorld( Namespace: namespace, Components: comps, Messages: messagesFields, - Queries: queryFields, + Queries: world.BuildQueryFields(), }) } } diff --git a/cardinal/server/server.go b/cardinal/server/server.go index a81ff3009..df3fe4f77 100644 --- a/cardinal/server/server.go +++ b/cardinal/server/server.go @@ -15,7 +15,6 @@ import ( "pkg.world.dev/world-engine/cardinal/server/handler" servertypes "pkg.world.dev/world-engine/cardinal/server/types" "pkg.world.dev/world-engine/cardinal/types" - "pkg.world.dev/world-engine/cardinal/types/engine" ) const ( @@ -36,11 +35,8 @@ type Server struct { // New returns an HTTP server with handlers for all QueryTypes and MessageTypes. func New( provider servertypes.ProviderWorld, - wCtx servertypes.ProviderContext, components []types.ComponentMetadata, messages []types.Message, - queryHandler engine.QueryHandler, - queryFields []engine.FieldDetail, opts ...Option, ) (*Server, error) { app := fiber.New(fiber.Config{ @@ -63,7 +59,7 @@ func New( app.Use(cors.New()) // Register routes - s.setupRoutes(provider, wCtx, messages, queryHandler, queryFields, components) + s.setupRoutes(provider, messages, components) return s, nil } @@ -121,10 +117,7 @@ func (s *Server) Shutdown() error { // @produces application/json func (s *Server) setupRoutes( provider servertypes.ProviderWorld, - wCtx servertypes.ProviderContext, messages []types.Message, - queryHandler engine.QueryHandler, - queryFields []engine.FieldDetail, components []types.ComponentMetadata, ) { // /tx/:group/:txType @@ -150,23 +143,23 @@ func (s *Server) setupRoutes( s.app.Get("/events", handler.WebSocketEvents()) // Route: /world - s.app.Get("/world", handler.GetWorld(components, messages, queryFields, wCtx.Namespace())) + s.app.Get("/world", handler.GetWorld(provider, components, messages, provider.Namespace())) // Route: /... s.app.Get("/health", handler.GetHealth()) // Route: /query/... query := s.app.Group("/query") - query.Post("/receipts/list", handler.GetReceipts(wCtx)) - query.Post("/:group/:name", handler.PostQuery(queryHandler, wCtx)) + query.Post("/receipts/list", handler.GetReceipts(provider)) + query.Post("/:group/:name", handler.PostQuery(provider)) // Route: /tx/... tx := s.app.Group("/tx") tx.Post("/:group/:name", handler.PostTransaction(provider, msgIndex, s.config.isSignatureVerificationDisabled)) // Route: /cql - s.app.Post("/cql", handler.PostCQL(provider, wCtx)) + s.app.Post("/cql", handler.PostCQL(provider)) // Route: /debug/state - s.app.Post("/debug/state", handler.GetDebugState(provider, wCtx)) + s.app.Post("/debug/state", handler.GetDebugState(provider)) } diff --git a/cardinal/server/types/provider.go b/cardinal/server/types/provider.go index f161cbb8e..4feaa9b3a 100644 --- a/cardinal/server/types/provider.go +++ b/cardinal/server/types/provider.go @@ -1,16 +1,12 @@ package types import ( - "reflect" - - "github.com/rs/zerolog" - "pkg.world.dev/world-engine/cardinal/gamestate" "pkg.world.dev/world-engine/cardinal/receipt" "pkg.world.dev/world-engine/cardinal/search" "pkg.world.dev/world-engine/cardinal/search/filter" "pkg.world.dev/world-engine/cardinal/types" - "pkg.world.dev/world-engine/cardinal/types/txpool" + "pkg.world.dev/world-engine/cardinal/types/engine" "pkg.world.dev/world-engine/sign" ) @@ -22,36 +18,12 @@ type ProviderWorld interface { GetComponentByName(name string) (types.ComponentMetadata, error) Search(filter filter.ComponentFilter) search.EntitySearch StoreReader() gamestate.Reader - //GetReadOnlyCtx() engine.Context -} - -type ProviderQuery interface { - Name() string - HandleQueryRaw(wCtx ProviderContext, bz []byte) ([]byte, error) - GetRequestFieldInformation() map[string]any - Group() string -} - -type ProviderContext interface { + QueryHandler(name string, group string, bz []byte) ([]byte, error) CurrentTick() uint64 ReceiptHistorySize() uint64 GetTransactionReceiptsForTick(tick uint64) ([]receipt.Receipt, error) - Namespace() string - Timestamp() uint64 - Logger() *zerolog.Logger - EmitEvent(map[string]any) error - EmitStringEvent(string) error - SetLogger(logger zerolog.Logger) - AddMessageError(id types.TxHash, err error) - SetMessageResult(id types.TxHash, a any) - GetComponentByName(name string) (types.ComponentMetadata, error) - GetMessageByType(mType reflect.Type) (types.Message, bool) - GetTransactionReceipt(id types.TxHash) (any, []error, bool) - GetSignerForPersonaTag(personaTag string, tick uint64) (addr string, err error) - AddTransaction(id types.MessageID, v any, sig *sign.Transaction) (uint64, types.TxHash) - IsWorldReady() bool - StoreReader() gamestate.Reader - StoreManager() gamestate.Manager - GetTxPool() *txpool.TxPool - IsReadOnly() bool + RunCQLSearch(filter filter.ComponentFilter) ([]types.CqlData, error, error) + GetDebugState() (types.DebugStateResponse, error, error) + BuildQueryFields() []engine.FieldDetail + //GetReadOnlyCtx() engine.Context } diff --git a/cardinal/types/cql.go b/cardinal/types/cql.go new file mode 100644 index 000000000..db487ff02 --- /dev/null +++ b/cardinal/types/cql.go @@ -0,0 +1,8 @@ +package types + +import "encoding/json" + +type CqlData struct { + ID EntityID `json:"id"` + Data []json.RawMessage `json:"data" swaggertype:"object"` +} diff --git a/cardinal/types/debug.go b/cardinal/types/debug.go new file mode 100644 index 000000000..82bedcbb5 --- /dev/null +++ b/cardinal/types/debug.go @@ -0,0 +1,12 @@ +package types + +import "encoding/json" + +type DebugStateRequest struct{} + +type DebugStateElement struct { + ID EntityID `json:"id"` + Components map[string]json.RawMessage `json:"components" swaggertype:"object"` +} + +type DebugStateResponse []DebugStateElement diff --git a/cardinal/types/engine/context.go b/cardinal/types/engine/context.go index a1879ac17..68beebc4e 100644 --- a/cardinal/types/engine/context.go +++ b/cardinal/types/engine/context.go @@ -18,8 +18,8 @@ package engine // // // For internal use. // -// // SetLogger is used to inject a new logger configuration to an engine context that is already created. -// SetLogger(logger zerolog.Logger) +// // setLogger is used to inject a new logger configuration to an engine context that is already created. +// setLogger(logger zerolog.Logger) // AddMessageError(id types.TxHash, err error) // SetMessageResult(id types.TxHash, a any) // GetComponentByName(name string) (types.ComponentMetadata, error) diff --git a/cardinal/types/engine/mocks/context.go b/cardinal/types/engine/mocks/context.go index c744454ae..b5f7dc115 100644 --- a/cardinal/types/engine/mocks/context.go +++ b/cardinal/types/engine/mocks/context.go @@ -269,15 +269,15 @@ func (mr *MockContextMockRecorder) ReceiptHistorySize() *gomock.Call { } // SetLogger mocks base method. -func (m *MockContext) SetLogger(logger zerolog.Logger) { +func (m *MockContext) setLogger(logger zerolog.Logger) { m.ctrl.T.Helper() - m.ctrl.Call(m, "SetLogger", logger) + m.ctrl.Call(m, "setLogger", logger) } // SetLogger indicates an expected call of SetLogger. func (mr *MockContextMockRecorder) SetLogger(logger interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetLogger", reflect.TypeOf((*MockContext)(nil).SetLogger), logger) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "setLogger", reflect.TypeOf((*MockContext)(nil).setLogger), logger) } // SetMessageResult mocks base method. diff --git a/cardinal/world.go b/cardinal/world.go index 4741f3de5..787308144 100644 --- a/cardinal/world.go +++ b/cardinal/world.go @@ -26,9 +26,11 @@ import ( "pkg.world.dev/world-engine/cardinal/search/filter" "pkg.world.dev/world-engine/cardinal/server" servertypes "pkg.world.dev/world-engine/cardinal/server/types" + "pkg.world.dev/world-engine/cardinal/server/utils" "pkg.world.dev/world-engine/cardinal/statsd" "pkg.world.dev/world-engine/cardinal/storage/redis" "pkg.world.dev/world-engine/cardinal/types" + "pkg.world.dev/world-engine/cardinal/types/engine" "pkg.world.dev/world-engine/cardinal/types/txpool" "pkg.world.dev/world-engine/cardinal/worldstage" "pkg.world.dev/world-engine/sign" @@ -110,7 +112,6 @@ func NewWorld(opts ...WorldOption) (*World, error) { } tick := new(atomic.Uint64) - world := &World{ namespace: Namespace(cfg.CardinalNamespace), rollupEnabled: cfg.CardinalRollupEnabled, @@ -181,7 +182,7 @@ func NewWorld(opts ...WorldOption) (*World, error) { ) } } - + world.QueryManager.BuildQueryIndex(world) return world, nil } @@ -329,15 +330,10 @@ func (w *World) StartGame() error { // receiptHistory tick separately. w.receiptHistory.SetTick(w.CurrentTick()) - queryHandler := BuildUniversalQueryHandler(w) - queryFields := BuildQueryFields(w) - // Create server // We can't do this is in NewWorld() because the server needs to know the registered messages // and register queries first. We can probably refactor this though. - w.server, err = server.New(w, - NewReadOnlyWorldContext(w), w.GetRegisteredComponents(), w.GetRegisteredMessages(), - queryHandler, queryFields, w.serverOptions...) + w.server, err = server.New(w, w.GetRegisteredComponents(), w.GetRegisteredMessages(), w.serverOptions...) if err != nil { return err } @@ -384,6 +380,21 @@ func (w *World) startServer() { }() } +func (w *World) BuildQueryFields() []engine.FieldDetail { + // Collecting the structure of all queries + queries := w.GetRegisteredQueries() + queriesFields := make([]engine.FieldDetail, 0, len(queries)) + for _, query := range queries { + // Extracting the fields of the query + queriesFields = append(queriesFields, engine.FieldDetail{ + Name: query.Name(), + Fields: query.GetRequestFieldInformation(), + URL: utils.GetQueryURL(query.Group(), query.Name()), + }) + } + return queriesFields +} + func (w *World) startGameLoop(ctx context.Context, tickStart <-chan time.Time, tickDone chan<- uint64) { log.Info().Msg("Game loop started") go func() { @@ -555,6 +566,37 @@ func (w *World) UseNonce(signerAddress string, nonce uint64) error { return w.redisStorage.UseNonce(signerAddress, nonce) } +func (w *World) GetDebugState() (types.DebugStateResponse, error, error) { + result := make(types.DebugStateResponse, 0) + s := w.Search(filter.All()) + var eachClosureErr error + wCtx := NewReadOnlyWorldContext(w) + searchEachErr := s.Each(wCtx, + func(id types.EntityID) bool { + var components []types.ComponentMetadata + components, eachClosureErr = w.StoreReader().GetComponentTypesForEntity(id) + if eachClosureErr != nil { + return false + } + resultElement := types.DebugStateElement{ + ID: id, + Components: make(map[string]json.RawMessage), + } + for _, c := range components { + var data json.RawMessage + data, eachClosureErr = w.StoreReader().GetComponentForEntityInRawJSON(c, id) + if eachClosureErr != nil { + return false + } + resultElement.Components[c.Name()] = data + } + result = append(result, resultElement) + return true + }, + ) + return result, eachClosureErr, searchEachErr +} + func (w *World) Namespace() string { return string(w.namespace) } @@ -630,3 +672,38 @@ func (w *World) populateAndBroadcastTickResults() { log.Err(err).Msgf("failed to broadcast tick results") } } + +func (w *World) ReceiptHistorySize() uint64 { + return w.receiptHistory.Size() +} + +func (w *World) RunCQLSearch(filter filter.ComponentFilter) ([]types.CqlData, error, error) { + result := make([]types.CqlData, 0) + var eachError error + wCtx := NewReadOnlyWorldContext(w) + searchErr := w.Search(filter).Each(wCtx, + func(id types.EntityID) bool { + components, err := w.StoreReader().GetComponentTypesForEntity(id) + if err != nil { + eachError = err + return false + } + resultElement := types.CqlData{ + ID: id, + Data: make([]json.RawMessage, 0), + } + + for _, c := range components { + data, err := w.StoreReader().GetComponentForEntityInRawJSON(c, id) + if err != nil { + eachError = err + return false + } + resultElement.Data = append(resultElement.Data, data) + } + result = append(result, resultElement) + return true + }, + ) + return result, eachError, searchErr +} From 41ab055aea3eb956c0c4fe17131a5e20e5ae8fe8 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Thu, 9 May 2024 17:50:33 -0700 Subject: [PATCH 14/76] fixed the linter. --- cardinal/query.go | 8 ++++---- cardinal/server/handler/cql.go | 2 +- cardinal/server/handler/query.go | 4 ---- cardinal/server/server.go | 3 ++- cardinal/server/types/provider.go | 1 - cardinal/world_context.go | 6 +++--- e2e/testgames/game/query/location.go | 2 +- e2e/testgames/game/sys/error.go | 2 +- e2e/testgames/game/sys/join.go | 2 +- e2e/testgames/game/sys/move.go | 2 +- e2e/testgames/gamebenchmark/sys/sys.go | 8 ++++---- 11 files changed, 18 insertions(+), 22 deletions(-) diff --git a/cardinal/query.go b/cardinal/query.go index 41ab5aa68..9aa44598c 100644 --- a/cardinal/query.go +++ b/cardinal/query.go @@ -11,6 +11,10 @@ import ( "pkg.world.dev/world-engine/cardinal/types" ) +var _ Query = &queryType[struct{}, struct{}]{} + +type QueryHandler = func(name string, group string, bz []byte) ([]byte, error) + type Query interface { // Name returns the name of the query. Name() string @@ -35,8 +39,6 @@ type Query interface { GetRequestFieldInformation() map[string]any } -var _ Query = &queryType[struct{}, struct{}]{} - type QueryOption[Request, Reply any] func(qt *queryType[Request, Reply]) type queryType[Request any, Reply any] struct { @@ -265,5 +267,3 @@ func validateQuery[Request any, Reply any]( } return nil } - -type QueryHandler = func(name string, group string, bz []byte) ([]byte, error) diff --git a/cardinal/server/handler/cql.go b/cardinal/server/handler/cql.go index c1df0905d..1e0e71bb1 100644 --- a/cardinal/server/handler/cql.go +++ b/cardinal/server/handler/cql.go @@ -29,7 +29,7 @@ type CQLQueryResponse struct { // @Failure 400 {string} string "Invalid request parameters" // @Router /cql [post] func PostCQL( - provider servertypes.ProviderWorld) func(*fiber.Ctx) error { //nolint:gocognit // to refactor later + provider servertypes.ProviderWorld) func(*fiber.Ctx) error { return func(ctx *fiber.Ctx) error { req := new(CQLQueryRequest) if err := ctx.BodyParser(req); err != nil { diff --git a/cardinal/server/handler/query.go b/cardinal/server/handler/query.go index 89c2e6a5f..6c61cf414 100644 --- a/cardinal/server/handler/query.go +++ b/cardinal/server/handler/query.go @@ -25,10 +25,6 @@ func PostQuery(world servertypes.ProviderWorld) func(*fiber.Ctx) error { if err != nil { return fiber.NewError(fiber.StatusNotFound, "query not found") } - if err != nil { - return fiber.NewError(fiber.StatusBadRequest, "encountered an error in query: "+err.Error()) - } - return ctx.Send(resBz) } } diff --git a/cardinal/server/server.go b/cardinal/server/server.go index df3fe4f77..7e9083e84 100644 --- a/cardinal/server/server.go +++ b/cardinal/server/server.go @@ -11,10 +11,11 @@ import ( "github.com/rotisserie/eris" "github.com/rs/zerolog/log" - _ "pkg.world.dev/world-engine/cardinal/server/docs" // for swagger. "pkg.world.dev/world-engine/cardinal/server/handler" servertypes "pkg.world.dev/world-engine/cardinal/server/types" "pkg.world.dev/world-engine/cardinal/types" + + _ "pkg.world.dev/world-engine/cardinal/server/docs" // for swagger. ) const ( diff --git a/cardinal/server/types/provider.go b/cardinal/server/types/provider.go index 4feaa9b3a..24d230e13 100644 --- a/cardinal/server/types/provider.go +++ b/cardinal/server/types/provider.go @@ -25,5 +25,4 @@ type ProviderWorld interface { RunCQLSearch(filter filter.ComponentFilter) ([]types.CqlData, error, error) GetDebugState() (types.DebugStateResponse, error, error) BuildQueryFields() []engine.FieldDetail - //GetReadOnlyCtx() engine.Context } diff --git a/cardinal/world_context.go b/cardinal/world_context.go index 82afe62b7..96b585c7b 100644 --- a/cardinal/world_context.go +++ b/cardinal/world_context.go @@ -14,6 +14,9 @@ import ( "pkg.world.dev/world-engine/sign" ) +// interface guard +var _ Context = (*worldContext)(nil) + //go:generate mockgen -source=context.go -package mocks -destination=mocks/context.go type Context interface { // Timestamp returns the UNIX timestamp of the tick. @@ -50,9 +53,6 @@ type Context interface { IsReadOnly() bool } -// interface guard -var _ Context = (*worldContext)(nil) - type worldContext struct { world *World txPool *txpool.TxPool diff --git a/e2e/testgames/game/query/location.go b/e2e/testgames/game/query/location.go index f1d4bbec4..8b1ba4706 100644 --- a/e2e/testgames/game/query/location.go +++ b/e2e/testgames/game/query/location.go @@ -21,7 +21,7 @@ func RegisterLocationQuery(world *cardinal.World) error { return cardinal.RegisterQuery[LocationRequest, LocationReply]( world, "location", - func(ctx cardinal.WorldContext, req *LocationRequest) (*LocationReply, error) { + func(ctx cardinal.Context, req *LocationRequest) (*LocationReply, error) { playerEntityID, ok := sys.PlayerEntityID[req.ID] if !ok { ctx.Logger().Info().Msg("listing existing players...") diff --git a/e2e/testgames/game/sys/error.go b/e2e/testgames/game/sys/error.go index 20d74b6fa..1034f574a 100644 --- a/e2e/testgames/game/sys/error.go +++ b/e2e/testgames/game/sys/error.go @@ -10,7 +10,7 @@ import ( // Error is a system that will produce an error for any incoming Error messages. It's // used to test receipt errors. -func Error(ctx cardinal.WorldContext) error { +func Error(ctx cardinal.Context) error { return cardinal.EachMessage[msg.ErrorInput, msg.ErrorOutput]( ctx, func(m cardinal.TxData[msg.ErrorInput]) (msg.ErrorOutput, error) { err := errors.New(m.Msg.ErrorMsg) diff --git a/e2e/testgames/game/sys/join.go b/e2e/testgames/game/sys/join.go index 6bddbdc29..d24eb2c07 100644 --- a/e2e/testgames/game/sys/join.go +++ b/e2e/testgames/game/sys/join.go @@ -12,7 +12,7 @@ import ( var PlayerEntityID = make(map[string]types.EntityID) -func Join(ctx cardinal.WorldContext) error { +func Join(ctx cardinal.Context) error { logger := ctx.Logger() return cardinal.EachMessage[msg.JoinInput, msg.JoinOutput]( ctx, func(jtx cardinal.TxData[msg.JoinInput]) (msg.JoinOutput, error) { diff --git a/e2e/testgames/game/sys/move.go b/e2e/testgames/game/sys/move.go index 7fd096ebc..10523b5d8 100644 --- a/e2e/testgames/game/sys/move.go +++ b/e2e/testgames/game/sys/move.go @@ -9,7 +9,7 @@ import ( "pkg.world.dev/world-engine/cardinal" ) -func Move(ctx cardinal.WorldContext) error { +func Move(ctx cardinal.Context) error { logger := ctx.Logger() return cardinal.EachMessage[msg.MoveInput, msg.MoveOutput](ctx, func(mtx cardinal.TxData[msg.MoveInput]) (msg.MoveOutput, error) { diff --git a/e2e/testgames/gamebenchmark/sys/sys.go b/e2e/testgames/gamebenchmark/sys/sys.go index be0d8471b..1d09f88d1 100644 --- a/e2e/testgames/gamebenchmark/sys/sys.go +++ b/e2e/testgames/gamebenchmark/sys/sys.go @@ -13,7 +13,7 @@ var ( TreeEntityIDs []types.EntityID ) -func InitTenThousandEntities(wCtx cardinal.WorldContext) error { +func InitTenThousandEntities(wCtx cardinal.Context) error { var err error entityAmount := 10000 TenThousandEntityIDs, err = cardinal.CreateMany(wCtx, entityAmount, &comp.SingleNumber{Number: 1}) @@ -23,7 +23,7 @@ func InitTenThousandEntities(wCtx cardinal.WorldContext) error { return nil } -func InitOneHundredEntities(wCtx cardinal.WorldContext) error { +func InitOneHundredEntities(wCtx cardinal.Context) error { var err error entityAmount := 100 OneHundredEntityIDs, err = cardinal.CreateMany(wCtx, entityAmount, &comp.ArrayComp{Numbers: [10000]int{}}) @@ -33,7 +33,7 @@ func InitOneHundredEntities(wCtx cardinal.WorldContext) error { return nil } -func InitTreeEntities(wCtx cardinal.WorldContext) error { +func InitTreeEntities(wCtx cardinal.Context) error { var err error var entityAmount = 100 var treeDepth = 10 @@ -48,7 +48,7 @@ func InitTreeEntities(wCtx cardinal.WorldContext) error { return nil } -func SystemBenchmark(wCtx cardinal.WorldContext) error { +func SystemBenchmark(wCtx cardinal.Context) error { for _, id := range TreeEntityIDs { gotcomp, err := cardinal.GetComponent[comp.Tree](wCtx, id) if err != nil { From 630b20a5d166a6459369306996422c55e1bc45de Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Thu, 9 May 2024 18:40:22 -0700 Subject: [PATCH 15/76] moved search into cardinal. --- cardinal/cardinal.go | 26 +---------- cardinal/{search => }/composedsearch.go | 2 +- cardinal/ecs_test.go | 9 ++-- cardinal/{search => }/filtercomponent.go | 10 ++--- cardinal/plugin_persona.go | 3 +- cardinal/{search => }/search.go | 55 +++++++++++++++--------- cardinal/search/context.go | 49 --------------------- cardinal/search/searchcomponent.go | 9 ---- cardinal/search/util.go | 31 ------------- cardinal/search_test.go | 43 +++++++++--------- cardinal/server/types/provider.go | 3 +- cardinal/types/search.go | 3 ++ cardinal/world.go | 5 +-- cardinal/world_persona.go | 5 +-- cardinal/world_persona_test.go | 3 +- 15 files changed, 78 insertions(+), 178 deletions(-) rename cardinal/{search => }/composedsearch.go (99%) rename cardinal/{search => }/filtercomponent.go (87%) rename cardinal/{search => }/search.go (93%) delete mode 100644 cardinal/search/context.go delete mode 100644 cardinal/search/searchcomponent.go delete mode 100644 cardinal/search/util.go create mode 100644 cardinal/types/search.go diff --git a/cardinal/cardinal.go b/cardinal/cardinal.go index 278345476..6eb7a1e2b 100644 --- a/cardinal/cardinal.go +++ b/cardinal/cardinal.go @@ -9,7 +9,6 @@ import ( "pkg.world.dev/world-engine/cardinal/component" "pkg.world.dev/world-engine/cardinal/iterators" - "pkg.world.dev/world-engine/cardinal/search" "pkg.world.dev/world-engine/cardinal/types" "pkg.world.dev/world-engine/cardinal/worldstage" ) @@ -23,27 +22,6 @@ var ( ErrComponentAlreadyOnEntity = iterators.ErrComponentAlreadyOnEntity ) -// Imported -// This section aggregates function from other packages such that they are easily accessible -// via cardinal. - -// NewSearch is used to create a search object. -// -// Usage: -// -// cardinal.NewSearch().Entity(filter.Contains(filter.Component[EnergyComponent]())) -var NewSearch = search.NewSearch - -// NewLegacySearch allows users to create a Search object with a filter already provided -// as a property. -// -// Example Usage: -// -// cardinal.NewLegacySearch().Entity(filter.Exact(Alpha{}, Beta{})).Count() -var NewLegacySearch = search.NewLegacySearch - -type Search = search.Search - // FilterFunction wrap your component filter function of func(comp T) bool inside FilterFunction to use // in search. // @@ -54,8 +32,8 @@ type Search = search.Search // return true // })) -func FilterFunction[T types.Component](f func(comp T) bool) func(ctx search.Context, id types.EntityID) (bool, error) { - return search.ComponentFilter[T](f) +func FilterFunction[T types.Component](f func(comp T) bool) func(ctx Context, id types.EntityID) (bool, error) { + return ComponentFilter[T](f) } func RegisterSystems(w *World, sys ...System) error { diff --git a/cardinal/search/composedsearch.go b/cardinal/composedsearch.go similarity index 99% rename from cardinal/search/composedsearch.go rename to cardinal/composedsearch.go index 5e2c6716e..c95410379 100644 --- a/cardinal/search/composedsearch.go +++ b/cardinal/composedsearch.go @@ -1,4 +1,4 @@ -package search +package cardinal import ( "github.com/rotisserie/eris" diff --git a/cardinal/ecs_test.go b/cardinal/ecs_test.go index 232b79ad6..f50117d63 100644 --- a/cardinal/ecs_test.go +++ b/cardinal/ecs_test.go @@ -7,7 +7,6 @@ import ( "pkg.world.dev/world-engine/assert" "pkg.world.dev/world-engine/cardinal" "pkg.world.dev/world-engine/cardinal/iterators" - "pkg.world.dev/world-engine/cardinal/search" "pkg.world.dev/world-engine/cardinal/search/filter" "pkg.world.dev/world-engine/cardinal/testutils" "pkg.world.dev/world-engine/cardinal/types" @@ -133,8 +132,8 @@ func TestECS(t *testing.T) { ) assert.NilError(t, err) - q := search.Or(cardinal.NewSearch().Entity( - filter.Contains(filter.Component[EnergyComponent]())), search.NewSearch().Entity( + q := cardinal.Or(cardinal.NewSearch().Entity( + filter.Contains(filter.Component[EnergyComponent]())), cardinal.NewSearch().Entity( filter.Contains(filter.Component[OwnableComponent]()))) amt, err := q.Count(wCtx) assert.NilError(t, err) @@ -585,9 +584,9 @@ func TestQueriesAndFiltersWorks(t *testing.T) { assert.NilError(t, err) assert.Equal(t, num, 1) - searchable := search.Or(cardinal.NewSearch().Entity( + searchable := cardinal.Or(cardinal.NewSearch().Entity( filter.Contains(filter.Component[A]())), - search.NewSearch().Entity(filter.Contains(filter.Component[D]()))) + cardinal.NewSearch().Entity(filter.Contains(filter.Component[D]()))) allCount, err := searchable.Count(wCtx) assert.NilError(t, err) assert.Equal(t, allCount, 3) diff --git a/cardinal/search/filtercomponent.go b/cardinal/filtercomponent.go similarity index 87% rename from cardinal/search/filtercomponent.go rename to cardinal/filtercomponent.go index 74fac9419..4b9917b38 100644 --- a/cardinal/search/filtercomponent.go +++ b/cardinal/filtercomponent.go @@ -1,4 +1,4 @@ -package search +package cardinal import ( "github.com/rotisserie/eris" @@ -10,10 +10,10 @@ import ( // It involves creating and combining primitives that represent // filtering properties on components. -type filterFn func(wCtx Context, id types.EntityID) (bool, error) +type FilterFn func(wCtx Context, id types.EntityID) (bool, error) //revive:disable-next-line:unexported-return -func ComponentFilter[T types.Component](f func(comp T) bool) filterFn { +func ComponentFilter[T types.Component](f func(comp T) bool) FilterFn { return func(wCtx Context, id types.EntityID) (bool, error) { var t T c, err := wCtx.GetComponentByName(t.Name()) @@ -42,7 +42,7 @@ func ComponentFilter[T types.Component](f func(comp T) bool) filterFn { } //revive:disable-next-line:unexported-return -func AndFilter(fns ...filterFn) filterFn { +func AndFilter(fns ...FilterFn) FilterFn { return func(wCtx Context, id types.EntityID) (bool, error) { var result = true var errCount = 0 @@ -62,7 +62,7 @@ func AndFilter(fns ...filterFn) filterFn { } //revive:disable-next-line:unexported-return -func OrFilter(fns ...filterFn) filterFn { +func OrFilter(fns ...FilterFn) FilterFn { return func(wCtx Context, id types.EntityID) (bool, error) { var result = false var errCount = 0 diff --git a/cardinal/plugin_persona.go b/cardinal/plugin_persona.go index 6b8765444..48e884556 100644 --- a/cardinal/plugin_persona.go +++ b/cardinal/plugin_persona.go @@ -10,7 +10,6 @@ import ( "pkg.world.dev/world-engine/cardinal/persona" "pkg.world.dev/world-engine/cardinal/persona/component" "pkg.world.dev/world-engine/cardinal/persona/msg" - "pkg.world.dev/world-engine/cardinal/search" "pkg.world.dev/world-engine/cardinal/search/filter" "pkg.world.dev/world-engine/cardinal/types" ) @@ -226,7 +225,7 @@ func buildGlobalPersonaIndex(wCtx Context) error { tickOfPersonaTagToAddressIndex = wCtx.CurrentTick() globalPersonaTagToAddressIndex = map[string]personaIndexEntry{} var errs []error - s := search.NewSearch().Entity(filter.Exact(filter.Component[component.SignerComponent]())) + s := NewSearch().Entity(filter.Exact(filter.Component[component.SignerComponent]())) err := s.Each(wCtx, func(id types.EntityID) bool { sc, err := GetComponent[component.SignerComponent](wCtx, id) diff --git a/cardinal/search/search.go b/cardinal/search.go similarity index 93% rename from cardinal/search/search.go rename to cardinal/search.go index 1914a74e9..4b040cff5 100644 --- a/cardinal/search/search.go +++ b/cardinal/search.go @@ -1,4 +1,4 @@ -package search +package cardinal import ( "slices" @@ -10,8 +10,6 @@ import ( "pkg.world.dev/world-engine/cardinal/types" ) -type CallbackFn func(types.EntityID) bool - type cache struct { archetypes []types.ArchetypeID seen int @@ -26,7 +24,7 @@ type cache struct { type Search struct { archMatches *cache filter filter.ComponentFilter - componentPropertyFilter filterFn + componentPropertyFilter FilterFn } // interfaces restrict order of operations. @@ -86,27 +84,27 @@ type searchBuilder interface { } //revive:disable-next-line -type EntitySearch interface { - Searchable - Where(componentFilter filterFn) EntitySearch -} -type Searchable interface { - evaluateSearch(eCtx Context) []types.ArchetypeID - Each(eCtx Context, callback CallbackFn) error - First(eCtx Context) (types.EntityID, error) - MustFirst(eCtx Context) types.EntityID - Count(eCtx Context) (int, error) - Collect(eCtx Context) ([]types.EntityID, error) -} +// Imported +// This section aggregates function from other packages such that they are easily accessible +// via cardinal. -// NewSearch creates a new search. -// It receives arbitrary filters that are used to filter entities. +// NewSearch is used to create a search object. +// +// Usage: +// +// cardinal.NewSearch().Entity(filter.Contains(filter.Component[EnergyComponent]())) func NewSearch() searchBuilder { return NewLegacySearch(nil).(searchBuilder) } // TODO: should deprecate this in the future. +// NewLegacySearch allows users to create a Search object with a filter already provided +// as a property. +// +// Example Usage: +// +// cardinal.NewLegacySearch().Entity(filter.Exact(Alpha{}, Beta{})).Count() func NewLegacySearch(componentFilter filter.ComponentFilter) EntitySearch { return &Search{ archMatches: &cache{}, @@ -122,8 +120,8 @@ func (s *Search) Entity(componentFilter filter.ComponentFilter) EntitySearch { // Once the where clause method is activated the search will ONLY return results // if a where clause returns true and no error. -func (s *Search) Where(componentFilter filterFn) EntitySearch { - var componentPropertyFilter filterFn +func (s *Search) Where(componentFilter FilterFn) EntitySearch { + var componentPropertyFilter FilterFn if s.componentPropertyFilter != nil { componentPropertyFilter = AndFilter(s.componentPropertyFilter, componentFilter) } else { @@ -264,3 +262,20 @@ func (s *Search) evaluateSearch(eCtx Context) []types.ArchetypeID { cache.seen = eCtx.StoreReader().ArchetypeCount() return cache.archetypes } + +//revive:disable-next-line +type EntitySearch interface { + Searchable + Where(componentFilter FilterFn) EntitySearch +} + +type Searchable interface { + evaluateSearch(eCtx Context) []types.ArchetypeID + Each(eCtx Context, callback CallbackFn) error + First(eCtx Context) (types.EntityID, error) + MustFirst(eCtx Context) types.EntityID + Count(eCtx Context) (int, error) + Collect(eCtx Context) ([]types.EntityID, error) +} + +type CallbackFn func(types.EntityID) bool diff --git a/cardinal/search/context.go b/cardinal/search/context.go deleted file mode 100644 index d89fa7f29..000000000 --- a/cardinal/search/context.go +++ /dev/null @@ -1,49 +0,0 @@ -package search - -import ( - "reflect" - - "github.com/rs/zerolog" - - "pkg.world.dev/world-engine/cardinal/gamestate" - "pkg.world.dev/world-engine/cardinal/receipt" - "pkg.world.dev/world-engine/cardinal/types" - "pkg.world.dev/world-engine/cardinal/types/txpool" - "pkg.world.dev/world-engine/sign" -) - -//go:generate mockgen -source=context.go -package mocks -destination=mocks/context.go -type Context interface { - // Timestamp returns the UNIX timestamp of the tick. - Timestamp() uint64 - // CurrentTick returns the current tick. - CurrentTick() uint64 - // Logger returns the logger that can be used to log messages from within system or query. - Logger() *zerolog.Logger - // EmitEvent emits an event that will be broadcast to all websocket subscribers. - EmitEvent(map[string]any) error - // EmitStringEvent emits a string event that will be broadcast to all websocket subscribers. - // This method is provided for backwards compatability. EmitEvent should be used for most cases. - EmitStringEvent(string) error - // Namespace returns the namespace of the world. - Namespace() string - - // For internal use. - - // SetLogger is used to inject a new logger configuration to an engine context that is already created. - SetLogger(logger zerolog.Logger) - AddMessageError(id types.TxHash, err error) - SetMessageResult(id types.TxHash, a any) - GetComponentByName(name string) (types.ComponentMetadata, error) - GetMessageByType(mType reflect.Type) (types.Message, bool) - GetTransactionReceipt(id types.TxHash) (any, []error, bool) - GetSignerForPersonaTag(personaTag string, tick uint64) (addr string, err error) - GetTransactionReceiptsForTick(tick uint64) ([]receipt.Receipt, error) - ReceiptHistorySize() uint64 - AddTransaction(id types.MessageID, v any, sig *sign.Transaction) (uint64, types.TxHash) - IsWorldReady() bool - StoreReader() gamestate.Reader - StoreManager() gamestate.Manager - GetTxPool() *txpool.TxPool - IsReadOnly() bool -} diff --git a/cardinal/search/searchcomponent.go b/cardinal/search/searchcomponent.go deleted file mode 100644 index 5e5e8eb6e..000000000 --- a/cardinal/search/searchcomponent.go +++ /dev/null @@ -1,9 +0,0 @@ -package search - -// This file represents primitives for search -// The primitive wraps the component and is used in search -// the purpose of the wrapper is to prevent the user from ever -// instantiating the component. These wrappers are used to check if entities -// contain the specified component during the search. - -//revive:disable-next-line:unexported-return diff --git a/cardinal/search/util.go b/cardinal/search/util.go deleted file mode 100644 index 5d07827cc..000000000 --- a/cardinal/search/util.go +++ /dev/null @@ -1,31 +0,0 @@ -package search - -import ( - "github.com/rotisserie/eris" - - "pkg.world.dev/world-engine/cardinal/iterators" -) - -var NonFatalError = []error{ - iterators.ErrEntityDoesNotExist, - iterators.ErrComponentNotOnEntity, - iterators.ErrComponentAlreadyOnEntity, - iterators.ErrEntityMustHaveAtLeastOneComponent, -} - -// panicOnFatalError is a helper function to panic on non-deterministic errors (i.e. Redis error). -func panicOnFatalError(wCtx Context, err error) { - if err != nil && !wCtx.IsReadOnly() && isFatalError(err) { - wCtx.Logger().Panic().Err(err).Msgf("fatal error: %v", eris.ToString(err, true)) - panic(err) - } -} - -func isFatalError(err error) bool { - for _, e := range NonFatalError { - if eris.Is(err, e) { - return false - } - } - return true -} diff --git a/cardinal/search_test.go b/cardinal/search_test.go index 0838126e7..3ab247303 100644 --- a/cardinal/search_test.go +++ b/cardinal/search_test.go @@ -5,7 +5,6 @@ import ( "pkg.world.dev/world-engine/assert" "pkg.world.dev/world-engine/cardinal" - "pkg.world.dev/world-engine/cardinal/search" "pkg.world.dev/world-engine/cardinal/search/filter" "pkg.world.dev/world-engine/cardinal/testutils" "pkg.world.dev/world-engine/cardinal/types" @@ -89,7 +88,7 @@ func TestSearchUsingAllMethods(t *testing.T) { filter.Contains(filter.Component[AlphaTest]()), filter.Contains(filter.Component[BetaTest]()), filter.Contains(filter.Component[GammaTest]())), - )).Where(func(_ search.Context, _ types.EntityID) (bool, error) { + )).Where(func(_ cardinal.Context, _ types.EntityID) (bool, error) { return true, nil }).Count(worldCtx) assert.NilError(t, err) @@ -98,7 +97,7 @@ func TestSearchUsingAllMethods(t *testing.T) { filter.Contains(filter.Component[AlphaTest]()), filter.Contains(filter.Component[BetaTest]()), filter.Contains(filter.Component[GammaTest]())), - )).Where(func(wCtx search.Context, id types.EntityID) (bool, error) { + )).Where(func(wCtx cardinal.Context, id types.EntityID) (bool, error) { c, err := cardinal.GetComponent[HP](wCtx, id) if err != nil { return false, err @@ -153,23 +152,23 @@ func TestSetOperationsOnSearch(t *testing.T) { filter.Component[AlphaTest]())) tests := []struct { - search search.Searchable + search cardinal.Searchable count int }{ { - search: search.And(q1, q2), + search: cardinal.And(q1, q2), count: 0, }, { - search: search.Or(q1, q2), + search: cardinal.Or(q1, q2), count: 20, }, { - search: search.Not(search.Or(q1, q2, q3)), + search: cardinal.Not(cardinal.Or(q1, q2, q3)), count: 10, }, { - search: search.Not(search.And(q1, q2, q3)), + search: cardinal.Not(cardinal.And(q1, q2, q3)), count: 40, }, { - search: search.Not(q4), + search: cardinal.Not(q4), count: 20, }, } @@ -217,7 +216,7 @@ func TestSearch_Integration(t *testing.T) { testCases := []struct { name string - search search.Searchable + search cardinal.Searchable want int }{ { @@ -240,13 +239,13 @@ func TestSearch_Integration(t *testing.T) { }, { "beta or gamma", - search.Or(cardinal.NewSearch().Entity(filter.Exact(filter.Component[BetaTest]())), + cardinal.Or(cardinal.NewSearch().Entity(filter.Exact(filter.Component[BetaTest]())), cardinal.NewSearch().Entity(filter.Exact(filter.Component[GammaTest]()))), 20, }, { "not alpha", - search.Not(cardinal.NewSearch().Entity(filter.Exact(filter.Component[AlphaTest]()))), + cardinal.Not(cardinal.NewSearch().Entity(filter.Exact(filter.Component[AlphaTest]()))), 61, }, { @@ -333,7 +332,7 @@ func TestSearch_Exact_ReturnsExactComponentMatch(t *testing.T) { _, err = cardinal.CreateMany(worldCtx, 10, AlphaTest{}, BetaTest{}, GammaTest{}) assert.NilError(t, err) - amt, err := search.NewSearch().Entity(filter.Exact(filter.Component[BetaTest]())).Count(worldCtx) + amt, err := cardinal.NewSearch().Entity(filter.Exact(filter.Component[BetaTest]())).Count(worldCtx) assert.NilError(t, err) assert.Equal(t, amt, 12) } @@ -366,7 +365,7 @@ func TestSearch_Contains_ReturnsEntityThatContainsComponents(t *testing.T) { _, err = cardinal.CreateMany(worldCtx, 10, AlphaTest{}, BetaTest{}, GammaTest{}) assert.NilError(t, err) - amt, err := search.NewSearch().Entity(filter.Contains(filter.Component[BetaTest]())).Count(worldCtx) + amt, err := cardinal.NewSearch().Entity(filter.Contains(filter.Component[BetaTest]())).Count(worldCtx) assert.NilError(t, err) assert.Equal(t, amt, 42) } @@ -399,7 +398,7 @@ func TestSearch_ComponentNotRegistered_ReturnsZeroEntityWithNoError(t *testing.T _, err = cardinal.CreateMany(worldCtx, 10, AlphaTest{}, BetaTest{}, GammaTest{}) assert.NilError(t, err) - amt, err := search.NewSearch().Entity(filter.Contains(filter.Component[HP]())).Count(worldCtx) + amt, err := cardinal.NewSearch().Entity(filter.Contains(filter.Component[HP]())).Count(worldCtx) assert.NilError(t, err) assert.Equal(t, amt, 0) } @@ -432,23 +431,23 @@ func TestUnregisteredComponentOnSetOperators(t *testing.T) { _, err = cardinal.CreateMany(worldCtx, 10, AlphaTest{}, BetaTest{}, GammaTest{}) assert.NilError(t, err) - q1 := search.NewSearch().Entity(filter.Contains(filter.Component[HP]())) - q2 := search.NewSearch().Entity(filter.Contains(filter.Component[AlphaTest]())) + q1 := cardinal.NewSearch().Entity(filter.Contains(filter.Component[HP]())) + q2 := cardinal.NewSearch().Entity(filter.Contains(filter.Component[AlphaTest]())) tests := []struct { - search search.Searchable + search cardinal.Searchable count int }{ { - search: search.And(q1, q2), + search: cardinal.And(q1, q2), count: 0, }, { - search: search.Or(q1, q2), + search: cardinal.Or(q1, q2), count: 40, }, { - search: search.Not(q1), + search: cardinal.Not(q1), count: 72, }, } @@ -486,7 +485,7 @@ func TestWhereClauseOnSearch(t *testing.T) { _, err = cardinal.CreateMany(worldCtx, 10, AlphaTest{}, BetaTest{}, GammaTest{}) assert.NilError(t, err) - q1 := cardinal.NewSearch().Entity(filter.All()).Where(func(wCtx search.Context, id types.EntityID) (bool, error) { + q1 := cardinal.NewSearch().Entity(filter.All()).Where(func(wCtx cardinal.Context, id types.EntityID) (bool, error) { _, err := cardinal.GetComponent[AlphaTest](wCtx, id) if err != nil { return false, err diff --git a/cardinal/server/types/provider.go b/cardinal/server/types/provider.go index 24d230e13..da96e8a09 100644 --- a/cardinal/server/types/provider.go +++ b/cardinal/server/types/provider.go @@ -3,7 +3,6 @@ package types import ( "pkg.world.dev/world-engine/cardinal/gamestate" "pkg.world.dev/world-engine/cardinal/receipt" - "pkg.world.dev/world-engine/cardinal/search" "pkg.world.dev/world-engine/cardinal/search/filter" "pkg.world.dev/world-engine/cardinal/types" "pkg.world.dev/world-engine/cardinal/types/engine" @@ -16,7 +15,7 @@ type ProviderWorld interface { AddTransaction(id types.MessageID, v any, sig *sign.Transaction) (uint64, types.TxHash) Namespace() string GetComponentByName(name string) (types.ComponentMetadata, error) - Search(filter filter.ComponentFilter) search.EntitySearch + //Search(filter filter.ComponentFilter) cardinal.EntitySearch StoreReader() gamestate.Reader QueryHandler(name string, group string, bz []byte) ([]byte, error) CurrentTick() uint64 diff --git a/cardinal/types/search.go b/cardinal/types/search.go new file mode 100644 index 000000000..30b3615cd --- /dev/null +++ b/cardinal/types/search.go @@ -0,0 +1,3 @@ +package types + +//revive:disable-next-line diff --git a/cardinal/world.go b/cardinal/world.go index 787308144..684697040 100644 --- a/cardinal/world.go +++ b/cardinal/world.go @@ -22,7 +22,6 @@ import ( ecslog "pkg.world.dev/world-engine/cardinal/log" "pkg.world.dev/world-engine/cardinal/receipt" "pkg.world.dev/world-engine/cardinal/router" - "pkg.world.dev/world-engine/cardinal/search" "pkg.world.dev/world-engine/cardinal/search/filter" "pkg.world.dev/world-engine/cardinal/server" servertypes "pkg.world.dev/world-engine/cardinal/server/types" @@ -633,8 +632,8 @@ func (w *World) HandleEVMQuery(name string, abiRequest []byte) ([]byte, error) { return qry.EncodeEVMReply(reply) } -func (w *World) Search(filter filter.ComponentFilter) search.EntitySearch { - return search.NewLegacySearch(filter) +func (w *World) Search(filter filter.ComponentFilter) EntitySearch { + return NewLegacySearch(filter) } func (w *World) StoreReader() gamestate.Reader { diff --git a/cardinal/world_persona.go b/cardinal/world_persona.go index 37c1f42c4..3b03b4ef3 100644 --- a/cardinal/world_persona.go +++ b/cardinal/world_persona.go @@ -7,7 +7,6 @@ import ( "pkg.world.dev/world-engine/cardinal/persona" "pkg.world.dev/world-engine/cardinal/persona/component" - "pkg.world.dev/world-engine/cardinal/search" "pkg.world.dev/world-engine/cardinal/search/filter" "pkg.world.dev/world-engine/cardinal/types" ) @@ -21,7 +20,7 @@ func (w *World) GetSignerForPersonaTag(personaTag string, tick uint64) (addr str } var errs []error wCtx := NewReadOnlyWorldContext(w) - s := search.NewSearch().Entity(filter.Exact(filter.Component[component.SignerComponent]())) + s := NewSearch().Entity(filter.Exact(filter.Component[component.SignerComponent]())) err = s.Each(wCtx, func(id types.EntityID) bool { sc, err := GetComponent[component.SignerComponent](wCtx, id) @@ -45,7 +44,7 @@ func (w *World) GetSignerForPersonaTag(personaTag string, tick uint64) (addr str func (w *World) GetSignerComponentForPersona(personaTag string) (*component.SignerComponent, error) { var sc *component.SignerComponent wCtx := NewReadOnlyWorldContext(w) - q := search.NewSearch().Entity(filter.Exact(filter.Component[component.SignerComponent]())) + q := NewSearch().Entity(filter.Exact(filter.Component[component.SignerComponent]())) var getComponentErr error searchIterationErr := eris.Wrap( q.Each(wCtx, diff --git a/cardinal/world_persona_test.go b/cardinal/world_persona_test.go index 4b618001f..bdcedca0c 100644 --- a/cardinal/world_persona_test.go +++ b/cardinal/world_persona_test.go @@ -10,7 +10,6 @@ import ( "pkg.world.dev/world-engine/cardinal" "pkg.world.dev/world-engine/cardinal/persona/component" "pkg.world.dev/world-engine/cardinal/persona/msg" - "pkg.world.dev/world-engine/cardinal/search" "pkg.world.dev/world-engine/cardinal/search/filter" "pkg.world.dev/world-engine/cardinal/testutils" "pkg.world.dev/world-engine/cardinal/types" @@ -100,7 +99,7 @@ func TestCreatePersonaSystem_WhenCardinalIsRestarted_PersonaTagsAreStillRegister // across a channel. emitNumberOfPersonaTagsSystem := func(wCtx cardinal.Context) error { result := countPersonaTagsResult{personaTags: map[string]bool{}} - err := search.NewSearch(). + err := cardinal.NewSearch(). Entity(filter.Exact(filter.Component[component.SignerComponent]())). Each(wCtx, func(id types.EntityID) bool { comp, err := cardinal.GetComponent[component.SignerComponent](wCtx, id) From 799db3eb1b06ed16668b6a7c2722bd54111b32e6 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Thu, 9 May 2024 18:45:20 -0700 Subject: [PATCH 16/76] make 3 methods private. --- cardinal/message.go | 4 ++-- cardinal/system.go | 2 +- cardinal/types/engine/context.go | 4 ++-- cardinal/types/engine/mocks/context.go | 10 +++++----- cardinal/world_context.go | 12 ++++++------ 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/cardinal/message.go b/cardinal/message.go index 3c3f17cc0..8854d360f 100644 --- a/cardinal/message.go +++ b/cardinal/message.go @@ -104,11 +104,11 @@ func (t *MessageType[In, Out]) SetID(id types.MessageID) error { } func (t *MessageType[In, Out]) AddError(wCtx Context, hash types.TxHash, err error) { - wCtx.AddMessageError(hash, err) + wCtx.addMessageError(hash, err) } func (t *MessageType[In, Out]) SetResult(wCtx Context, hash types.TxHash, result Out) { - wCtx.SetMessageResult(hash, result) + wCtx.setMessageResult(hash, result) } func (t *MessageType[In, Out]) GetReceipt(wCtx Context, hash types.TxHash) ( diff --git a/cardinal/system.go b/cardinal/system.go index a220807b4..08d48d616 100644 --- a/cardinal/system.go +++ b/cardinal/system.go @@ -119,7 +119,7 @@ func (m *systemManager) runSystems(wCtx Context) error { m.currentSystem = sys.Name // Inject the system name into the logger - wCtx.SetLogger(wCtx.Logger().With().Str("system", sys.Name).Logger()) + wCtx.setLogger(wCtx.Logger().With().Str("system", sys.Name).Logger()) // Executes the system function that the user registered systemStartTime := time.Now() diff --git a/cardinal/types/engine/context.go b/cardinal/types/engine/context.go index 68beebc4e..78707cc3c 100644 --- a/cardinal/types/engine/context.go +++ b/cardinal/types/engine/context.go @@ -20,8 +20,8 @@ package engine // // // setLogger is used to inject a new logger configuration to an engine context that is already created. // setLogger(logger zerolog.Logger) -// AddMessageError(id types.TxHash, err error) -// SetMessageResult(id types.TxHash, a any) +// addMessageError(id types.TxHash, err error) +// setMessageResult(id types.TxHash, a any) // GetComponentByName(name string) (types.ComponentMetadata, error) // GetMessageByType(mType reflect.Type) (types.Message, bool) // GetTransactionReceipt(id types.TxHash) (any, []error, bool) diff --git a/cardinal/types/engine/mocks/context.go b/cardinal/types/engine/mocks/context.go index b5f7dc115..285183609 100644 --- a/cardinal/types/engine/mocks/context.go +++ b/cardinal/types/engine/mocks/context.go @@ -42,13 +42,13 @@ func (m *MockContext) EXPECT() *MockContextMockRecorder { // AddMessageError mocks base method. func (m *MockContext) AddMessageError(id types.TxHash, err error) { m.ctrl.T.Helper() - m.ctrl.Call(m, "AddMessageError", id, err) + m.ctrl.Call(m, "addMessageError", id, err) } // AddMessageError indicates an expected call of AddMessageError. func (mr *MockContextMockRecorder) AddMessageError(id, err interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddMessageError", reflect.TypeOf((*MockContext)(nil).AddMessageError), id, err) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "addMessageError", reflect.TypeOf((*MockContext)(nil).AddMessageError), id, err) } // AddTransaction mocks base method. @@ -268,7 +268,7 @@ func (mr *MockContextMockRecorder) ReceiptHistorySize() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReceiptHistorySize", reflect.TypeOf((*MockContext)(nil).ReceiptHistorySize)) } -// SetLogger mocks base method. +// setLogger mocks base method. func (m *MockContext) setLogger(logger zerolog.Logger) { m.ctrl.T.Helper() m.ctrl.Call(m, "setLogger", logger) @@ -283,13 +283,13 @@ func (mr *MockContextMockRecorder) SetLogger(logger interface{}) *gomock.Call { // SetMessageResult mocks base method. func (m *MockContext) SetMessageResult(id types.TxHash, a any) { m.ctrl.T.Helper() - m.ctrl.Call(m, "SetMessageResult", id, a) + m.ctrl.Call(m, "setMessageResult", id, a) } // SetMessageResult indicates an expected call of SetMessageResult. func (mr *MockContextMockRecorder) SetMessageResult(id, a interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetMessageResult", reflect.TypeOf((*MockContext)(nil).SetMessageResult), id, a) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "setMessageResult", reflect.TypeOf((*MockContext)(nil).SetMessageResult), id, a) } // StoreManager mocks base method. diff --git a/cardinal/world_context.go b/cardinal/world_context.go index 96b585c7b..5a516f5c9 100644 --- a/cardinal/world_context.go +++ b/cardinal/world_context.go @@ -36,9 +36,9 @@ type Context interface { // For internal use. // SetLogger is used to inject a new logger configuration to an engine context that is already created. - SetLogger(logger zerolog.Logger) - AddMessageError(id types.TxHash, err error) - SetMessageResult(id types.TxHash, a any) + setLogger(logger zerolog.Logger) + addMessageError(id types.TxHash, err error) + setMessageResult(id types.TxHash, a any) GetComponentByName(name string) (types.ComponentMetadata, error) GetMessageByType(mType reflect.Type) (types.Message, bool) GetTransactionReceipt(id types.TxHash) (any, []error, bool) @@ -104,7 +104,7 @@ func (ctx *worldContext) GetMessageByType(mType reflect.Type) (types.Message, bo return ctx.world.GetMessageByType(mType) } -func (ctx *worldContext) SetLogger(logger zerolog.Logger) { +func (ctx *worldContext) setLogger(logger zerolog.Logger) { ctx.logger = &logger } @@ -112,12 +112,12 @@ func (ctx *worldContext) GetComponentByName(name string) (types.ComponentMetadat return ctx.world.GetComponentByName(name) } -func (ctx *worldContext) AddMessageError(id types.TxHash, err error) { +func (ctx *worldContext) addMessageError(id types.TxHash, err error) { // TODO(scott): i dont trust exposing this to the users. this should be fully abstracted away. ctx.world.receiptHistory.AddError(id, err) } -func (ctx *worldContext) SetMessageResult(id types.TxHash, a any) { +func (ctx *worldContext) setMessageResult(id types.TxHash, a any) { // TODO(scott): i dont trust exposing this to the users. this should be fully abstracted away. ctx.world.receiptHistory.SetResult(id, a) } From 5b35880fd981a332e5f4f65daa4d4fb5908eaebe Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Thu, 9 May 2024 18:52:02 -0700 Subject: [PATCH 17/76] 4 methods. --- cardinal/cardinal.go | 12 ++++++------ cardinal/types/engine/context.go | 2 +- cardinal/types/engine/mocks/context.go | 4 ++-- cardinal/util.go | 2 +- cardinal/world_context.go | 6 +++--- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/cardinal/cardinal.go b/cardinal/cardinal.go index 6eb7a1e2b..266483098 100644 --- a/cardinal/cardinal.go +++ b/cardinal/cardinal.go @@ -168,7 +168,7 @@ func CreateMany(wCtx Context, num int, components ...types.Component) (entityIDs defer func() { panicOnFatalError(wCtx, err) }() // Error if the context is read only - if wCtx.IsReadOnly() { + if wCtx.isReadOnly() { return nil, ErrEntityMutationOnReadOnly } @@ -216,7 +216,7 @@ func SetComponent[T types.Component](wCtx Context, id types.EntityID, component defer func() { panicOnFatalError(wCtx, err) }() // Error if the context is read only - if wCtx.IsReadOnly() { + if wCtx.isReadOnly() { return ErrEntityMutationOnReadOnly } @@ -278,7 +278,7 @@ func UpdateComponent[T types.Component](wCtx Context, id types.EntityID, fn func defer func() { panicOnFatalError(wCtx, err) }() // Error if the context is read only - if wCtx.IsReadOnly() { + if wCtx.isReadOnly() { return err } @@ -304,7 +304,7 @@ func AddComponentTo[T types.Component](wCtx Context, id types.EntityID) (err err defer func() { panicOnFatalError(wCtx, err) }() // Error if the context is read only - if wCtx.IsReadOnly() { + if wCtx.isReadOnly() { return ErrEntityMutationOnReadOnly } @@ -329,7 +329,7 @@ func RemoveComponentFrom[T types.Component](wCtx Context, id types.EntityID) (er defer func() { panicOnFatalError(wCtx, err) }() // Error if the context is read only - if wCtx.IsReadOnly() { + if wCtx.isReadOnly() { return ErrEntityMutationOnReadOnly } @@ -354,7 +354,7 @@ func Remove(wCtx Context, id types.EntityID) (err error) { defer func() { panicOnFatalError(wCtx, err) }() // Error if the context is read only - if wCtx.IsReadOnly() { + if wCtx.isReadOnly() { return ErrEntityMutationOnReadOnly } diff --git a/cardinal/types/engine/context.go b/cardinal/types/engine/context.go index 78707cc3c..1a5706488 100644 --- a/cardinal/types/engine/context.go +++ b/cardinal/types/engine/context.go @@ -33,5 +33,5 @@ package engine // StoreReader() gamestate.Reader // StoreManager() gamestate.Manager // GetTxPool() *txpool.TxPool -// IsReadOnly() bool +// isReadOnly() bool //} diff --git a/cardinal/types/engine/mocks/context.go b/cardinal/types/engine/mocks/context.go index 285183609..1d7e4d1d4 100644 --- a/cardinal/types/engine/mocks/context.go +++ b/cardinal/types/engine/mocks/context.go @@ -201,7 +201,7 @@ func (mr *MockContextMockRecorder) GetTxPool() *gomock.Call { // IsReadOnly mocks base method. func (m *MockContext) IsReadOnly() bool { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "IsReadOnly") + ret := m.ctrl.Call(m, "isReadOnly") ret0, _ := ret[0].(bool) return ret0 } @@ -209,7 +209,7 @@ func (m *MockContext) IsReadOnly() bool { // IsReadOnly indicates an expected call of IsReadOnly. func (mr *MockContextMockRecorder) IsReadOnly() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsReadOnly", reflect.TypeOf((*MockContext)(nil).IsReadOnly)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "isReadOnly", reflect.TypeOf((*MockContext)(nil).IsReadOnly)) } // IsWorldReady mocks base method. diff --git a/cardinal/util.go b/cardinal/util.go index faec93b1a..fc7a29e64 100644 --- a/cardinal/util.go +++ b/cardinal/util.go @@ -33,7 +33,7 @@ func separateOptions(opts []WorldOption) ( // panicOnFatalError is a helper function to panic on non-deterministic errors (i.e. Redis error). func panicOnFatalError(wCtx Context, err error) { - if err != nil && !wCtx.IsReadOnly() && isFatalError(err) { + if err != nil && !wCtx.isReadOnly() && isFatalError(err) { wCtx.Logger().Panic().Err(err).Msgf("fatal error: %v", eris.ToString(err, true)) panic(err) } diff --git a/cardinal/world_context.go b/cardinal/world_context.go index 5a516f5c9..43e96e2e6 100644 --- a/cardinal/world_context.go +++ b/cardinal/world_context.go @@ -50,7 +50,7 @@ type Context interface { StoreReader() gamestate.Reader StoreManager() gamestate.Manager GetTxPool() *txpool.TxPool - IsReadOnly() bool + isReadOnly() bool } type worldContext struct { @@ -162,7 +162,7 @@ func (ctx *worldContext) GetTxPool() *txpool.TxPool { return ctx.txPool } -func (ctx *worldContext) IsReadOnly() bool { +func (ctx *worldContext) isReadOnly() bool { return ctx.readOnly } @@ -172,7 +172,7 @@ func (ctx *worldContext) StoreManager() gamestate.Manager { func (ctx *worldContext) StoreReader() gamestate.Reader { sm := ctx.StoreManager() - if ctx.IsReadOnly() { + if ctx.isReadOnly() { return sm.ToReadOnly() } return sm From 2252d9e7239e3bf4b4391e3e9a152261f9d5648e Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Thu, 9 May 2024 18:52:46 -0700 Subject: [PATCH 18/76] checkpoint. --- cardinal/message.go | 2 +- cardinal/types/engine/context.go | 2 +- cardinal/types/engine/mocks/context.go | 4 ++-- cardinal/world_context.go | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cardinal/message.go b/cardinal/message.go index 8854d360f..06f8df668 100644 --- a/cardinal/message.go +++ b/cardinal/message.go @@ -148,7 +148,7 @@ func (t *MessageType[In, Out]) Each(wCtx Context, fn func(TxData[In]) (Out, erro // In extracts all the TxData in the tx pool that match this MessageType's ID. func (t *MessageType[In, Out]) In(wCtx Context) []TxData[In] { - tq := wCtx.GetTxPool() + tq := wCtx.getTxPool() var txs []TxData[In] for _, txData := range tq.ForID(t.ID()) { if val, ok := txData.Msg.(In); ok { diff --git a/cardinal/types/engine/context.go b/cardinal/types/engine/context.go index 1a5706488..6a8d27656 100644 --- a/cardinal/types/engine/context.go +++ b/cardinal/types/engine/context.go @@ -32,6 +32,6 @@ package engine // IsWorldReady() bool // StoreReader() gamestate.Reader // StoreManager() gamestate.Manager -// GetTxPool() *txpool.TxPool +// getTxPool() *txpool.TxPool // isReadOnly() bool //} diff --git a/cardinal/types/engine/mocks/context.go b/cardinal/types/engine/mocks/context.go index 1d7e4d1d4..dc9cf50d0 100644 --- a/cardinal/types/engine/mocks/context.go +++ b/cardinal/types/engine/mocks/context.go @@ -187,7 +187,7 @@ func (mr *MockContextMockRecorder) GetTransactionReceiptsForTick(tick interface{ // GetTxPool mocks base method. func (m *MockContext) GetTxPool() *txpool.TxPool { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetTxPool") + ret := m.ctrl.Call(m, "getTxPool") ret0, _ := ret[0].(*txpool.TxPool) return ret0 } @@ -195,7 +195,7 @@ func (m *MockContext) GetTxPool() *txpool.TxPool { // GetTxPool indicates an expected call of GetTxPool. func (mr *MockContextMockRecorder) GetTxPool() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTxPool", reflect.TypeOf((*MockContext)(nil).GetTxPool)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "getTxPool", reflect.TypeOf((*MockContext)(nil).GetTxPool)) } // IsReadOnly mocks base method. diff --git a/cardinal/world_context.go b/cardinal/world_context.go index 43e96e2e6..9f9618da4 100644 --- a/cardinal/world_context.go +++ b/cardinal/world_context.go @@ -49,7 +49,7 @@ type Context interface { IsWorldReady() bool StoreReader() gamestate.Reader StoreManager() gamestate.Manager - GetTxPool() *txpool.TxPool + getTxPool() *txpool.TxPool isReadOnly() bool } @@ -158,7 +158,7 @@ func (ctx *worldContext) AddTransaction(id types.MessageID, v any, sig *sign.Tra return ctx.world.AddTransaction(id, v, sig) } -func (ctx *worldContext) GetTxPool() *txpool.TxPool { +func (ctx *worldContext) getTxPool() *txpool.TxPool { return ctx.txPool } From 7356fc5083bede8ff43503bf5ff1d2e661174979 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Thu, 9 May 2024 18:54:23 -0700 Subject: [PATCH 19/76] checkpoint. --- cardinal/cardinal.go | 2 +- cardinal/filtercomponent.go | 2 +- cardinal/search.go | 10 +++++----- cardinal/types/engine/context.go | 2 +- cardinal/types/engine/mocks/context.go | 4 ++-- cardinal/world_context.go | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/cardinal/cardinal.go b/cardinal/cardinal.go index 266483098..ae06d6abf 100644 --- a/cardinal/cardinal.go +++ b/cardinal/cardinal.go @@ -255,7 +255,7 @@ func GetComponent[T types.Component](wCtx Context, id types.EntityID) (comp *T, } // Get current component value - compValue, err := wCtx.StoreReader().GetComponentForEntity(c, id) + compValue, err := wCtx.storeReader().GetComponentForEntity(c, id) if err != nil { return nil, err } diff --git a/cardinal/filtercomponent.go b/cardinal/filtercomponent.go index 4b9917b38..58e98a2f0 100644 --- a/cardinal/filtercomponent.go +++ b/cardinal/filtercomponent.go @@ -21,7 +21,7 @@ func ComponentFilter[T types.Component](f func(comp T) bool) FilterFn { return false, err } // Get current component value - compValue, err := wCtx.StoreReader().GetComponentForEntity(c, id) + compValue, err := wCtx.storeReader().GetComponentForEntity(c, id) if err != nil { return false, err } diff --git a/cardinal/search.go b/cardinal/search.go index 4b040cff5..2478fd766 100644 --- a/cardinal/search.go +++ b/cardinal/search.go @@ -140,7 +140,7 @@ func (s *Search) Each(eCtx Context, callback CallbackFn) (err error) { defer func() { defer panicOnFatalError(eCtx, err) }() result := s.evaluateSearch(eCtx) - iter := iterators.NewEntityIterator(0, eCtx.StoreReader(), result) + iter := iterators.NewEntityIterator(0, eCtx.storeReader(), result) for iter.HasNext() { entities, err := iter.Next() if err != nil { @@ -190,7 +190,7 @@ func (s *Search) Count(eCtx Context) (ret int, err error) { defer func() { defer panicOnFatalError(eCtx, err) }() result := s.evaluateSearch(eCtx) - iter := iterators.NewEntityIterator(0, eCtx.StoreReader(), result) + iter := iterators.NewEntityIterator(0, eCtx.storeReader(), result) for iter.HasNext() { entities, err := iter.Next() if err != nil { @@ -219,7 +219,7 @@ func (s *Search) First(eCtx Context) (id types.EntityID, err error) { defer func() { defer panicOnFatalError(eCtx, err) }() result := s.evaluateSearch(eCtx) - iter := iterators.NewEntityIterator(0, eCtx.StoreReader(), result) + iter := iterators.NewEntityIterator(0, eCtx.storeReader(), result) if !iter.HasNext() { return iterators.BadID, eris.Wrap(err, "") } @@ -256,10 +256,10 @@ func (s *Search) MustFirst(eCtx Context) types.EntityID { func (s *Search) evaluateSearch(eCtx Context) []types.ArchetypeID { cache := s.archMatches - for it := eCtx.StoreReader().SearchFrom(s.filter, cache.seen); it.HasNext(); { + for it := eCtx.storeReader().SearchFrom(s.filter, cache.seen); it.HasNext(); { cache.archetypes = append(cache.archetypes, it.Next()) } - cache.seen = eCtx.StoreReader().ArchetypeCount() + cache.seen = eCtx.storeReader().ArchetypeCount() return cache.archetypes } diff --git a/cardinal/types/engine/context.go b/cardinal/types/engine/context.go index 6a8d27656..15b2bee2d 100644 --- a/cardinal/types/engine/context.go +++ b/cardinal/types/engine/context.go @@ -30,7 +30,7 @@ package engine // ReceiptHistorySize() uint64 // AddTransaction(id types.MessageID, v any, sig *sign.Transaction) (uint64, types.TxHash) // IsWorldReady() bool -// StoreReader() gamestate.Reader +// storeReader() gamestate.Reader // StoreManager() gamestate.Manager // getTxPool() *txpool.TxPool // isReadOnly() bool diff --git a/cardinal/types/engine/mocks/context.go b/cardinal/types/engine/mocks/context.go index dc9cf50d0..f0f4116fd 100644 --- a/cardinal/types/engine/mocks/context.go +++ b/cardinal/types/engine/mocks/context.go @@ -309,7 +309,7 @@ func (mr *MockContextMockRecorder) StoreManager() *gomock.Call { // StoreReader mocks base method. func (m *MockContext) StoreReader() gamestate.Reader { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "StoreReader") + ret := m.ctrl.Call(m, "storeReader") ret0, _ := ret[0].(gamestate.Reader) return ret0 } @@ -317,7 +317,7 @@ func (m *MockContext) StoreReader() gamestate.Reader { // StoreReader indicates an expected call of StoreReader. func (mr *MockContextMockRecorder) StoreReader() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StoreReader", reflect.TypeOf((*MockContext)(nil).StoreReader)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "storeReader", reflect.TypeOf((*MockContext)(nil).StoreReader)) } // Timestamp mocks base method. diff --git a/cardinal/world_context.go b/cardinal/world_context.go index 9f9618da4..4d26f4484 100644 --- a/cardinal/world_context.go +++ b/cardinal/world_context.go @@ -47,7 +47,7 @@ type Context interface { ReceiptHistorySize() uint64 AddTransaction(id types.MessageID, v any, sig *sign.Transaction) (uint64, types.TxHash) IsWorldReady() bool - StoreReader() gamestate.Reader + storeReader() gamestate.Reader StoreManager() gamestate.Manager getTxPool() *txpool.TxPool isReadOnly() bool @@ -170,7 +170,7 @@ func (ctx *worldContext) StoreManager() gamestate.Manager { return ctx.world.entityStore } -func (ctx *worldContext) StoreReader() gamestate.Reader { +func (ctx *worldContext) storeReader() gamestate.Reader { sm := ctx.StoreManager() if ctx.isReadOnly() { return sm.ToReadOnly() From 0492a2bee421bc5739998ca99740e0c80c4aac20 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Thu, 9 May 2024 18:56:25 -0700 Subject: [PATCH 20/76] checkpoint. --- cardinal/cardinal_test.go | 4 ++-- cardinal/types/engine/context.go | 4 ++-- cardinal/types/engine/mocks/context.go | 8 ++++---- cardinal/world.go | 2 +- cardinal/world_context.go | 8 ++++---- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/cardinal/cardinal_test.go b/cardinal/cardinal_test.go index cdbf08b1c..72074ce9b 100644 --- a/cardinal/cardinal_test.go +++ b/cardinal/cardinal_test.go @@ -274,7 +274,7 @@ func TestAddToPoolDuringTickDoesNotTimeout(t *testing.T) { // Make sure we're actually in the system. inSystemCh <- struct{}{} - // Make sure we can call AddTransaction again in a reasonable amount of time + // Make sure we can call addTransaction again in a reasonable amount of time timeout := time.After(500 * time.Millisecond) doneWithAddTx := make(chan struct{}) @@ -287,7 +287,7 @@ func TestAddToPoolDuringTickDoesNotTimeout(t *testing.T) { case <-doneWithAddTx: // happy path case <-timeout: - t.Fatal("timeout while trying to AddTransaction") + t.Fatal("timeout while trying to addTransaction") } // release the system inSystemCh <- struct{}{} diff --git a/cardinal/types/engine/context.go b/cardinal/types/engine/context.go index 15b2bee2d..7d331d6ca 100644 --- a/cardinal/types/engine/context.go +++ b/cardinal/types/engine/context.go @@ -27,8 +27,8 @@ package engine // GetTransactionReceipt(id types.TxHash) (any, []error, bool) // GetSignerForPersonaTag(personaTag string, tick uint64) (addr string, err error) // GetTransactionReceiptsForTick(tick uint64) ([]receipt.Receipt, error) -// ReceiptHistorySize() uint64 -// AddTransaction(id types.MessageID, v any, sig *sign.Transaction) (uint64, types.TxHash) +// receiptHistorySize() uint64 +// addTransaction(id types.MessageID, v any, sig *sign.Transaction) (uint64, types.TxHash) // IsWorldReady() bool // storeReader() gamestate.Reader // StoreManager() gamestate.Manager diff --git a/cardinal/types/engine/mocks/context.go b/cardinal/types/engine/mocks/context.go index f0f4116fd..9bec464f5 100644 --- a/cardinal/types/engine/mocks/context.go +++ b/cardinal/types/engine/mocks/context.go @@ -54,7 +54,7 @@ func (mr *MockContextMockRecorder) AddMessageError(id, err interface{}) *gomock. // AddTransaction mocks base method. func (m *MockContext) AddTransaction(id types.MessageID, v any, sig *sign.Transaction) (uint64, types.TxHash) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AddTransaction", id, v, sig) + ret := m.ctrl.Call(m, "addTransaction", id, v, sig) ret0, _ := ret[0].(uint64) ret1, _ := ret[1].(types.TxHash) return ret0, ret1 @@ -63,7 +63,7 @@ func (m *MockContext) AddTransaction(id types.MessageID, v any, sig *sign.Transa // AddTransaction indicates an expected call of AddTransaction. func (mr *MockContextMockRecorder) AddTransaction(id, v, sig interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddTransaction", reflect.TypeOf((*MockContext)(nil).AddTransaction), id, v, sig) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "addTransaction", reflect.TypeOf((*MockContext)(nil).AddTransaction), id, v, sig) } // CurrentTick mocks base method. @@ -257,7 +257,7 @@ func (mr *MockContextMockRecorder) Namespace() *gomock.Call { // ReceiptHistorySize mocks base method. func (m *MockContext) ReceiptHistorySize() uint64 { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ReceiptHistorySize") + ret := m.ctrl.Call(m, "receiptHistorySize") ret0, _ := ret[0].(uint64) return ret0 } @@ -265,7 +265,7 @@ func (m *MockContext) ReceiptHistorySize() uint64 { // ReceiptHistorySize indicates an expected call of ReceiptHistorySize. func (mr *MockContextMockRecorder) ReceiptHistorySize() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReceiptHistorySize", reflect.TypeOf((*MockContext)(nil).ReceiptHistorySize)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "receiptHistorySize", reflect.TypeOf((*MockContext)(nil).ReceiptHistorySize)) } // setLogger mocks base method. diff --git a/cardinal/world.go b/cardinal/world.go index 684697040..a5d1b1221 100644 --- a/cardinal/world.go +++ b/cardinal/world.go @@ -536,7 +536,7 @@ func (w *World) drainChannelsWaitingForNextTick() { } // AddTransaction adds a transaction to the transaction pool. This should not be used directly. -// Instead, use a MessageType.AddTransaction to ensure type consistency. Returns the tick this transaction will be +// Instead, use a MessageType.addTransaction to ensure type consistency. Returns the tick this transaction will be // executed in. func (w *World) AddTransaction(id types.MessageID, v any, sig *sign.Transaction) ( tick uint64, txHash types.TxHash, diff --git a/cardinal/world_context.go b/cardinal/world_context.go index 4d26f4484..addad0357 100644 --- a/cardinal/world_context.go +++ b/cardinal/world_context.go @@ -44,8 +44,8 @@ type Context interface { GetTransactionReceipt(id types.TxHash) (any, []error, bool) GetSignerForPersonaTag(personaTag string, tick uint64) (addr string, err error) GetTransactionReceiptsForTick(tick uint64) ([]receipt.Receipt, error) - ReceiptHistorySize() uint64 - AddTransaction(id types.MessageID, v any, sig *sign.Transaction) (uint64, types.TxHash) + receiptHistorySize() uint64 + addTransaction(id types.MessageID, v any, sig *sign.Transaction) (uint64, types.TxHash) IsWorldReady() bool storeReader() gamestate.Reader StoreManager() gamestate.Manager @@ -146,7 +146,7 @@ func (ctx *worldContext) GetTransactionReceiptsForTick(tick uint64) ([]receipt.R return ctx.world.GetTransactionReceiptsForTick(tick) } -func (ctx *worldContext) ReceiptHistorySize() uint64 { +func (ctx *worldContext) receiptHistorySize() uint64 { return ctx.world.receiptHistory.Size() } @@ -154,7 +154,7 @@ func (ctx *worldContext) Namespace() string { return ctx.world.Namespace() } -func (ctx *worldContext) AddTransaction(id types.MessageID, v any, sig *sign.Transaction) (uint64, types.TxHash) { +func (ctx *worldContext) addTransaction(id types.MessageID, v any, sig *sign.Transaction) (uint64, types.TxHash) { return ctx.world.AddTransaction(id, v, sig) } From 8297b10014c587830fd0576e49e839e0b6c366e6 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Thu, 9 May 2024 18:58:01 -0700 Subject: [PATCH 21/76] checkpoint. --- cardinal/message.go | 2 +- cardinal/types/engine/context.go | 2 +- cardinal/types/engine/mocks/context.go | 4 ++-- cardinal/world_context.go | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cardinal/message.go b/cardinal/message.go index 06f8df668..ada795857 100644 --- a/cardinal/message.go +++ b/cardinal/message.go @@ -114,7 +114,7 @@ func (t *MessageType[In, Out]) SetResult(wCtx Context, hash types.TxHash, result func (t *MessageType[In, Out]) GetReceipt(wCtx Context, hash types.TxHash) ( v Out, errs []error, ok bool, ) { - iface, errs, ok := wCtx.GetTransactionReceipt(hash) + iface, errs, ok := wCtx.getTransactionReceipt(hash) if !ok { return v, nil, false } diff --git a/cardinal/types/engine/context.go b/cardinal/types/engine/context.go index 7d331d6ca..fbc039695 100644 --- a/cardinal/types/engine/context.go +++ b/cardinal/types/engine/context.go @@ -24,7 +24,7 @@ package engine // setMessageResult(id types.TxHash, a any) // GetComponentByName(name string) (types.ComponentMetadata, error) // GetMessageByType(mType reflect.Type) (types.Message, bool) -// GetTransactionReceipt(id types.TxHash) (any, []error, bool) +// getTransactionReceipt(id types.TxHash) (any, []error, bool) // GetSignerForPersonaTag(personaTag string, tick uint64) (addr string, err error) // GetTransactionReceiptsForTick(tick uint64) ([]receipt.Receipt, error) // receiptHistorySize() uint64 diff --git a/cardinal/types/engine/mocks/context.go b/cardinal/types/engine/mocks/context.go index 9bec464f5..068c0e8de 100644 --- a/cardinal/types/engine/mocks/context.go +++ b/cardinal/types/engine/mocks/context.go @@ -156,7 +156,7 @@ func (mr *MockContextMockRecorder) GetSignerForPersonaTag(personaTag, tick inter // GetTransactionReceipt mocks base method. func (m *MockContext) GetTransactionReceipt(id types.TxHash) (any, []error, bool) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetTransactionReceipt", id) + ret := m.ctrl.Call(m, "getTransactionReceipt", id) ret0, _ := ret[0].(any) ret1, _ := ret[1].([]error) ret2, _ := ret[2].(bool) @@ -166,7 +166,7 @@ func (m *MockContext) GetTransactionReceipt(id types.TxHash) (any, []error, bool // GetTransactionReceipt indicates an expected call of GetTransactionReceipt. func (mr *MockContextMockRecorder) GetTransactionReceipt(id interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTransactionReceipt", reflect.TypeOf((*MockContext)(nil).GetTransactionReceipt), id) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "getTransactionReceipt", reflect.TypeOf((*MockContext)(nil).GetTransactionReceipt), id) } // GetTransactionReceiptsForTick mocks base method. diff --git a/cardinal/world_context.go b/cardinal/world_context.go index addad0357..f4c588231 100644 --- a/cardinal/world_context.go +++ b/cardinal/world_context.go @@ -41,7 +41,7 @@ type Context interface { setMessageResult(id types.TxHash, a any) GetComponentByName(name string) (types.ComponentMetadata, error) GetMessageByType(mType reflect.Type) (types.Message, bool) - GetTransactionReceipt(id types.TxHash) (any, []error, bool) + getTransactionReceipt(id types.TxHash) (any, []error, bool) GetSignerForPersonaTag(personaTag string, tick uint64) (addr string, err error) GetTransactionReceiptsForTick(tick uint64) ([]receipt.Receipt, error) receiptHistorySize() uint64 @@ -122,7 +122,7 @@ func (ctx *worldContext) setMessageResult(id types.TxHash, a any) { ctx.world.receiptHistory.SetResult(id, a) } -func (ctx *worldContext) GetTransactionReceipt(id types.TxHash) (any, []error, bool) { +func (ctx *worldContext) getTransactionReceipt(id types.TxHash) (any, []error, bool) { rec, ok := ctx.world.receiptHistory.GetReceipt(id) if !ok { return nil, nil, false From 6c98b6ffc4355fe1377024540a74e8166bd8dfea Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Thu, 9 May 2024 18:58:29 -0700 Subject: [PATCH 22/76] checkpoint. --- cardinal/cardinal_test.go | 2 +- cardinal/types/engine/context.go | 2 +- cardinal/types/engine/mocks/context.go | 4 ++-- cardinal/world_context.go | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cardinal/cardinal_test.go b/cardinal/cardinal_test.go index 72074ce9b..78b0fbb7a 100644 --- a/cardinal/cardinal_test.go +++ b/cardinal/cardinal_test.go @@ -685,7 +685,7 @@ func TestTransactionExample(t *testing.T) { } } // Make sure transaction errors are recorded in the receipt - receipts, err := testWorldCtx.GetTransactionReceiptsForTick(testWorldCtx.CurrentTick() - 1) + receipts, err := testWorldCtx.getTransactionReceiptsForTick(testWorldCtx.CurrentTick() - 1) assert.NilError(t, err) assert.Equal(t, 1, len(receipts)) assert.Equal(t, 1, len(receipts[0].Errs)) diff --git a/cardinal/types/engine/context.go b/cardinal/types/engine/context.go index fbc039695..ef3e52fb1 100644 --- a/cardinal/types/engine/context.go +++ b/cardinal/types/engine/context.go @@ -26,7 +26,7 @@ package engine // GetMessageByType(mType reflect.Type) (types.Message, bool) // getTransactionReceipt(id types.TxHash) (any, []error, bool) // GetSignerForPersonaTag(personaTag string, tick uint64) (addr string, err error) -// GetTransactionReceiptsForTick(tick uint64) ([]receipt.Receipt, error) +// getTransactionReceiptsForTick(tick uint64) ([]receipt.Receipt, error) // receiptHistorySize() uint64 // addTransaction(id types.MessageID, v any, sig *sign.Transaction) (uint64, types.TxHash) // IsWorldReady() bool diff --git a/cardinal/types/engine/mocks/context.go b/cardinal/types/engine/mocks/context.go index 068c0e8de..8a2830f46 100644 --- a/cardinal/types/engine/mocks/context.go +++ b/cardinal/types/engine/mocks/context.go @@ -172,7 +172,7 @@ func (mr *MockContextMockRecorder) GetTransactionReceipt(id interface{}) *gomock // GetTransactionReceiptsForTick mocks base method. func (m *MockContext) GetTransactionReceiptsForTick(tick uint64) ([]receipt.Receipt, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetTransactionReceiptsForTick", tick) + ret := m.ctrl.Call(m, "getTransactionReceiptsForTick", tick) ret0, _ := ret[0].([]receipt.Receipt) ret1, _ := ret[1].(error) return ret0, ret1 @@ -181,7 +181,7 @@ func (m *MockContext) GetTransactionReceiptsForTick(tick uint64) ([]receipt.Rece // GetTransactionReceiptsForTick indicates an expected call of GetTransactionReceiptsForTick. func (mr *MockContextMockRecorder) GetTransactionReceiptsForTick(tick interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTransactionReceiptsForTick", reflect.TypeOf((*MockContext)(nil).GetTransactionReceiptsForTick), tick) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "getTransactionReceiptsForTick", reflect.TypeOf((*MockContext)(nil).GetTransactionReceiptsForTick), tick) } // GetTxPool mocks base method. diff --git a/cardinal/world_context.go b/cardinal/world_context.go index f4c588231..10395ae67 100644 --- a/cardinal/world_context.go +++ b/cardinal/world_context.go @@ -43,7 +43,7 @@ type Context interface { GetMessageByType(mType reflect.Type) (types.Message, bool) getTransactionReceipt(id types.TxHash) (any, []error, bool) GetSignerForPersonaTag(personaTag string, tick uint64) (addr string, err error) - GetTransactionReceiptsForTick(tick uint64) ([]receipt.Receipt, error) + getTransactionReceiptsForTick(tick uint64) ([]receipt.Receipt, error) receiptHistorySize() uint64 addTransaction(id types.MessageID, v any, sig *sign.Transaction) (uint64, types.TxHash) IsWorldReady() bool @@ -142,7 +142,7 @@ func (ctx *worldContext) GetSignerForPersonaTag(personaTag string, tick uint64) return ctx.world.GetSignerForPersonaTag(personaTag, tick) } -func (ctx *worldContext) GetTransactionReceiptsForTick(tick uint64) ([]receipt.Receipt, error) { +func (ctx *worldContext) getTransactionReceiptsForTick(tick uint64) ([]receipt.Receipt, error) { return ctx.world.GetTransactionReceiptsForTick(tick) } From 1520543a2cc236f764e4d8666961a2c68dffd692 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Thu, 9 May 2024 19:01:57 -0700 Subject: [PATCH 23/76] checkpoint. --- cardinal/cardinal_test.go | 2 +- cardinal/persona_signer.go | 2 +- cardinal/types/engine/context.go | 2 +- cardinal/types/engine/mocks/context.go | 4 ++-- cardinal/world_context.go | 8 ++++---- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/cardinal/cardinal_test.go b/cardinal/cardinal_test.go index 78b0fbb7a..72074ce9b 100644 --- a/cardinal/cardinal_test.go +++ b/cardinal/cardinal_test.go @@ -685,7 +685,7 @@ func TestTransactionExample(t *testing.T) { } } // Make sure transaction errors are recorded in the receipt - receipts, err := testWorldCtx.getTransactionReceiptsForTick(testWorldCtx.CurrentTick() - 1) + receipts, err := testWorldCtx.GetTransactionReceiptsForTick(testWorldCtx.CurrentTick() - 1) assert.NilError(t, err) assert.Equal(t, 1, len(receipts)) assert.Equal(t, 1, len(receipts[0].Errs)) diff --git a/cardinal/persona_signer.go b/cardinal/persona_signer.go index dda0ea1d1..f5d64affe 100644 --- a/cardinal/persona_signer.go +++ b/cardinal/persona_signer.go @@ -30,7 +30,7 @@ type PersonaSignerQueryResponse struct { func PersonaSignerQuery(wCtx Context, req *PersonaSignerQueryRequest) (*PersonaSignerQueryResponse, error) { var status string - addr, err := wCtx.GetSignerForPersonaTag(req.PersonaTag, req.Tick) + addr, err := wCtx.getSignerForPersonaTag(req.PersonaTag, req.Tick) if err != nil { //nolint:gocritic // cant switch case this. if errors.Is(err, persona.ErrPersonaTagHasNoSigner) { diff --git a/cardinal/types/engine/context.go b/cardinal/types/engine/context.go index ef3e52fb1..fa4766faa 100644 --- a/cardinal/types/engine/context.go +++ b/cardinal/types/engine/context.go @@ -25,7 +25,7 @@ package engine // GetComponentByName(name string) (types.ComponentMetadata, error) // GetMessageByType(mType reflect.Type) (types.Message, bool) // getTransactionReceipt(id types.TxHash) (any, []error, bool) -// GetSignerForPersonaTag(personaTag string, tick uint64) (addr string, err error) +// getSignerForPersonaTag(personaTag string, tick uint64) (addr string, err error) // getTransactionReceiptsForTick(tick uint64) ([]receipt.Receipt, error) // receiptHistorySize() uint64 // addTransaction(id types.MessageID, v any, sig *sign.Transaction) (uint64, types.TxHash) diff --git a/cardinal/types/engine/mocks/context.go b/cardinal/types/engine/mocks/context.go index 8a2830f46..930a263ed 100644 --- a/cardinal/types/engine/mocks/context.go +++ b/cardinal/types/engine/mocks/context.go @@ -141,7 +141,7 @@ func (mr *MockContextMockRecorder) GetMessageByType(mType interface{}) *gomock.C // GetSignerForPersonaTag mocks base method. func (m *MockContext) GetSignerForPersonaTag(personaTag string, tick uint64) (string, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetSignerForPersonaTag", personaTag, tick) + ret := m.ctrl.Call(m, "getSignerForPersonaTag", personaTag, tick) ret0, _ := ret[0].(string) ret1, _ := ret[1].(error) return ret0, ret1 @@ -150,7 +150,7 @@ func (m *MockContext) GetSignerForPersonaTag(personaTag string, tick uint64) (st // GetSignerForPersonaTag indicates an expected call of GetSignerForPersonaTag. func (mr *MockContextMockRecorder) GetSignerForPersonaTag(personaTag, tick interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSignerForPersonaTag", reflect.TypeOf((*MockContext)(nil).GetSignerForPersonaTag), personaTag, tick) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "getSignerForPersonaTag", reflect.TypeOf((*MockContext)(nil).GetSignerForPersonaTag), personaTag, tick) } // GetTransactionReceipt mocks base method. diff --git a/cardinal/world_context.go b/cardinal/world_context.go index 10395ae67..0d5765c40 100644 --- a/cardinal/world_context.go +++ b/cardinal/world_context.go @@ -42,8 +42,8 @@ type Context interface { GetComponentByName(name string) (types.ComponentMetadata, error) GetMessageByType(mType reflect.Type) (types.Message, bool) getTransactionReceipt(id types.TxHash) (any, []error, bool) - GetSignerForPersonaTag(personaTag string, tick uint64) (addr string, err error) - getTransactionReceiptsForTick(tick uint64) ([]receipt.Receipt, error) + getSignerForPersonaTag(personaTag string, tick uint64) (addr string, err error) + GetTransactionReceiptsForTick(tick uint64) ([]receipt.Receipt, error) receiptHistorySize() uint64 addTransaction(id types.MessageID, v any, sig *sign.Transaction) (uint64, types.TxHash) IsWorldReady() bool @@ -138,11 +138,11 @@ func (ctx *worldContext) EmitStringEvent(e string) error { return ctx.world.tickResults.AddStringEvent(e) } -func (ctx *worldContext) GetSignerForPersonaTag(personaTag string, tick uint64) (addr string, err error) { +func (ctx *worldContext) getSignerForPersonaTag(personaTag string, tick uint64) (addr string, err error) { return ctx.world.GetSignerForPersonaTag(personaTag, tick) } -func (ctx *worldContext) getTransactionReceiptsForTick(tick uint64) ([]receipt.Receipt, error) { +func (ctx *worldContext) GetTransactionReceiptsForTick(tick uint64) ([]receipt.Receipt, error) { return ctx.world.GetTransactionReceiptsForTick(tick) } From d5f9dcd97664153b776554466e2979b142418da8 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Thu, 9 May 2024 19:02:47 -0700 Subject: [PATCH 24/76] privatized. All other internal methods that are still public are used in tests. --- cardinal/cardinal.go | 2 +- cardinal/types/engine/context.go | 2 +- cardinal/types/engine/mocks/context.go | 4 ++-- cardinal/world_context.go | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cardinal/cardinal.go b/cardinal/cardinal.go index ae06d6abf..89a5bb316 100644 --- a/cardinal/cardinal.go +++ b/cardinal/cardinal.go @@ -172,7 +172,7 @@ func CreateMany(wCtx Context, num int, components ...types.Component) (entityIDs return nil, ErrEntityMutationOnReadOnly } - if !wCtx.IsWorldReady() { + if !wCtx.isWorldReady() { return nil, ErrEntitiesCreatedBeforeReady } diff --git a/cardinal/types/engine/context.go b/cardinal/types/engine/context.go index fa4766faa..a56aa830c 100644 --- a/cardinal/types/engine/context.go +++ b/cardinal/types/engine/context.go @@ -29,7 +29,7 @@ package engine // getTransactionReceiptsForTick(tick uint64) ([]receipt.Receipt, error) // receiptHistorySize() uint64 // addTransaction(id types.MessageID, v any, sig *sign.Transaction) (uint64, types.TxHash) -// IsWorldReady() bool +// isWorldReady() bool // storeReader() gamestate.Reader // StoreManager() gamestate.Manager // getTxPool() *txpool.TxPool diff --git a/cardinal/types/engine/mocks/context.go b/cardinal/types/engine/mocks/context.go index 930a263ed..560fb91f9 100644 --- a/cardinal/types/engine/mocks/context.go +++ b/cardinal/types/engine/mocks/context.go @@ -215,7 +215,7 @@ func (mr *MockContextMockRecorder) IsReadOnly() *gomock.Call { // IsWorldReady mocks base method. func (m *MockContext) IsWorldReady() bool { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "IsWorldReady") + ret := m.ctrl.Call(m, "isWorldReady") ret0, _ := ret[0].(bool) return ret0 } @@ -223,7 +223,7 @@ func (m *MockContext) IsWorldReady() bool { // IsWorldReady indicates an expected call of IsWorldReady. func (mr *MockContextMockRecorder) IsWorldReady() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsWorldReady", reflect.TypeOf((*MockContext)(nil).IsWorldReady)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "isWorldReady", reflect.TypeOf((*MockContext)(nil).IsWorldReady)) } // Logger mocks base method. diff --git a/cardinal/world_context.go b/cardinal/world_context.go index 0d5765c40..84cb90029 100644 --- a/cardinal/world_context.go +++ b/cardinal/world_context.go @@ -46,7 +46,7 @@ type Context interface { GetTransactionReceiptsForTick(tick uint64) ([]receipt.Receipt, error) receiptHistorySize() uint64 addTransaction(id types.MessageID, v any, sig *sign.Transaction) (uint64, types.TxHash) - IsWorldReady() bool + isWorldReady() bool storeReader() gamestate.Reader StoreManager() gamestate.Manager getTxPool() *txpool.TxPool @@ -178,7 +178,7 @@ func (ctx *worldContext) storeReader() gamestate.Reader { return sm } -func (ctx *worldContext) IsWorldReady() bool { +func (ctx *worldContext) isWorldReady() bool { stage := ctx.world.worldStage.Current() return stage == worldstage.Ready || stage == worldstage.Running || From 53a7e70f463c47f3a0aac4482d89ac0625aa11d1 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Thu, 9 May 2024 19:06:39 -0700 Subject: [PATCH 25/76] checkpoint. --- cardinal/cardinal.go | 2 +- cardinal/cardinal_test.go | 18 +++++++++--------- cardinal/state_test.go | 2 +- cardinal/testutils/testutils.go | 19 ------------------- cardinal/types/engine/context.go | 2 +- cardinal/types/engine/mocks/context.go | 4 ++-- cardinal/util.go | 18 ++++++++++++++++++ cardinal/world_context.go | 4 ++-- cardinal/world_test.go | 2 +- 9 files changed, 35 insertions(+), 36 deletions(-) diff --git a/cardinal/cardinal.go b/cardinal/cardinal.go index 89a5bb316..69a2eb13f 100644 --- a/cardinal/cardinal.go +++ b/cardinal/cardinal.go @@ -90,7 +90,7 @@ func MustRegisterComponent[T types.Component](w *World) { func EachMessage[In any, Out any](wCtx Context, fn func(TxData[In]) (Out, error)) error { var msg MessageType[In, Out] msgType := reflect.TypeOf(msg) - tempRes, ok := wCtx.GetMessageByType(msgType) + tempRes, ok := wCtx.getMessageByType(msgType) if !ok { return eris.Errorf("Could not find %s, Message may not be registered.", msg.Name()) } diff --git a/cardinal/cardinal_test.go b/cardinal/cardinal_test.go index 72074ce9b..ec6cc1cf3 100644 --- a/cardinal/cardinal_test.go +++ b/cardinal/cardinal_test.go @@ -201,7 +201,7 @@ func TestTransactionAreAppliedToSomeEntities(t *testing.T) { ids, err := cardinal.CreateMany(wCtx, 100, ScoreComponent{}) assert.NilError(t, err) // Entities at index 5, 10 and 50 will be updated with some values - modifyScoreMsg, err := testutils.GetMessage[*ModifyScoreMsg, *EmptyMsgResult](wCtx) + modifyScoreMsg, err := cardinal.GetMessage[*ModifyScoreMsg, *EmptyMsgResult](wCtx) assert.NilError(t, err) tf.AddTransaction( modifyScoreMsg.ID(), &ModifyScoreMsg{ @@ -324,7 +324,7 @@ func TestTransactionsAreExecutedAtNextTick(t *testing.T) { err := cardinal.RegisterSystems( world, func(wCtx cardinal.Context) error { - modScoreMsg, err := testutils.GetMessage[*ModifyScoreMsg, *EmptyMsgResult](wCtx) + modScoreMsg, err := cardinal.GetMessage[*ModifyScoreMsg, *EmptyMsgResult](wCtx) if err != nil { return err } @@ -338,7 +338,7 @@ func TestTransactionsAreExecutedAtNextTick(t *testing.T) { err = cardinal.RegisterSystems( world, func(wCtx cardinal.Context) error { - modScoreMsg, err := testutils.GetMessage[*ModifyScoreMsg, *EmptyMsgResult](wCtx) + modScoreMsg, err := cardinal.GetMessage[*ModifyScoreMsg, *EmptyMsgResult](wCtx) if err != nil { return err } @@ -447,7 +447,7 @@ func TestCanGetTransactionErrorsAndResults(t *testing.T) { // 2) An EntityID that uniquely identifies this specific transaction // 3) The signature // This function would replace both "In" and "TxsAndSigsIn" - moveMsg, err := testutils.GetMessage[MoveMsg, MoveMsgResult](wCtx) + moveMsg, err := cardinal.GetMessage[MoveMsg, MoveMsgResult](wCtx) assert.NilError(t, err) txData := moveMsg.In(wCtx) assert.Equal(t, 1, len(txData), "expected 1 move transaction") @@ -506,7 +506,7 @@ func TestSystemCanFindErrorsFromEarlierSystem(t *testing.T) { world, func(wCtx cardinal.Context) error { systemCalls++ - numTx, err := testutils.GetMessage[MsgIn, MsgOut](wCtx) + numTx, err := cardinal.GetMessage[MsgIn, MsgOut](wCtx) if err != nil { return err } @@ -525,7 +525,7 @@ func TestSystemCanFindErrorsFromEarlierSystem(t *testing.T) { world, func(wCtx cardinal.Context) error { systemCalls++ - numTx, err := testutils.GetMessage[MsgIn, MsgOut](wCtx) + numTx, err := cardinal.GetMessage[MsgIn, MsgOut](wCtx) if err != nil { return err } @@ -568,7 +568,7 @@ func TestSystemCanClobberTransactionResult(t *testing.T) { world, func(wCtx cardinal.Context) error { systemCalls++ - numTx, err := testutils.GetMessage[MsgIn, MsgOut](wCtx) + numTx, err := cardinal.GetMessage[MsgIn, MsgOut](wCtx) assert.NilError(t, err) txs := numTx.In(wCtx) assert.Equal(t, 1, len(txs)) @@ -585,7 +585,7 @@ func TestSystemCanClobberTransactionResult(t *testing.T) { world, func(wCtx cardinal.Context) error { systemCalls++ - numTx, err := testutils.GetMessage[MsgIn, MsgOut](wCtx) + numTx, err := cardinal.GetMessage[MsgIn, MsgOut](wCtx) if err != nil { return err } @@ -628,7 +628,7 @@ func TestTransactionExample(t *testing.T) { assert.NilError(t, cardinal.RegisterMessage[AddHealthToEntityTx, AddHealthToEntityResult](world, msgName)) err := cardinal.RegisterSystems(world, func(wCtx cardinal.Context) error { // test "In" method - addHealthToEntity, err := testutils.GetMessage[AddHealthToEntityTx, AddHealthToEntityResult](wCtx) + addHealthToEntity, err := cardinal.GetMessage[AddHealthToEntityTx, AddHealthToEntityResult](wCtx) if err != nil { return err } diff --git a/cardinal/state_test.go b/cardinal/state_test.go index f4492837a..91569446f 100644 --- a/cardinal/state_test.go +++ b/cardinal/state_test.go @@ -309,7 +309,7 @@ func TestCanFindTransactionsAfterReloadingEngine(t *testing.T) { err := cardinal.RegisterSystems( world, func(wCtx cardinal.Context) error { - someTx, err := testutils.GetMessage[Msg, Result](wCtx) + someTx, err := cardinal.GetMessage[Msg, Result](wCtx) return cardinal.EachMessage[Msg, Result](wCtx, func(tx cardinal.TxData[Msg]) (Result, error) { someTx.SetResult(wCtx, tx.Hash, Result{}) return Result{}, err diff --git a/cardinal/testutils/testutils.go b/cardinal/testutils/testutils.go index a907ecfa4..5f0d91e82 100644 --- a/cardinal/testutils/testutils.go +++ b/cardinal/testutils/testutils.go @@ -2,15 +2,11 @@ package testutils import ( "crypto/ecdsa" - "reflect" "testing" "time" "github.com/ethereum/go-ethereum/crypto" - "github.com/rotisserie/eris" - "pkg.world.dev/world-engine/cardinal" - "pkg.world.dev/world-engine/cardinal/types" "pkg.world.dev/world-engine/sign" ) @@ -59,18 +55,3 @@ func UniqueSignatureWithName(name string) *sign.Transaction { func UniqueSignature() *sign.Transaction { return UniqueSignatureWithName("some_persona_tag") } - -func GetMessage[In any, Out any](wCtx cardinal.Context) (*cardinal.MessageType[In, Out], error) { - var msg cardinal.MessageType[In, Out] - msgType := reflect.TypeOf(msg) - tempRes, ok := wCtx.GetMessageByType(msgType) - if !ok { - return nil, eris.Errorf("Could not find %q, Message may not be registered.", msg.Name()) - } - var _ types.Message = &msg - res, ok := tempRes.(*cardinal.MessageType[In, Out]) - if !ok { - return &msg, eris.New("wrong type") - } - return res, nil -} diff --git a/cardinal/types/engine/context.go b/cardinal/types/engine/context.go index a56aa830c..d2a3da950 100644 --- a/cardinal/types/engine/context.go +++ b/cardinal/types/engine/context.go @@ -23,7 +23,7 @@ package engine // addMessageError(id types.TxHash, err error) // setMessageResult(id types.TxHash, a any) // GetComponentByName(name string) (types.ComponentMetadata, error) -// GetMessageByType(mType reflect.Type) (types.Message, bool) +// getMessageByType(mType reflect.Type) (types.Message, bool) // getTransactionReceipt(id types.TxHash) (any, []error, bool) // getSignerForPersonaTag(personaTag string, tick uint64) (addr string, err error) // getTransactionReceiptsForTick(tick uint64) ([]receipt.Receipt, error) diff --git a/cardinal/types/engine/mocks/context.go b/cardinal/types/engine/mocks/context.go index 560fb91f9..733c348a9 100644 --- a/cardinal/types/engine/mocks/context.go +++ b/cardinal/types/engine/mocks/context.go @@ -126,7 +126,7 @@ func (mr *MockContextMockRecorder) GetComponentByName(name interface{}) *gomock. // GetMessageByType mocks base method. func (m *MockContext) GetMessageByType(mType reflect.Type) (types.Message, bool) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetMessageByType", mType) + ret := m.ctrl.Call(m, "getMessageByType", mType) ret0, _ := ret[0].(types.Message) ret1, _ := ret[1].(bool) return ret0, ret1 @@ -135,7 +135,7 @@ func (m *MockContext) GetMessageByType(mType reflect.Type) (types.Message, bool) // GetMessageByType indicates an expected call of GetMessageByType. func (mr *MockContextMockRecorder) GetMessageByType(mType interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMessageByType", reflect.TypeOf((*MockContext)(nil).GetMessageByType), mType) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "getMessageByType", reflect.TypeOf((*MockContext)(nil).GetMessageByType), mType) } // GetSignerForPersonaTag mocks base method. diff --git a/cardinal/util.go b/cardinal/util.go index fc7a29e64..364816304 100644 --- a/cardinal/util.go +++ b/cardinal/util.go @@ -1,9 +1,12 @@ package cardinal import ( + "reflect" + "github.com/rotisserie/eris" "pkg.world.dev/world-engine/cardinal/server" + "pkg.world.dev/world-engine/cardinal/types" ) var NonFatalError = []error{ @@ -47,3 +50,18 @@ func isFatalError(err error) bool { } return true } + +func GetMessage[In any, Out any](wCtx Context) (*MessageType[In, Out], error) { + var msg MessageType[In, Out] + msgType := reflect.TypeOf(msg) + tempRes, ok := wCtx.getMessageByType(msgType) + if !ok { + return nil, eris.Errorf("Could not find %q, Message may not be registered.", msg.Name()) + } + var _ types.Message = &msg + res, ok := tempRes.(*MessageType[In, Out]) + if !ok { + return &msg, eris.New("wrong type") + } + return res, nil +} diff --git a/cardinal/world_context.go b/cardinal/world_context.go index 84cb90029..4dc89818c 100644 --- a/cardinal/world_context.go +++ b/cardinal/world_context.go @@ -40,7 +40,7 @@ type Context interface { addMessageError(id types.TxHash, err error) setMessageResult(id types.TxHash, a any) GetComponentByName(name string) (types.ComponentMetadata, error) - GetMessageByType(mType reflect.Type) (types.Message, bool) + getMessageByType(mType reflect.Type) (types.Message, bool) getTransactionReceipt(id types.TxHash) (any, []error, bool) getSignerForPersonaTag(personaTag string, tick uint64) (addr string, err error) GetTransactionReceiptsForTick(tick uint64) ([]receipt.Receipt, error) @@ -100,7 +100,7 @@ func (ctx *worldContext) Logger() *zerolog.Logger { return ctx.logger } -func (ctx *worldContext) GetMessageByType(mType reflect.Type) (types.Message, bool) { +func (ctx *worldContext) getMessageByType(mType reflect.Type) (types.Message, bool) { return ctx.world.GetMessageByType(mType) } diff --git a/cardinal/world_test.go b/cardinal/world_test.go index 4fb5f7a69..0d598761c 100644 --- a/cardinal/world_test.go +++ b/cardinal/world_test.go @@ -539,7 +539,7 @@ func doTickCapturePanic(ctx context.Context, world *World) (err error) { func getMessage[In any, Out any](wCtx Context) (*MessageType[In, Out], error) { var msg MessageType[In, Out] msgType := reflect.TypeOf(msg) - tempRes, ok := wCtx.GetMessageByType(msgType) + tempRes, ok := wCtx.getMessageByType(msgType) if !ok { return &msg, eris.Errorf("Could not find %s, Message may not be registered.", msg.Name()) } From a8836a3080232d4e8a8229da9fbd117750866225 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Thu, 9 May 2024 19:13:58 -0700 Subject: [PATCH 26/76] checkpoint. --- cardinal/cardinal_test.go | 2 +- cardinal/util.go | 9 +++++++++ cardinal/world_context.go | 4 ++-- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/cardinal/cardinal_test.go b/cardinal/cardinal_test.go index ec6cc1cf3..a8319adee 100644 --- a/cardinal/cardinal_test.go +++ b/cardinal/cardinal_test.go @@ -685,7 +685,7 @@ func TestTransactionExample(t *testing.T) { } } // Make sure transaction errors are recorded in the receipt - receipts, err := testWorldCtx.GetTransactionReceiptsForTick(testWorldCtx.CurrentTick() - 1) + receipts, err := cardinal.GetTransactionReceiptsForTick(testWorldCtx, testWorldCtx.CurrentTick()-1) assert.NilError(t, err) assert.Equal(t, 1, len(receipts)) assert.Equal(t, 1, len(receipts[0].Errs)) diff --git a/cardinal/util.go b/cardinal/util.go index 364816304..3f3229b98 100644 --- a/cardinal/util.go +++ b/cardinal/util.go @@ -5,6 +5,7 @@ import ( "github.com/rotisserie/eris" + "pkg.world.dev/world-engine/cardinal/receipt" "pkg.world.dev/world-engine/cardinal/server" "pkg.world.dev/world-engine/cardinal/types" ) @@ -65,3 +66,11 @@ func GetMessage[In any, Out any](wCtx Context) (*MessageType[In, Out], error) { } return res, nil } + +func GetTransactionReceiptsForTick(wCtx Context, tick uint64) ([]receipt.Receipt, error) { + ctx, ok := wCtx.(*worldContext) + if !ok { + return nil, eris.New("error in test type assertion.") + } + return ctx.world.GetTransactionReceiptsForTick(tick) +} diff --git a/cardinal/world_context.go b/cardinal/world_context.go index 4dc89818c..3f03a1094 100644 --- a/cardinal/world_context.go +++ b/cardinal/world_context.go @@ -43,7 +43,7 @@ type Context interface { getMessageByType(mType reflect.Type) (types.Message, bool) getTransactionReceipt(id types.TxHash) (any, []error, bool) getSignerForPersonaTag(personaTag string, tick uint64) (addr string, err error) - GetTransactionReceiptsForTick(tick uint64) ([]receipt.Receipt, error) + getTransactionReceiptsForTick(tick uint64) ([]receipt.Receipt, error) receiptHistorySize() uint64 addTransaction(id types.MessageID, v any, sig *sign.Transaction) (uint64, types.TxHash) isWorldReady() bool @@ -142,7 +142,7 @@ func (ctx *worldContext) getSignerForPersonaTag(personaTag string, tick uint64) return ctx.world.GetSignerForPersonaTag(personaTag, tick) } -func (ctx *worldContext) GetTransactionReceiptsForTick(tick uint64) ([]receipt.Receipt, error) { +func (ctx *worldContext) getTransactionReceiptsForTick(tick uint64) ([]receipt.Receipt, error) { return ctx.world.GetTransactionReceiptsForTick(tick) } From fcea4ce43e798b33dd5bb87dec9c199ce863ca5d Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Thu, 9 May 2024 19:16:26 -0700 Subject: [PATCH 27/76] checkpoint. --- cardinal/cardinal.go | 12 ++++++------ cardinal/search_test.go | 2 +- cardinal/types/engine/context.go | 2 +- cardinal/types/engine/mocks/context.go | 4 ++-- cardinal/util.go | 5 +++++ cardinal/world_context.go | 6 +++--- 6 files changed, 18 insertions(+), 13 deletions(-) diff --git a/cardinal/cardinal.go b/cardinal/cardinal.go index 69a2eb13f..0c363bc33 100644 --- a/cardinal/cardinal.go +++ b/cardinal/cardinal.go @@ -187,7 +187,7 @@ func CreateMany(wCtx Context, num int, components ...types.Component) (entityIDs } // Create the entities - entityIDs, err = wCtx.StoreManager().CreateManyEntities(num, acc...) + entityIDs, err = wCtx.storeManager().CreateManyEntities(num, acc...) if err != nil { return nil, err } @@ -201,7 +201,7 @@ func CreateMany(wCtx Context, num int, components ...types.Component) (entityIDs return nil, eris.Wrap(err, "failed to create entity because component is not registered") } - err = wCtx.StoreManager().SetComponentForEntity(c, id, comp) + err = wCtx.storeManager().SetComponentForEntity(c, id, comp) if err != nil { return nil, err } @@ -228,7 +228,7 @@ func SetComponent[T types.Component](wCtx Context, id types.EntityID, component } // Store the component - err = wCtx.StoreManager().SetComponentForEntity(c, id, component) + err = wCtx.storeManager().SetComponentForEntity(c, id, component) if err != nil { return err } @@ -316,7 +316,7 @@ func AddComponentTo[T types.Component](wCtx Context, id types.EntityID) (err err } // Add the component to entity - err = wCtx.StoreManager().AddComponentToEntity(c, id) + err = wCtx.storeManager().AddComponentToEntity(c, id) if err != nil { return err } @@ -341,7 +341,7 @@ func RemoveComponentFrom[T types.Component](wCtx Context, id types.EntityID) (er } // Remove the component from entity - err = wCtx.StoreManager().RemoveComponentFromEntity(c, id) + err = wCtx.storeManager().RemoveComponentFromEntity(c, id) if err != nil { return err } @@ -358,7 +358,7 @@ func Remove(wCtx Context, id types.EntityID) (err error) { return ErrEntityMutationOnReadOnly } - err = wCtx.StoreManager().RemoveEntity(id) + err = wCtx.storeManager().RemoveEntity(id) if err != nil { return err } diff --git a/cardinal/search_test.go b/cardinal/search_test.go index 3ab247303..b2b62b655 100644 --- a/cardinal/search_test.go +++ b/cardinal/search_test.go @@ -81,7 +81,7 @@ func TestSearchUsingAllMethods(t *testing.T) { for i, id := range hpids { c, err := worldCtx.GetComponentByName(HP{}.Name()) assert.NilError(t, err) - err = worldCtx.StoreManager().SetComponentForEntity(c, id, HP{amount: i}) + err = cardinal.GetStoreManagerFromContext(worldCtx).SetComponentForEntity(c, id, HP{amount: i}) assert.NilError(t, err) } amt, err := cardinal.NewSearch().Entity(filter.Not(filter.Or( diff --git a/cardinal/types/engine/context.go b/cardinal/types/engine/context.go index d2a3da950..f296c2ed9 100644 --- a/cardinal/types/engine/context.go +++ b/cardinal/types/engine/context.go @@ -31,7 +31,7 @@ package engine // addTransaction(id types.MessageID, v any, sig *sign.Transaction) (uint64, types.TxHash) // isWorldReady() bool // storeReader() gamestate.Reader -// StoreManager() gamestate.Manager +// storeManager() gamestate.Manager // getTxPool() *txpool.TxPool // isReadOnly() bool //} diff --git a/cardinal/types/engine/mocks/context.go b/cardinal/types/engine/mocks/context.go index 733c348a9..8585e5e8a 100644 --- a/cardinal/types/engine/mocks/context.go +++ b/cardinal/types/engine/mocks/context.go @@ -295,7 +295,7 @@ func (mr *MockContextMockRecorder) SetMessageResult(id, a interface{}) *gomock.C // StoreManager mocks base method. func (m *MockContext) StoreManager() gamestate.Manager { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "StoreManager") + ret := m.ctrl.Call(m, "storeManager") ret0, _ := ret[0].(gamestate.Manager) return ret0 } @@ -303,7 +303,7 @@ func (m *MockContext) StoreManager() gamestate.Manager { // StoreManager indicates an expected call of StoreManager. func (mr *MockContextMockRecorder) StoreManager() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StoreManager", reflect.TypeOf((*MockContext)(nil).StoreManager)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "storeManager", reflect.TypeOf((*MockContext)(nil).StoreManager)) } // StoreReader mocks base method. diff --git a/cardinal/util.go b/cardinal/util.go index 3f3229b98..427cc53f7 100644 --- a/cardinal/util.go +++ b/cardinal/util.go @@ -5,6 +5,7 @@ import ( "github.com/rotisserie/eris" + "pkg.world.dev/world-engine/cardinal/gamestate" "pkg.world.dev/world-engine/cardinal/receipt" "pkg.world.dev/world-engine/cardinal/server" "pkg.world.dev/world-engine/cardinal/types" @@ -74,3 +75,7 @@ func GetTransactionReceiptsForTick(wCtx Context, tick uint64) ([]receipt.Receipt } return ctx.world.GetTransactionReceiptsForTick(tick) } + +func GetStoreManagerFromContext(wCtx Context) gamestate.Manager { + return wCtx.storeManager() +} diff --git a/cardinal/world_context.go b/cardinal/world_context.go index 3f03a1094..b49bfb398 100644 --- a/cardinal/world_context.go +++ b/cardinal/world_context.go @@ -48,7 +48,7 @@ type Context interface { addTransaction(id types.MessageID, v any, sig *sign.Transaction) (uint64, types.TxHash) isWorldReady() bool storeReader() gamestate.Reader - StoreManager() gamestate.Manager + storeManager() gamestate.Manager getTxPool() *txpool.TxPool isReadOnly() bool } @@ -166,12 +166,12 @@ func (ctx *worldContext) isReadOnly() bool { return ctx.readOnly } -func (ctx *worldContext) StoreManager() gamestate.Manager { +func (ctx *worldContext) storeManager() gamestate.Manager { return ctx.world.entityStore } func (ctx *worldContext) storeReader() gamestate.Reader { - sm := ctx.StoreManager() + sm := ctx.storeManager() if ctx.isReadOnly() { return sm.ToReadOnly() } From a3fb9151fadfd1cbcee2bde0a8fbbf5d8b07cb18 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Thu, 9 May 2024 19:25:25 -0700 Subject: [PATCH 28/76] DONE. --- cardinal/cardinal.go | 12 ++++++------ cardinal/filtercomponent.go | 2 +- cardinal/search_test.go | 2 +- cardinal/server/handler/cql.go | 2 +- cardinal/types/engine/context.go | 2 +- cardinal/types/engine/mocks/context.go | 4 ++-- cardinal/util.go | 4 ++++ cardinal/world_context.go | 4 ++-- 8 files changed, 18 insertions(+), 14 deletions(-) diff --git a/cardinal/cardinal.go b/cardinal/cardinal.go index 0c363bc33..cc92842ab 100644 --- a/cardinal/cardinal.go +++ b/cardinal/cardinal.go @@ -179,7 +179,7 @@ func CreateMany(wCtx Context, num int, components ...types.Component) (entityIDs // Get all component metadata for the given components acc := make([]types.ComponentMetadata, 0, len(components)) for _, comp := range components { - c, err := wCtx.GetComponentByName(comp.Name()) + c, err := wCtx.getComponentByName(comp.Name()) if err != nil { return nil, eris.Wrap(err, "failed to create entity because component is not registered") } @@ -196,7 +196,7 @@ func CreateMany(wCtx Context, num int, components ...types.Component) (entityIDs for _, id := range entityIDs { for _, comp := range components { var c types.ComponentMetadata - c, err = wCtx.GetComponentByName(comp.Name()) + c, err = wCtx.getComponentByName(comp.Name()) if err != nil { return nil, eris.Wrap(err, "failed to create entity because component is not registered") } @@ -222,7 +222,7 @@ func SetComponent[T types.Component](wCtx Context, id types.EntityID, component // Get the component metadata var t T - c, err := wCtx.GetComponentByName(t.Name()) + c, err := wCtx.getComponentByName(t.Name()) if err != nil { return err } @@ -249,7 +249,7 @@ func GetComponent[T types.Component](wCtx Context, id types.EntityID) (comp *T, // Get the component metadata var t T - c, err := wCtx.GetComponentByName(t.Name()) + c, err := wCtx.getComponentByName(t.Name()) if err != nil { return nil, err } @@ -310,7 +310,7 @@ func AddComponentTo[T types.Component](wCtx Context, id types.EntityID) (err err // Get the component metadata var t T - c, err := wCtx.GetComponentByName(t.Name()) + c, err := wCtx.getComponentByName(t.Name()) if err != nil { return err } @@ -335,7 +335,7 @@ func RemoveComponentFrom[T types.Component](wCtx Context, id types.EntityID) (er // Get the component metadata var t T - c, err := wCtx.GetComponentByName(t.Name()) + c, err := wCtx.getComponentByName(t.Name()) if err != nil { return err } diff --git a/cardinal/filtercomponent.go b/cardinal/filtercomponent.go index 58e98a2f0..f54a07cf8 100644 --- a/cardinal/filtercomponent.go +++ b/cardinal/filtercomponent.go @@ -16,7 +16,7 @@ type FilterFn func(wCtx Context, id types.EntityID) (bool, error) func ComponentFilter[T types.Component](f func(comp T) bool) FilterFn { return func(wCtx Context, id types.EntityID) (bool, error) { var t T - c, err := wCtx.GetComponentByName(t.Name()) + c, err := wCtx.getComponentByName(t.Name()) if err != nil { return false, err } diff --git a/cardinal/search_test.go b/cardinal/search_test.go index b2b62b655..05261d398 100644 --- a/cardinal/search_test.go +++ b/cardinal/search_test.go @@ -79,7 +79,7 @@ func TestSearchUsingAllMethods(t *testing.T) { hpids, err := cardinal.CreateMany(worldCtx, 10, HP{}) assert.NilError(t, err) for i, id := range hpids { - c, err := worldCtx.GetComponentByName(HP{}.Name()) + c, err := cardinal.GetComponentByNameFromContext(worldCtx, HP{}.Name()) assert.NilError(t, err) err = cardinal.GetStoreManagerFromContext(worldCtx).SetComponentForEntity(c, id, HP{amount: i}) assert.NilError(t, err) diff --git a/cardinal/server/handler/cql.go b/cardinal/server/handler/cql.go index 1e0e71bb1..7629e9b90 100644 --- a/cardinal/server/handler/cql.go +++ b/cardinal/server/handler/cql.go @@ -36,7 +36,7 @@ func PostCQL( return err } - // getComponentByName is a wrapper function that casts component.ComponentMetadata from ctx.GetComponentByName + // getComponentByName is a wrapper function that casts component.ComponentMetadata from ctx.getComponentByName // to types.Component getComponentByName := func(name string) (types.Component, error) { comp, err := provider.GetComponentByName(name) diff --git a/cardinal/types/engine/context.go b/cardinal/types/engine/context.go index f296c2ed9..f59ea9113 100644 --- a/cardinal/types/engine/context.go +++ b/cardinal/types/engine/context.go @@ -22,7 +22,7 @@ package engine // setLogger(logger zerolog.Logger) // addMessageError(id types.TxHash, err error) // setMessageResult(id types.TxHash, a any) -// GetComponentByName(name string) (types.ComponentMetadata, error) +// getComponentByName(name string) (types.ComponentMetadata, error) // getMessageByType(mType reflect.Type) (types.Message, bool) // getTransactionReceipt(id types.TxHash) (any, []error, bool) // getSignerForPersonaTag(personaTag string, tick uint64) (addr string, err error) diff --git a/cardinal/types/engine/mocks/context.go b/cardinal/types/engine/mocks/context.go index 8585e5e8a..6ed32f414 100644 --- a/cardinal/types/engine/mocks/context.go +++ b/cardinal/types/engine/mocks/context.go @@ -111,7 +111,7 @@ func (mr *MockContextMockRecorder) EmitStringEvent(arg0 interface{}) *gomock.Cal // GetComponentByName mocks base method. func (m *MockContext) GetComponentByName(name string) (types.ComponentMetadata, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetComponentByName", name) + ret := m.ctrl.Call(m, "getComponentByName", name) ret0, _ := ret[0].(types.ComponentMetadata) ret1, _ := ret[1].(error) return ret0, ret1 @@ -120,7 +120,7 @@ func (m *MockContext) GetComponentByName(name string) (types.ComponentMetadata, // GetComponentByName indicates an expected call of GetComponentByName. func (mr *MockContextMockRecorder) GetComponentByName(name interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetComponentByName", reflect.TypeOf((*MockContext)(nil).GetComponentByName), name) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "getComponentByName", reflect.TypeOf((*MockContext)(nil).GetComponentByName), name) } // GetMessageByType mocks base method. diff --git a/cardinal/util.go b/cardinal/util.go index 427cc53f7..a7b92c7a7 100644 --- a/cardinal/util.go +++ b/cardinal/util.go @@ -79,3 +79,7 @@ func GetTransactionReceiptsForTick(wCtx Context, tick uint64) ([]receipt.Receipt func GetStoreManagerFromContext(wCtx Context) gamestate.Manager { return wCtx.storeManager() } + +func GetComponentByNameFromContext(wCtx Context, name string) (types.ComponentMetadata, error) { + return wCtx.getComponentByName(name) +} diff --git a/cardinal/world_context.go b/cardinal/world_context.go index b49bfb398..8d614e3eb 100644 --- a/cardinal/world_context.go +++ b/cardinal/world_context.go @@ -39,7 +39,7 @@ type Context interface { setLogger(logger zerolog.Logger) addMessageError(id types.TxHash, err error) setMessageResult(id types.TxHash, a any) - GetComponentByName(name string) (types.ComponentMetadata, error) + getComponentByName(name string) (types.ComponentMetadata, error) getMessageByType(mType reflect.Type) (types.Message, bool) getTransactionReceipt(id types.TxHash) (any, []error, bool) getSignerForPersonaTag(personaTag string, tick uint64) (addr string, err error) @@ -108,7 +108,7 @@ func (ctx *worldContext) setLogger(logger zerolog.Logger) { ctx.logger = &logger } -func (ctx *worldContext) GetComponentByName(name string) (types.ComponentMetadata, error) { +func (ctx *worldContext) getComponentByName(name string) (types.ComponentMetadata, error) { return ctx.world.GetComponentByName(name) } From 258a4d8e7004f859d3e9c7744da2dbadb46c05c6 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Thu, 9 May 2024 19:30:11 -0700 Subject: [PATCH 29/76] lints --- cardinal/search.go | 34 +++++++++++++++---------------- cardinal/server/types/provider.go | 1 - 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/cardinal/search.go b/cardinal/search.go index 2478fd766..2249edfbf 100644 --- a/cardinal/search.go +++ b/cardinal/search.go @@ -15,6 +15,23 @@ type cache struct { seen int } +//revive:disable-next-line +type EntitySearch interface { + Searchable + Where(componentFilter FilterFn) EntitySearch +} + +type Searchable interface { + evaluateSearch(eCtx Context) []types.ArchetypeID + Each(eCtx Context, callback CallbackFn) error + First(eCtx Context) (types.EntityID, error) + MustFirst(eCtx Context) types.EntityID + Count(eCtx Context) (int, error) + Collect(eCtx Context) ([]types.EntityID, error) +} + +type CallbackFn func(types.EntityID) bool + // Search represents a search for entities. // It is used to filter entities based on their components. // It receives arbitrary filters that are used to filter entities. @@ -262,20 +279,3 @@ func (s *Search) evaluateSearch(eCtx Context) []types.ArchetypeID { cache.seen = eCtx.storeReader().ArchetypeCount() return cache.archetypes } - -//revive:disable-next-line -type EntitySearch interface { - Searchable - Where(componentFilter FilterFn) EntitySearch -} - -type Searchable interface { - evaluateSearch(eCtx Context) []types.ArchetypeID - Each(eCtx Context, callback CallbackFn) error - First(eCtx Context) (types.EntityID, error) - MustFirst(eCtx Context) types.EntityID - Count(eCtx Context) (int, error) - Collect(eCtx Context) ([]types.EntityID, error) -} - -type CallbackFn func(types.EntityID) bool diff --git a/cardinal/server/types/provider.go b/cardinal/server/types/provider.go index da96e8a09..0885f698d 100644 --- a/cardinal/server/types/provider.go +++ b/cardinal/server/types/provider.go @@ -15,7 +15,6 @@ type ProviderWorld interface { AddTransaction(id types.MessageID, v any, sig *sign.Transaction) (uint64, types.TxHash) Namespace() string GetComponentByName(name string) (types.ComponentMetadata, error) - //Search(filter filter.ComponentFilter) cardinal.EntitySearch StoreReader() gamestate.Reader QueryHandler(name string, group string, bz []byte) ([]byte, error) CurrentTick() uint64 From e5845b95d1dbe1f3f64aca5adb848a467115d2a3 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Fri, 10 May 2024 09:43:34 -0700 Subject: [PATCH 30/76] rename provider to world. --- cardinal/router/router.go | 6 +++--- cardinal/server/handler/cql.go | 6 +++--- cardinal/server/handler/debug.go | 4 ++-- cardinal/server/handler/tx.go | 6 +++--- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/cardinal/router/router.go b/cardinal/router/router.go index c59ef8bb7..824fb91dd 100644 --- a/cardinal/router/router.go +++ b/cardinal/router/router.go @@ -62,8 +62,8 @@ type router struct { routerKey string } -func New(namespace, sequencerAddr, routerKey string, provider Provider) (Router, error) { - rtr := &router{namespace: namespace, port: defaultPort, provider: provider, routerKey: routerKey} +func New(namespace, sequencerAddr, routerKey string, world Provider) (Router, error) { + rtr := &router{namespace: namespace, port: defaultPort, provider: world, routerKey: routerKey} conn, err := grpc.Dial( sequencerAddr, @@ -74,7 +74,7 @@ func New(namespace, sequencerAddr, routerKey string, provider Provider) (Router, return nil, eris.Wrapf(err, "error dialing shard seqeuncer address at %q", sequencerAddr) } rtr.ShardSequencer = shard.NewTransactionHandlerClient(conn) - rtr.server = newEvmServer(provider, routerKey) + rtr.server = newEvmServer(world, routerKey) routerv1.RegisterMsgServer(rtr.server.grpcServer, rtr.server) return rtr, nil } diff --git a/cardinal/server/handler/cql.go b/cardinal/server/handler/cql.go index 7629e9b90..f2d4b8062 100644 --- a/cardinal/server/handler/cql.go +++ b/cardinal/server/handler/cql.go @@ -29,7 +29,7 @@ type CQLQueryResponse struct { // @Failure 400 {string} string "Invalid request parameters" // @Router /cql [post] func PostCQL( - provider servertypes.ProviderWorld) func(*fiber.Ctx) error { + world servertypes.ProviderWorld) func(*fiber.Ctx) error { return func(ctx *fiber.Ctx) error { req := new(CQLQueryRequest) if err := ctx.BodyParser(req); err != nil { @@ -39,7 +39,7 @@ func PostCQL( // getComponentByName is a wrapper function that casts component.ComponentMetadata from ctx.getComponentByName // to types.Component getComponentByName := func(name string) (types.Component, error) { - comp, err := provider.GetComponentByName(name) + comp, err := world.GetComponentByName(name) if err != nil { return nil, err } @@ -51,7 +51,7 @@ func PostCQL( if err != nil { return fiber.NewError(fiber.StatusBadRequest, err.Error()) } - result, eachError, searchErr := provider.RunCQLSearch(resultFilter) + result, eachError, searchErr := world.RunCQLSearch(resultFilter) if searchErr != nil { return fiber.NewError(fiber.StatusInternalServerError, searchErr.Error()) } diff --git a/cardinal/server/handler/debug.go b/cardinal/server/handler/debug.go index 78b746b37..d00088065 100644 --- a/cardinal/server/handler/debug.go +++ b/cardinal/server/handler/debug.go @@ -13,9 +13,9 @@ import ( // @Produce application/json // @Success 200 {object} DebugStateResponse "List of all entities" // @Router /debug/state [post] -func GetDebugState(provider servertypes.ProviderWorld) func(*fiber.Ctx) error { +func GetDebugState(world servertypes.ProviderWorld) func(*fiber.Ctx) error { return func(ctx *fiber.Ctx) error { - result, eachClosureErr, searchEachErr := provider.GetDebugState() + result, eachClosureErr, searchEachErr := world.GetDebugState() if eachClosureErr != nil { return eachClosureErr } diff --git a/cardinal/server/handler/tx.go b/cardinal/server/handler/tx.go index 3c0b55a4b..68f06d12d 100644 --- a/cardinal/server/handler/tx.go +++ b/cardinal/server/handler/tx.go @@ -41,7 +41,7 @@ type Transaction = sign.Transaction // @Failure 400 {string} string "Invalid request parameter" // @Router /tx/{txGroup}/{txName} [post] func PostTransaction( - provider servertypes.ProviderWorld, msgs map[string]map[string]types.Message, disableSigVerification bool, + world servertypes.ProviderWorld, msgs map[string]map[string]types.Message, disableSigVerification bool, ) func(*fiber.Ctx) error { return func(ctx *fiber.Ctx) error { msgType, ok := msgs[ctx.Params("group")][ctx.Params("name")] @@ -75,14 +75,14 @@ func PostTransaction( signerAddress = createPersonaMsg.SignerAddress } - if err = lookupSignerAndValidateSignature(provider, signerAddress, tx); err != nil { + if err = lookupSignerAndValidateSignature(world, signerAddress, tx); err != nil { return err } } // Add the transaction to the engine // TODO(scott): this should just deal with txpool instead of having to go through engine - tick, hash := provider.AddTransaction(msgType.ID(), msg, tx) + tick, hash := world.AddTransaction(msgType.ID(), msg, tx) return ctx.JSON(&PostTransactionResponse{ TxHash: string(hash), From 1e385ab0fce217eab78098e647887d4fde32eb50 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Fri, 10 May 2024 10:52:03 -0700 Subject: [PATCH 31/76] rename provider to world. lints and swagger fixes. --- cardinal/server/docs/docs.go | 92 ++++++++----------------------- cardinal/server/docs/swagger.json | 92 ++++++++----------------------- cardinal/server/docs/swagger.yaml | 67 +++++++--------------- cardinal/server/handler/debug.go | 8 ++- cardinal/server/handler/tx.go | 16 +++--- cardinal/server/handler/world.go | 4 +- cardinal/server/server.go | 18 +++--- 7 files changed, 94 insertions(+), 203 deletions(-) diff --git a/cardinal/server/docs/docs.go b/cardinal/server/docs/docs.go index dc5763f22..29946f2c7 100644 --- a/cardinal/server/docs/docs.go +++ b/cardinal/server/docs/docs.go @@ -65,7 +65,7 @@ const docTemplate = `{ "schema": { "type": "array", "items": { - "$ref": "#/definitions/handler.debugStateElement" + "$ref": "#/definitions/types.DebugStateElement" } } } @@ -106,50 +106,6 @@ const docTemplate = `{ } } }, - "/query/game/{queryName}": { - "post": { - "description": "Executes a query", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "summary": "Executes a query", - "parameters": [ - { - "type": "string", - "description": "Name of a registered query", - "name": "queryName", - "in": "path", - "required": true - }, - { - "description": "Query to be executed", - "name": "queryBody", - "in": "body", - "required": true, - "schema": { - "type": "object" - } - } - ], - "responses": { - "200": { - "description": "Results of the executed query", - "schema": { - "type": "object" - } - }, - "400": { - "description": "Invalid request parameters", - "schema": { - "type": "string" - } - } - } - } - }, "/query/receipts/list": { "post": { "description": "Retrieves all transaction receipts", @@ -398,6 +354,23 @@ const docTemplate = `{ } }, "definitions": { + "engine.FieldDetail": { + "type": "object", + "properties": { + "fields": { + "description": "variable name and type", + "type": "object", + "additionalProperties": {} + }, + "name": { + "description": "name of the message or query", + "type": "string" + }, + "url": { + "type": "string" + } + } + }, "handler.CQLQueryRequest": { "type": "object", "properties": { @@ -412,28 +385,11 @@ const docTemplate = `{ "results": { "type": "array", "items": { - "$ref": "#/definitions/handler.cqlData" + "$ref": "#/definitions/types.CqlData" } } } }, - "handler.FieldDetail": { - "type": "object", - "properties": { - "fields": { - "description": "variable name and type", - "type": "object", - "additionalProperties": {} - }, - "name": { - "description": "name of the message or query", - "type": "string" - }, - "url": { - "type": "string" - } - } - }, "handler.GetHealthResponse": { "type": "object", "properties": { @@ -452,13 +408,13 @@ const docTemplate = `{ "description": "list of component names", "type": "array", "items": { - "$ref": "#/definitions/handler.FieldDetail" + "$ref": "#/definitions/engine.FieldDetail" } }, "messages": { "type": "array", "items": { - "$ref": "#/definitions/handler.FieldDetail" + "$ref": "#/definitions/engine.FieldDetail" } }, "namespace": { @@ -467,7 +423,7 @@ const docTemplate = `{ "queries": { "type": "array", "items": { - "$ref": "#/definitions/handler.FieldDetail" + "$ref": "#/definitions/engine.FieldDetail" } } } @@ -551,7 +507,7 @@ const docTemplate = `{ } } }, - "handler.cqlData": { + "types.CqlData": { "type": "object", "properties": { "data": { @@ -562,7 +518,7 @@ const docTemplate = `{ } } }, - "handler.debugStateElement": { + "types.DebugStateElement": { "type": "object", "properties": { "components": { diff --git a/cardinal/server/docs/swagger.json b/cardinal/server/docs/swagger.json index 0526e3f23..7f38dbfdd 100644 --- a/cardinal/server/docs/swagger.json +++ b/cardinal/server/docs/swagger.json @@ -62,7 +62,7 @@ "schema": { "type": "array", "items": { - "$ref": "#/definitions/handler.debugStateElement" + "$ref": "#/definitions/types.DebugStateElement" } } } @@ -103,50 +103,6 @@ } } }, - "/query/game/{queryName}": { - "post": { - "description": "Executes a query", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "summary": "Executes a query", - "parameters": [ - { - "type": "string", - "description": "Name of a registered query", - "name": "queryName", - "in": "path", - "required": true - }, - { - "description": "Query to be executed", - "name": "queryBody", - "in": "body", - "required": true, - "schema": { - "type": "object" - } - } - ], - "responses": { - "200": { - "description": "Results of the executed query", - "schema": { - "type": "object" - } - }, - "400": { - "description": "Invalid request parameters", - "schema": { - "type": "string" - } - } - } - } - }, "/query/receipts/list": { "post": { "description": "Retrieves all transaction receipts", @@ -395,6 +351,23 @@ } }, "definitions": { + "engine.FieldDetail": { + "type": "object", + "properties": { + "fields": { + "description": "variable name and type", + "type": "object", + "additionalProperties": {} + }, + "name": { + "description": "name of the message or query", + "type": "string" + }, + "url": { + "type": "string" + } + } + }, "handler.CQLQueryRequest": { "type": "object", "properties": { @@ -409,28 +382,11 @@ "results": { "type": "array", "items": { - "$ref": "#/definitions/handler.cqlData" + "$ref": "#/definitions/types.CqlData" } } } }, - "handler.FieldDetail": { - "type": "object", - "properties": { - "fields": { - "description": "variable name and type", - "type": "object", - "additionalProperties": {} - }, - "name": { - "description": "name of the message or query", - "type": "string" - }, - "url": { - "type": "string" - } - } - }, "handler.GetHealthResponse": { "type": "object", "properties": { @@ -449,13 +405,13 @@ "description": "list of component names", "type": "array", "items": { - "$ref": "#/definitions/handler.FieldDetail" + "$ref": "#/definitions/engine.FieldDetail" } }, "messages": { "type": "array", "items": { - "$ref": "#/definitions/handler.FieldDetail" + "$ref": "#/definitions/engine.FieldDetail" } }, "namespace": { @@ -464,7 +420,7 @@ "queries": { "type": "array", "items": { - "$ref": "#/definitions/handler.FieldDetail" + "$ref": "#/definitions/engine.FieldDetail" } } } @@ -548,7 +504,7 @@ } } }, - "handler.cqlData": { + "types.CqlData": { "type": "object", "properties": { "data": { @@ -559,7 +515,7 @@ } } }, - "handler.debugStateElement": { + "types.DebugStateElement": { "type": "object", "properties": { "components": { diff --git a/cardinal/server/docs/swagger.yaml b/cardinal/server/docs/swagger.yaml index bf9c100d9..889d43084 100644 --- a/cardinal/server/docs/swagger.yaml +++ b/cardinal/server/docs/swagger.yaml @@ -1,18 +1,6 @@ basePath: / definitions: - handler.CQLQueryRequest: - properties: - cql: - type: string - type: object - handler.CQLQueryResponse: - properties: - results: - items: - $ref: '#/definitions/handler.cqlData' - type: array - type: object - handler.FieldDetail: + engine.FieldDetail: properties: fields: additionalProperties: {} @@ -24,6 +12,18 @@ definitions: url: type: string type: object + handler.CQLQueryRequest: + properties: + cql: + type: string + type: object + handler.CQLQueryResponse: + properties: + results: + items: + $ref: '#/definitions/types.CqlData' + type: array + type: object handler.GetHealthResponse: properties: isGameLoopRunning: @@ -36,17 +36,17 @@ definitions: components: description: list of component names items: - $ref: '#/definitions/handler.FieldDetail' + $ref: '#/definitions/engine.FieldDetail' type: array messages: items: - $ref: '#/definitions/handler.FieldDetail' + $ref: '#/definitions/engine.FieldDetail' type: array namespace: type: string queries: items: - $ref: '#/definitions/handler.FieldDetail' + $ref: '#/definitions/engine.FieldDetail' type: array type: object handler.ListTxReceiptsRequest: @@ -101,14 +101,14 @@ definitions: description: hex encoded string type: string type: object - handler.cqlData: + types.CqlData: properties: data: type: object id: type: integer type: object - handler.debugStateElement: + types.DebugStateElement: properties: components: type: object @@ -155,7 +155,7 @@ paths: description: List of all entities schema: items: - $ref: '#/definitions/handler.debugStateElement' + $ref: '#/definitions/types.DebugStateElement' type: array summary: Retrieves a list of all entities in the game state /events: @@ -214,35 +214,6 @@ paths: schema: type: string summary: Executes a query - /query/game/{queryName}: - post: - consumes: - - application/json - description: Executes a query - parameters: - - description: Name of a registered query - in: path - name: queryName - required: true - type: string - - description: Query to be executed - in: body - name: queryBody - required: true - schema: - type: object - produces: - - application/json - responses: - "200": - description: Results of the executed query - schema: - type: object - "400": - description: Invalid request parameters - schema: - type: string - summary: Executes a query /query/receipts/list: post: consumes: diff --git a/cardinal/server/handler/debug.go b/cardinal/server/handler/debug.go index d00088065..b138e870d 100644 --- a/cardinal/server/handler/debug.go +++ b/cardinal/server/handler/debug.go @@ -4,8 +4,11 @@ import ( "github.com/gofiber/fiber/v2" servertypes "pkg.world.dev/world-engine/cardinal/server/types" + "pkg.world.dev/world-engine/cardinal/types" ) +type DebugStateResponse = types.DebugStateResponse + // GetDebugState godoc // // @Summary Retrieves a list of all entities in the game state @@ -15,7 +18,10 @@ import ( // @Router /debug/state [post] func GetDebugState(world servertypes.ProviderWorld) func(*fiber.Ctx) error { return func(ctx *fiber.Ctx) error { - result, eachClosureErr, searchEachErr := world.GetDebugState() + var result DebugStateResponse + var eachClosureErr error + var searchEachErr error + result, eachClosureErr, searchEachErr = world.GetDebugState() if eachClosureErr != nil { return eachClosureErr } diff --git a/cardinal/server/handler/tx.go b/cardinal/server/handler/tx.go index 68f06d12d..a2837aabc 100644 --- a/cardinal/server/handler/tx.go +++ b/cardinal/server/handler/tx.go @@ -104,9 +104,9 @@ func PostTransaction( // @Failure 400 {string} string "Invalid request parameter" // @Router /tx/game/{txName} [post] func PostGameTransaction( - provider servertypes.ProviderWorld, msgs map[string]map[string]types.Message, disableSigVerification bool, + world servertypes.ProviderWorld, msgs map[string]map[string]types.Message, disableSigVerification bool, ) func(*fiber.Ctx) error { - return PostTransaction(provider, msgs, disableSigVerification) + return PostTransaction(world, msgs, disableSigVerification) } // NOTE: duplication for cleaner swagger docs @@ -121,26 +121,26 @@ func PostGameTransaction( // @Failure 400 {string} string "Invalid request parameter" // @Router /tx/persona/create-persona [post] func PostPersonaTransaction( - provider servertypes.ProviderWorld, msgs map[string]map[string]types.Message, disableSigVerification bool, + world servertypes.ProviderWorld, msgs map[string]map[string]types.Message, disableSigVerification bool, ) func(*fiber.Ctx) error { - return PostTransaction(provider, msgs, disableSigVerification) + return PostTransaction(world, msgs, disableSigVerification) } -func lookupSignerAndValidateSignature(provider servertypes.ProviderWorld, signerAddress string, tx *Transaction) error { +func lookupSignerAndValidateSignature(world servertypes.ProviderWorld, signerAddress string, tx *Transaction) error { var err error if signerAddress == "" { - signerAddress, err = provider.GetSignerForPersonaTag(tx.PersonaTag, 0) + signerAddress, err = world.GetSignerForPersonaTag(tx.PersonaTag, 0) if err != nil { return fiber.NewError(fiber.StatusBadRequest, "could not get signer for persona: "+err.Error()) } } - if err = validateSignature(tx, signerAddress, provider.Namespace(), + if err = validateSignature(tx, signerAddress, world.Namespace(), tx.IsSystemTransaction()); err != nil { return fiber.NewError(fiber.StatusBadRequest, "failed to validate transaction: "+err.Error()) } // TODO(scott): this should be refactored; it should be the responsibility of the engine tx processor // to mark the nonce as used once it's included in the tick, not the server. - if err = provider.UseNonce(signerAddress, tx.Nonce); err != nil { + if err = world.UseNonce(signerAddress, tx.Nonce); err != nil { return fiber.NewError(fiber.StatusInternalServerError, "failed to use nonce: "+err.Error()) } return nil diff --git a/cardinal/server/handler/world.go b/cardinal/server/handler/world.go index 88e57b698..65c6f2637 100644 --- a/cardinal/server/handler/world.go +++ b/cardinal/server/handler/world.go @@ -11,6 +11,8 @@ import ( "pkg.world.dev/world-engine/cardinal/types/engine" ) +type GetWorldResponse = engine.GetWorldResponse + // GetWorld godoc // // @Summary Retrieves details of the game world @@ -50,7 +52,7 @@ func GetWorld( // Collecting the structure of all queries return func(ctx *fiber.Ctx) error { - return ctx.JSON(engine.GetWorldResponse{ + return ctx.JSON(GetWorldResponse{ Namespace: namespace, Components: comps, Messages: messagesFields, diff --git a/cardinal/server/server.go b/cardinal/server/server.go index 7e9083e84..2ee7c8e35 100644 --- a/cardinal/server/server.go +++ b/cardinal/server/server.go @@ -35,7 +35,7 @@ type Server struct { // New returns an HTTP server with handlers for all QueryTypes and MessageTypes. func New( - provider servertypes.ProviderWorld, + world servertypes.ProviderWorld, components []types.ComponentMetadata, messages []types.Message, opts ...Option, @@ -60,7 +60,7 @@ func New( app.Use(cors.New()) // Register routes - s.setupRoutes(provider, messages, components) + s.setupRoutes(world, messages, components) return s, nil } @@ -117,7 +117,7 @@ func (s *Server) Shutdown() error { // @consumes application/json // @produces application/json func (s *Server) setupRoutes( - provider servertypes.ProviderWorld, + world servertypes.ProviderWorld, messages []types.Message, components []types.ComponentMetadata, ) { @@ -144,23 +144,23 @@ func (s *Server) setupRoutes( s.app.Get("/events", handler.WebSocketEvents()) // Route: /world - s.app.Get("/world", handler.GetWorld(provider, components, messages, provider.Namespace())) + s.app.Get("/world", handler.GetWorld(world, components, messages, world.Namespace())) // Route: /... s.app.Get("/health", handler.GetHealth()) // Route: /query/... query := s.app.Group("/query") - query.Post("/receipts/list", handler.GetReceipts(provider)) - query.Post("/:group/:name", handler.PostQuery(provider)) + query.Post("/receipts/list", handler.GetReceipts(world)) + query.Post("/:group/:name", handler.PostQuery(world)) // Route: /tx/... tx := s.app.Group("/tx") - tx.Post("/:group/:name", handler.PostTransaction(provider, msgIndex, s.config.isSignatureVerificationDisabled)) + tx.Post("/:group/:name", handler.PostTransaction(world, msgIndex, s.config.isSignatureVerificationDisabled)) // Route: /cql - s.app.Post("/cql", handler.PostCQL(provider)) + s.app.Post("/cql", handler.PostCQL(world)) // Route: /debug/state - s.app.Post("/debug/state", handler.GetDebugState(provider)) + s.app.Post("/debug/state", handler.GetDebugState(world)) } From 2dd20ade32e9249ffc3b4edab3c9ec0cf61e1517 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Fri, 10 May 2024 11:33:36 -0700 Subject: [PATCH 32/76] remove old context file. --- cardinal/search.go | 6 ------ cardinal/types/engine/context.go | 37 -------------------------------- 2 files changed, 43 deletions(-) delete mode 100644 cardinal/types/engine/context.go diff --git a/cardinal/search.go b/cardinal/search.go index 2249edfbf..861d901f8 100644 --- a/cardinal/search.go +++ b/cardinal/search.go @@ -100,12 +100,6 @@ type searchBuilder interface { Entity(componentFilter filter.ComponentFilter) EntitySearch } -//revive:disable-next-line - -// Imported -// This section aggregates function from other packages such that they are easily accessible -// via cardinal. - // NewSearch is used to create a search object. // // Usage: diff --git a/cardinal/types/engine/context.go b/cardinal/types/engine/context.go deleted file mode 100644 index f59ea9113..000000000 --- a/cardinal/types/engine/context.go +++ /dev/null @@ -1,37 +0,0 @@ -package engine - -//go:generate mockgen -source=context.go -package mocks -destination=mocks/context.go -// type Context interface { -// // Timestamp returns the UNIX timestamp of the tick. -// Timestamp() uint64 -// // CurrentTick returns the current tick. -// CurrentTick() uint64 -// // Logger returns the logger that can be used to log messages from within system or query. -// Logger() *zerolog.Logger -// // EmitEvent emits an event that will be broadcast to all websocket subscribers. -// EmitEvent(map[string]any) error -// // EmitStringEvent emits a string event that will be broadcast to all websocket subscribers. -// // This method is provided for backwards compatability. EmitEvent should be used for most cases. -// EmitStringEvent(string) error -// // Namespace returns the namespace of the world. -// Namespace() string -// -// // For internal use. -// -// // setLogger is used to inject a new logger configuration to an engine context that is already created. -// setLogger(logger zerolog.Logger) -// addMessageError(id types.TxHash, err error) -// setMessageResult(id types.TxHash, a any) -// getComponentByName(name string) (types.ComponentMetadata, error) -// getMessageByType(mType reflect.Type) (types.Message, bool) -// getTransactionReceipt(id types.TxHash) (any, []error, bool) -// getSignerForPersonaTag(personaTag string, tick uint64) (addr string, err error) -// getTransactionReceiptsForTick(tick uint64) ([]receipt.Receipt, error) -// receiptHistorySize() uint64 -// addTransaction(id types.MessageID, v any, sig *sign.Transaction) (uint64, types.TxHash) -// isWorldReady() bool -// storeReader() gamestate.Reader -// storeManager() gamestate.Manager -// getTxPool() *txpool.TxPool -// isReadOnly() bool -//} From c3a6550ed2f21a4b96abf29b73f242dee9ad5f21 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Fri, 10 May 2024 13:56:45 -0700 Subject: [PATCH 33/76] make new query type private. --- cardinal/cardinal.go | 2 +- cardinal/query.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cardinal/cardinal.go b/cardinal/cardinal.go index cc92842ab..95ca031dc 100644 --- a/cardinal/cardinal.go +++ b/cardinal/cardinal.go @@ -141,7 +141,7 @@ func RegisterQuery[Request any, Reply any]( ) } - q, err := NewQueryType[Request, Reply](name, handler, opts...) + q, err := newQueryType[Request, Reply](name, handler, opts...) if err != nil { return err } diff --git a/cardinal/query.go b/cardinal/query.go index 9aa44598c..deb69370f 100644 --- a/cardinal/query.go +++ b/cardinal/query.go @@ -67,7 +67,7 @@ func WithCustomQueryGroup[Request, Reply any](group string) QueryOption[Request, } } -func NewQueryType[Request any, Reply any]( +func newQueryType[Request any, Reply any]( name string, handler func(wCtx Context, req *Request) (*Reply, error), opts ...QueryOption[Request, Reply], From 62750f96931f593deb52ac4b7214c81aa6a8df75 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Fri, 10 May 2024 14:08:45 -0700 Subject: [PATCH 34/76] privatize handQuery and handleQueryRaw --- cardinal/errors_test.go | 4 ++-- cardinal/persona/persona_test.go | 13 +++++++------ cardinal/query.go | 8 ++++---- cardinal/query_manager.go | 2 +- cardinal/query_test.go | 6 +++--- cardinal/util.go | 4 ++++ cardinal/world.go | 2 +- 7 files changed, 22 insertions(+), 17 deletions(-) diff --git a/cardinal/errors_test.go b/cardinal/errors_test.go index 2326328e7..caf5408c7 100644 --- a/cardinal/errors_test.go +++ b/cardinal/errors_test.go @@ -309,7 +309,7 @@ func TestQueriesDoNotPanicOnComponentHasNotBeenRegistered(t *testing.T) { assert.Check(t, err == nil) readOnlyWorldCtx := cardinal.NewReadOnlyWorldContext(world) - _, err = query.HandleQuery(readOnlyWorldCtx, QueryRequest{}) + _, err = cardinal.HandleQuery(readOnlyWorldCtx, query, QueryRequest{}) // Each test case is meant to generate a "ErrComponentNotRegistered" error assert.Check(t, errors.Is(err, component.ErrComponentNotRegistered), "expected a component not registered error, got %v", err) @@ -355,6 +355,6 @@ func TestGetComponentInQueryDoesNotPanicOnRedisError(t *testing.T) { assert.Check(t, recover() == nil, "expected no panic in a query") }() - _, err = query.HandleQuery(readOnlyWorldCtx, QueryRequest{}) + _, err = cardinal.HandleQuery(readOnlyWorldCtx, query, QueryRequest{}) assert.ErrorContains(t, err, "connection refused", "expected a connection error") } diff --git a/cardinal/persona/persona_test.go b/cardinal/persona/persona_test.go index f25ef5c53..1bf337b16 100644 --- a/cardinal/persona/persona_test.go +++ b/cardinal/persona/persona_test.go @@ -236,7 +236,7 @@ func TestQuerySigner(t *testing.T) { query, err := world.GetQueryByName("signer") assert.NilError(t, err) - res, err := query.HandleQuery(cardinal.NewReadOnlyWorldContext(world), &cardinal.PersonaSignerQueryRequest{ + res, err := cardinal.HandleQuery(cardinal.NewReadOnlyWorldContext(world), query, &cardinal.PersonaSignerQueryRequest{ PersonaTag: personaTag, }) assert.NilError(t, err) @@ -254,7 +254,7 @@ func TestQuerySignerAvailable(t *testing.T) { query, err := world.GetQueryByName("signer") assert.NilError(t, err) - res, err := query.HandleQuery(cardinal.NewReadOnlyWorldContext(world), &cardinal.PersonaSignerQueryRequest{ + res, err := cardinal.HandleQuery(cardinal.NewReadOnlyWorldContext(world), query, &cardinal.PersonaSignerQueryRequest{ PersonaTag: "some-random-nonexistent-persona-tag", }) assert.NilError(t, err) @@ -271,10 +271,11 @@ func TestQuerySignerUnknown(t *testing.T) { query, err := engine.GetQueryByName("signer") assert.NilError(t, err) - res, err := query.HandleQuery(cardinal.NewReadOnlyWorldContext(engine), &cardinal.PersonaSignerQueryRequest{ - PersonaTag: "doesnt_matter", - Tick: engine.CurrentTick(), - }) + res, err := cardinal.HandleQuery(cardinal.NewReadOnlyWorldContext(engine), query, + &cardinal.PersonaSignerQueryRequest{ + PersonaTag: "doesnt_matter", + Tick: engine.CurrentTick(), + }) assert.NilError(t, err) response, ok := res.(*cardinal.PersonaSignerQueryResponse) diff --git a/cardinal/query.go b/cardinal/query.go index deb69370f..5e0eaec67 100644 --- a/cardinal/query.go +++ b/cardinal/query.go @@ -21,10 +21,10 @@ type Query interface { // Group returns the group of the query. Group() string // HandleQuery handles queries with concrete types, rather than encoded bytes. - HandleQuery(Context, any) (any, error) + handleQuery(Context, any) (any, error) // HandleQueryRaw is given a reference to the engine, json encoded bytes that represent a query request // and is expected to return a json encoded response struct. - HandleQueryRaw(Context, []byte) ([]byte, error) + handleQueryRaw(Context, []byte) ([]byte, error) // DecodeEVMRequest decodes bytes originating from the evm into the request type, which will be ABI encoded. DecodeEVMRequest([]byte) (any, error) // EncodeEVMReply encodes the reply as an abi encoded struct. @@ -116,7 +116,7 @@ func (r *queryType[req, rep]) Group() string { return r.group } -func (r *queryType[req, rep]) HandleQuery(wCtx Context, a any) (any, error) { +func (r *queryType[req, rep]) handleQuery(wCtx Context, a any) (any, error) { var request *req if reflect.TypeOf(a).Kind() == reflect.Pointer { ptrRequest, ok := a.(*req) @@ -135,7 +135,7 @@ func (r *queryType[req, rep]) HandleQuery(wCtx Context, a any) (any, error) { return reply, err } -func (r *queryType[req, rep]) HandleQueryRaw(wCtx Context, bz []byte) ([]byte, error) { +func (r *queryType[req, rep]) handleQueryRaw(wCtx Context, bz []byte) ([]byte, error) { request := new(req) err := json.Unmarshal(bz, request) if err != nil { diff --git a/cardinal/query_manager.go b/cardinal/query_manager.go index 41244b814..108c9f684 100644 --- a/cardinal/query_manager.go +++ b/cardinal/query_manager.go @@ -73,7 +73,7 @@ func (w *World) QueryHandler(name string, group string, bz []byte) ([]byte, erro return nil, eris.Errorf("query with name %s not found", name) } wCtx := NewReadOnlyWorldContext(w) - return query.HandleQueryRaw(wCtx, bz) + return query.handleQueryRaw(wCtx, bz) } // GetQueryByName returns a query corresponding to its name. diff --git a/cardinal/query_test.go b/cardinal/query_test.go index 19678fd7b..102eff25d 100644 --- a/cardinal/query_test.go +++ b/cardinal/query_test.go @@ -101,17 +101,17 @@ func TestQueryExample(t *testing.T) { q, err := world.GetQueryByName("query_health") assert.NilError(t, err) - resp, err := q.HandleQuery(worldCtx, QueryHealthRequest{1_000_000}) + resp, err := cardinal.HandleQuery(worldCtx, q, QueryHealthRequest{1_000_000}) assert.NilError(t, err) assert.Equal(t, 0, len(resp.(*QueryHealthResponse).IDs)) // All entities should have health over -100 - resp, err = q.HandleQuery(worldCtx, QueryHealthRequest{-100}) + resp, err = cardinal.HandleQuery(worldCtx, q, QueryHealthRequest{-100}) assert.NilError(t, err) assert.Equal(t, 100, len(resp.(*QueryHealthResponse).IDs)) // Exactly 10 entities should have health at or above 90 - resp, err = q.HandleQuery(worldCtx, QueryHealthRequest{90}) + resp, err = cardinal.HandleQuery(worldCtx, q, QueryHealthRequest{90}) assert.NilError(t, err) assert.Equal(t, 10, len(resp.(*QueryHealthResponse).IDs)) } diff --git a/cardinal/util.go b/cardinal/util.go index a7b92c7a7..50a6a1182 100644 --- a/cardinal/util.go +++ b/cardinal/util.go @@ -83,3 +83,7 @@ func GetStoreManagerFromContext(wCtx Context) gamestate.Manager { func GetComponentByNameFromContext(wCtx Context, name string) (types.ComponentMetadata, error) { return wCtx.getComponentByName(name) } + +func HandleQuery(wCtx Context, query Query, a any) (any, error) { + return query.handleQuery(wCtx, a) +} diff --git a/cardinal/world.go b/cardinal/world.go index a5d1b1221..4f6984040 100644 --- a/cardinal/world.go +++ b/cardinal/world.go @@ -624,7 +624,7 @@ func (w *World) HandleEVMQuery(name string, abiRequest []byte) ([]byte, error) { return nil, err } - reply, err := qry.HandleQuery(NewReadOnlyWorldContext(w), req) + reply, err := qry.handleQuery(NewReadOnlyWorldContext(w), req) if err != nil { return nil, err } From 206fa4e711780aef5d1776ca7406af4b75763d53 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Fri, 10 May 2024 14:27:29 -0700 Subject: [PATCH 35/76] review changes. --- cardinal/errors_test.go | 2 +- cardinal/query.go | 8 +++----- cardinal/query_manager.go | 34 +++++++++++++++++----------------- cardinal/util.go | 2 +- 4 files changed, 22 insertions(+), 24 deletions(-) diff --git a/cardinal/errors_test.go b/cardinal/errors_test.go index caf5408c7..d83d52a8e 100644 --- a/cardinal/errors_test.go +++ b/cardinal/errors_test.go @@ -350,7 +350,7 @@ func TestGetComponentInQueryDoesNotPanicOnRedisError(t *testing.T) { tf.Redis.Close() readOnlyWorldCtx := cardinal.NewReadOnlyWorldContext(world) - // This will fail with a redis connection error, and since we're in a Query, we should NOT panic + // This will fail with a redis connection error, and since we're in a query, we should NOT panic defer func() { assert.Check(t, recover() == nil, "expected no panic in a query") }() diff --git a/cardinal/query.go b/cardinal/query.go index 5e0eaec67..7d0970cd4 100644 --- a/cardinal/query.go +++ b/cardinal/query.go @@ -11,11 +11,9 @@ import ( "pkg.world.dev/world-engine/cardinal/types" ) -var _ Query = &queryType[struct{}, struct{}]{} +var _ query = &queryType[struct{}, struct{}]{} -type QueryHandler = func(name string, group string, bz []byte) ([]byte, error) - -type Query interface { +type query interface { // Name returns the name of the query. Name() string // Group returns the group of the query. @@ -71,7 +69,7 @@ func newQueryType[Request any, Reply any]( name string, handler func(wCtx Context, req *Request) (*Reply, error), opts ...QueryOption[Request, Reply], -) (Query, error) { +) (query, error) { err := validateQuery[Request, Reply](name, handler) if err != nil { return nil, err diff --git a/cardinal/query_manager.go b/cardinal/query_manager.go index 108c9f684..05bfacc03 100644 --- a/cardinal/query_manager.go +++ b/cardinal/query_manager.go @@ -5,31 +5,31 @@ import ( ) type QueryManager interface { - RegisterQuery(name string, query Query) error - GetRegisteredQueries() []Query - GetQueryByName(name string) (Query, error) + RegisterQuery(name string, query query) error + GetRegisteredQueries() []query + GetQueryByName(name string) (query, error) BuildQueryIndex(world *World) - GetQueryIndex() map[string]map[string]Query + GetQueryIndex() map[string]map[string]query } type queryManager struct { - registeredQueries map[string]Query - queryIndex map[string]map[string]Query + registeredQueries map[string]query + queryIndex map[string]map[string]query } func newQueryManager() QueryManager { return &queryManager{ - registeredQueries: make(map[string]Query), + registeredQueries: make(map[string]query), } } -func (m *queryManager) GetQueryIndex() map[string]map[string]Query { +func (m *queryManager) GetQueryIndex() map[string]map[string]query { return m.queryIndex } // RegisterQuery registers a query with the query manager. // There can only be one query with a given name. -func (m *queryManager) RegisterQuery(name string, query Query) error { +func (m *queryManager) RegisterQuery(name string, query query) error { // Check that the query is not already registered if err := m.isQueryNameUnique(name); err != nil { return err @@ -41,8 +41,8 @@ func (m *queryManager) RegisterQuery(name string, query Query) error { } // GetRegisteredQueries returns all the registered queries. -func (m *queryManager) GetRegisteredQueries() []Query { - registeredQueries := make([]Query, 0, len(m.registeredQueries)) +func (m *queryManager) GetRegisteredQueries() []query { + registeredQueries := make([]query, 0, len(m.registeredQueries)) for _, query := range m.registeredQueries { registeredQueries = append(registeredQueries, query) } @@ -51,14 +51,14 @@ func (m *queryManager) GetRegisteredQueries() []Query { func (m *queryManager) BuildQueryIndex(world *World) { queries := world.GetRegisteredQueries() - m.queryIndex = make(map[string]map[string]Query) + m.queryIndex = make(map[string]map[string]query) // Create query index - for _, query := range queries { + for _, q := range queries { // Initialize inner map if it doesn't exist - if _, ok := m.queryIndex[query.Group()]; !ok { - m.queryIndex[query.Group()] = make(map[string]Query) + if _, ok := m.queryIndex[q.Group()]; !ok { + m.queryIndex[q.Group()] = make(map[string]query) } - m.queryIndex[query.Group()][query.Name()] = query + m.queryIndex[q.Group()][q.Name()] = q } } func (w *World) QueryHandler(name string, group string, bz []byte) ([]byte, error) { @@ -77,7 +77,7 @@ func (w *World) QueryHandler(name string, group string, bz []byte) ([]byte, erro } // GetQueryByName returns a query corresponding to its name. -func (m *queryManager) GetQueryByName(name string) (Query, error) { +func (m *queryManager) GetQueryByName(name string) (query, error) { query, ok := m.registeredQueries[name] if !ok { return nil, eris.Errorf("query %q is not registered", name) diff --git a/cardinal/util.go b/cardinal/util.go index 50a6a1182..6221537b8 100644 --- a/cardinal/util.go +++ b/cardinal/util.go @@ -84,6 +84,6 @@ func GetComponentByNameFromContext(wCtx Context, name string) (types.ComponentMe return wCtx.getComponentByName(name) } -func HandleQuery(wCtx Context, query Query, a any) (any, error) { +func HandleQuery(wCtx Context, query query, a any) (any, error) { return query.handleQuery(wCtx, a) } From 16635c071732dc01fc47f31bdb6e105281bf256d Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Fri, 10 May 2024 14:36:28 -0700 Subject: [PATCH 36/76] change GetDebugState to GetState --- cardinal/server/handler/debug.go | 4 ++-- cardinal/server/server.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cardinal/server/handler/debug.go b/cardinal/server/handler/debug.go index b138e870d..4f49e9414 100644 --- a/cardinal/server/handler/debug.go +++ b/cardinal/server/handler/debug.go @@ -9,14 +9,14 @@ import ( type DebugStateResponse = types.DebugStateResponse -// GetDebugState godoc +// GetState godoc // // @Summary Retrieves a list of all entities in the game state // @Description Retrieves a list of all entities in the game state // @Produce application/json // @Success 200 {object} DebugStateResponse "List of all entities" // @Router /debug/state [post] -func GetDebugState(world servertypes.ProviderWorld) func(*fiber.Ctx) error { +func GetState(world servertypes.ProviderWorld) func(*fiber.Ctx) error { return func(ctx *fiber.Ctx) error { var result DebugStateResponse var eachClosureErr error diff --git a/cardinal/server/server.go b/cardinal/server/server.go index 2ee7c8e35..5b5236577 100644 --- a/cardinal/server/server.go +++ b/cardinal/server/server.go @@ -162,5 +162,5 @@ func (s *Server) setupRoutes( s.app.Post("/cql", handler.PostCQL(world)) // Route: /debug/state - s.app.Post("/debug/state", handler.GetDebugState(world)) + s.app.Post("/debug/state", handler.GetState(world)) } From 4b0c96796dc94388bfa38ab32bcf6e94c0aaf6ca Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Fri, 10 May 2024 14:37:57 -0700 Subject: [PATCH 37/76] rename context to WorldContext --- cardinal/benchmark/benchmark_test.go | 2 +- cardinal/cardinal.go | 22 +++++----- cardinal/cardinal_test.go | 30 ++++++------- cardinal/composedsearch.go | 36 ++++++++-------- cardinal/ecs_test.go | 2 +- cardinal/engine_test.go | 18 ++++---- cardinal/errors_test.go | 58 +++++++++++++------------- cardinal/example_messagetype_test.go | 2 +- cardinal/filtercomponent.go | 8 ++-- cardinal/log/log_test.go | 4 +- cardinal/message.go | 10 ++--- cardinal/persona_signer.go | 2 +- cardinal/plugin_persona.go | 6 +-- cardinal/query.go | 14 +++---- cardinal/query_test.go | 8 ++-- cardinal/search.go | 24 +++++------ cardinal/search_test.go | 6 +-- cardinal/server/event_test.go | 10 ++--- cardinal/server/receipts_test.go | 2 +- cardinal/server/server_test.go | 6 +-- cardinal/state_test.go | 4 +- cardinal/system.go | 6 +-- cardinal/system_test.go | 10 ++--- cardinal/util.go | 12 +++--- cardinal/world.go | 2 +- cardinal/world_context.go | 10 ++--- cardinal/world_persona_test.go | 2 +- cardinal/world_test.go | 26 ++++++------ e2e/testgames/game/query/location.go | 2 +- e2e/testgames/game/sys/error.go | 2 +- e2e/testgames/game/sys/join.go | 2 +- e2e/testgames/game/sys/move.go | 2 +- e2e/testgames/gamebenchmark/sys/sys.go | 8 ++-- 33 files changed, 179 insertions(+), 179 deletions(-) diff --git a/cardinal/benchmark/benchmark_test.go b/cardinal/benchmark/benchmark_test.go index 4327751b6..7d249590f 100644 --- a/cardinal/benchmark/benchmark_test.go +++ b/cardinal/benchmark/benchmark_test.go @@ -34,7 +34,7 @@ func setupWorld(t testing.TB, numOfEntities int, enableHealthSystem bool) *testu if enableHealthSystem { err := cardinal.RegisterSystems( world, - func(wCtx cardinal.Context) error { + func(wCtx cardinal.WorldContext) error { q := cardinal.NewSearch().Entity(filter.Contains(filter.Component[Health]())) err := q.Each(wCtx, func(id types.EntityID) bool { diff --git a/cardinal/cardinal.go b/cardinal/cardinal.go index 95ca031dc..14b1996e1 100644 --- a/cardinal/cardinal.go +++ b/cardinal/cardinal.go @@ -32,7 +32,7 @@ var ( // return true // })) -func FilterFunction[T types.Component](f func(comp T) bool) func(ctx Context, id types.EntityID) (bool, error) { +func FilterFunction[T types.Component](f func(comp T) bool) func(ctx WorldContext, id types.EntityID) (bool, error) { return ComponentFilter[T](f) } @@ -87,7 +87,7 @@ func MustRegisterComponent[T types.Component](w *World) { } } -func EachMessage[In any, Out any](wCtx Context, fn func(TxData[In]) (Out, error)) error { +func EachMessage[In any, Out any](wCtx WorldContext, fn func(TxData[In]) (Out, error)) error { var msg MessageType[In, Out] msgType := reflect.TypeOf(msg) tempRes, ok := wCtx.getMessageByType(msgType) @@ -130,7 +130,7 @@ func RegisterMessage[In any, Out any](world *World, name string, opts ...Message func RegisterQuery[Request any, Reply any]( w *World, name string, - handler func(wCtx Context, req *Request) (*Reply, error), + handler func(wCtx WorldContext, req *Request) (*Reply, error), opts ...QueryOption[Request, Reply], ) (err error) { if w.worldStage.Current() != worldstage.Init { @@ -153,7 +153,7 @@ func RegisterQuery[Request any, Reply any]( // Create creates a single entity in the world, and returns the id of the newly created entity. // At least 1 component must be provided. -func Create(wCtx Context, components ...types.Component) (_ types.EntityID, err error) { +func Create(wCtx WorldContext, components ...types.Component) (_ types.EntityID, err error) { // We don't handle panics here because we let CreateMany handle it for us entityIDs, err := CreateMany(wCtx, 1, components...) if err != nil { @@ -164,7 +164,7 @@ func Create(wCtx Context, components ...types.Component) (_ types.EntityID, err // CreateMany creates multiple entities in the world, and returns the slice of ids for the newly created // entities. At least 1 component must be provided. -func CreateMany(wCtx Context, num int, components ...types.Component) (entityIDs []types.EntityID, err error) { +func CreateMany(wCtx WorldContext, num int, components ...types.Component) (entityIDs []types.EntityID, err error) { defer func() { panicOnFatalError(wCtx, err) }() // Error if the context is read only @@ -212,7 +212,7 @@ func CreateMany(wCtx Context, num int, components ...types.Component) (entityIDs } // SetComponent sets component data to the entity. -func SetComponent[T types.Component](wCtx Context, id types.EntityID, component *T) (err error) { +func SetComponent[T types.Component](wCtx WorldContext, id types.EntityID, component *T) (err error) { defer func() { panicOnFatalError(wCtx, err) }() // Error if the context is read only @@ -244,7 +244,7 @@ func SetComponent[T types.Component](wCtx Context, id types.EntityID, component } // GetComponent returns component data from the entity. -func GetComponent[T types.Component](wCtx Context, id types.EntityID) (comp *T, err error) { +func GetComponent[T types.Component](wCtx WorldContext, id types.EntityID) (comp *T, err error) { defer func() { panicOnFatalError(wCtx, err) }() // Get the component metadata @@ -274,7 +274,7 @@ func GetComponent[T types.Component](wCtx Context, id types.EntityID) (comp *T, return comp, nil } -func UpdateComponent[T types.Component](wCtx Context, id types.EntityID, fn func(*T) *T) (err error) { +func UpdateComponent[T types.Component](wCtx WorldContext, id types.EntityID, fn func(*T) *T) (err error) { defer func() { panicOnFatalError(wCtx, err) }() // Error if the context is read only @@ -300,7 +300,7 @@ func UpdateComponent[T types.Component](wCtx Context, id types.EntityID, fn func return nil } -func AddComponentTo[T types.Component](wCtx Context, id types.EntityID) (err error) { +func AddComponentTo[T types.Component](wCtx WorldContext, id types.EntityID) (err error) { defer func() { panicOnFatalError(wCtx, err) }() // Error if the context is read only @@ -325,7 +325,7 @@ func AddComponentTo[T types.Component](wCtx Context, id types.EntityID) (err err } // RemoveComponentFrom removes a component from an entity. -func RemoveComponentFrom[T types.Component](wCtx Context, id types.EntityID) (err error) { +func RemoveComponentFrom[T types.Component](wCtx WorldContext, id types.EntityID) (err error) { defer func() { panicOnFatalError(wCtx, err) }() // Error if the context is read only @@ -350,7 +350,7 @@ func RemoveComponentFrom[T types.Component](wCtx Context, id types.EntityID) (er } // Remove removes the given Entity from the world. -func Remove(wCtx Context, id types.EntityID) (err error) { +func Remove(wCtx WorldContext, id types.EntityID) (err error) { defer func() { panicOnFatalError(wCtx, err) }() // Error if the context is read only diff --git a/cardinal/cardinal_test.go b/cardinal/cardinal_test.go index a8319adee..bebe95afc 100644 --- a/cardinal/cardinal_test.go +++ b/cardinal/cardinal_test.go @@ -69,7 +69,7 @@ func TestForEachTransaction(t *testing.T) { someMsgName := "some_msg" assert.NilError(t, cardinal.RegisterMessage[SomeMsgRequest, SomeMsgResponse](world, someMsgName)) - err := cardinal.RegisterSystems(world, func(wCtx cardinal.Context) error { + err := cardinal.RegisterSystems(world, func(wCtx cardinal.WorldContext) error { return cardinal.EachMessage[SomeMsgRequest, SomeMsgResponse](wCtx, func(t cardinal.TxData[SomeMsgRequest]) (result SomeMsgResponse, err error) { if t.Msg.GenerateError { @@ -145,7 +145,7 @@ func TestSystemsAreExecutedDuringGameTick(t *testing.T) { err := cardinal.RegisterSystems( world, - func(wCtx cardinal.Context) error { + func(wCtx cardinal.WorldContext) error { search := cardinal.NewSearch().Entity(filter.Exact(filter.Component[CounterComponent]())) id := search.MustFirst(wCtx) return cardinal.UpdateComponent[CounterComponent]( @@ -179,7 +179,7 @@ func TestTransactionAreAppliedToSomeEntities(t *testing.T) { err := cardinal.RegisterSystems( world, - func(wCtx cardinal.Context) error { + func(wCtx cardinal.WorldContext) error { return cardinal.EachMessage[*ModifyScoreMsg, *EmptyMsgResult](wCtx, func(msData cardinal.TxData[*ModifyScoreMsg]) (*EmptyMsgResult, error) { ms := msData.Msg @@ -255,7 +255,7 @@ func TestAddToPoolDuringTickDoesNotTimeout(t *testing.T) { // to verify that the addition of more transactions doesn't block. err := cardinal.RegisterSystems( world, - func(cardinal.Context) error { + func(cardinal.WorldContext) error { <-inSystemCh <-inSystemCh return nil @@ -323,7 +323,7 @@ func TestTransactionsAreExecutedAtNextTick(t *testing.T) { // commands mid-tick. err := cardinal.RegisterSystems( world, - func(wCtx cardinal.Context) error { + func(wCtx cardinal.WorldContext) error { modScoreMsg, err := cardinal.GetMessage[*ModifyScoreMsg, *EmptyMsgResult](wCtx) if err != nil { return err @@ -337,7 +337,7 @@ func TestTransactionsAreExecutedAtNextTick(t *testing.T) { err = cardinal.RegisterSystems( world, - func(wCtx cardinal.Context) error { + func(wCtx cardinal.WorldContext) error { modScoreMsg, err := cardinal.GetMessage[*ModifyScoreMsg, *EmptyMsgResult](wCtx) if err != nil { return err @@ -441,7 +441,7 @@ func TestCanGetTransactionErrorsAndResults(t *testing.T) { err := cardinal.RegisterSystems( world, - func(wCtx cardinal.Context) error { + func(wCtx cardinal.WorldContext) error { // This new In function returns a triplet of information: // 1) The transaction input // 2) An EntityID that uniquely identifies this specific transaction @@ -504,7 +504,7 @@ func TestSystemCanFindErrorsFromEarlierSystem(t *testing.T) { systemCalls := 0 err := cardinal.RegisterSystems( world, - func(wCtx cardinal.Context) error { + func(wCtx cardinal.WorldContext) error { systemCalls++ numTx, err := cardinal.GetMessage[MsgIn, MsgOut](wCtx) if err != nil { @@ -523,7 +523,7 @@ func TestSystemCanFindErrorsFromEarlierSystem(t *testing.T) { err = cardinal.RegisterSystems( world, - func(wCtx cardinal.Context) error { + func(wCtx cardinal.WorldContext) error { systemCalls++ numTx, err := cardinal.GetMessage[MsgIn, MsgOut](wCtx) if err != nil { @@ -566,7 +566,7 @@ func TestSystemCanClobberTransactionResult(t *testing.T) { secondResult := MsgOut{5678} err := cardinal.RegisterSystems( world, - func(wCtx cardinal.Context) error { + func(wCtx cardinal.WorldContext) error { systemCalls++ numTx, err := cardinal.GetMessage[MsgIn, MsgOut](wCtx) assert.NilError(t, err) @@ -583,7 +583,7 @@ func TestSystemCanClobberTransactionResult(t *testing.T) { err = cardinal.RegisterSystems( world, - func(wCtx cardinal.Context) error { + func(wCtx cardinal.WorldContext) error { systemCalls++ numTx, err := cardinal.GetMessage[MsgIn, MsgOut](wCtx) if err != nil { @@ -626,7 +626,7 @@ func TestTransactionExample(t *testing.T) { assert.NilError(t, cardinal.RegisterComponent[Health](world)) msgName := "add_health" assert.NilError(t, cardinal.RegisterMessage[AddHealthToEntityTx, AddHealthToEntityResult](world, msgName)) - err := cardinal.RegisterSystems(world, func(wCtx cardinal.Context) error { + err := cardinal.RegisterSystems(world, func(wCtx cardinal.WorldContext) error { // test "In" method addHealthToEntity, err := cardinal.GetMessage[AddHealthToEntityTx, AddHealthToEntityResult](wCtx) if err != nil { @@ -743,7 +743,7 @@ func TestCanQueryInsideSystem(t *testing.T) { assert.NilError(t, cardinal.RegisterComponent[Foo](world)) gotNumOfEntities := 0 - err := cardinal.RegisterSystems(world, func(wCtx cardinal.Context) error { + err := cardinal.RegisterSystems(world, func(wCtx cardinal.WorldContext) error { err := cardinal.NewSearch().Entity(filter.Exact(filter.Component[Foo]())).Each(wCtx, func(types.EntityID) bool { gotNumOfEntities++ return true @@ -767,7 +767,7 @@ func TestCanGetTimestampFromWorldContext(t *testing.T) { var ts uint64 tf := testutils.NewTestFixture(t, nil) world := tf.World - err := cardinal.RegisterSystems(world, func(context cardinal.Context) error { + err := cardinal.RegisterSystems(world, func(context cardinal.WorldContext) error { ts = context.Timestamp() return nil }) @@ -788,7 +788,7 @@ func TestShutdownViaSignal(t *testing.T) { httpBaseURL := "http://" + addr assert.NilError(t, cardinal.RegisterComponent[Foo](world)) wantNumOfEntities := 10 - err := cardinal.RegisterInitSystems(world, func(wCtx cardinal.Context) error { + err := cardinal.RegisterInitSystems(world, func(wCtx cardinal.WorldContext) error { _, err := cardinal.CreateMany(wCtx, wantNumOfEntities/2, Foo{}) if err != nil { return err diff --git a/cardinal/composedsearch.go b/cardinal/composedsearch.go index c95410379..d81b15ac7 100644 --- a/cardinal/composedsearch.go +++ b/cardinal/composedsearch.go @@ -19,7 +19,7 @@ type NotSearch struct { search Searchable } -func (orSearch *OrSearch) evaluateSearch(eCtx Context) []types.ArchetypeID { +func (orSearch *OrSearch) evaluateSearch(eCtx WorldContext) []types.ArchetypeID { acc := make([]types.ArchetypeID, 0) for _, search := range orSearch.searches { acc = append(acc, search.evaluateSearch(eCtx)...) @@ -27,7 +27,7 @@ func (orSearch *OrSearch) evaluateSearch(eCtx Context) []types.ArchetypeID { return acc } -func (orSearch *OrSearch) Each(eCtx Context, callback CallbackFn) error { +func (orSearch *OrSearch) Each(eCtx WorldContext, callback CallbackFn) error { // deduplicate idCount := make(map[types.EntityID]int) for _, search := range orSearch.searches { @@ -56,7 +56,7 @@ func (orSearch *OrSearch) Each(eCtx Context, callback CallbackFn) error { return nil } -func (orSearch *OrSearch) Collect(eCtx Context) ([]types.EntityID, error) { +func (orSearch *OrSearch) Collect(eCtx WorldContext) ([]types.EntityID, error) { // deduplicate idExists := make(map[types.EntityID]bool) res := make([]types.EntityID, 0) @@ -79,7 +79,7 @@ func (orSearch *OrSearch) Collect(eCtx Context) ([]types.EntityID, error) { return res, nil } -func (orSearch *OrSearch) First(eCtx Context) (types.EntityID, error) { +func (orSearch *OrSearch) First(eCtx WorldContext) (types.EntityID, error) { ids, err := orSearch.Collect(eCtx) if err != nil { return 0, err @@ -90,7 +90,7 @@ func (orSearch *OrSearch) First(eCtx Context) (types.EntityID, error) { return ids[0], nil } -func (orSearch *OrSearch) MustFirst(eCtx Context) types.EntityID { +func (orSearch *OrSearch) MustFirst(eCtx WorldContext) types.EntityID { id, err := orSearch.First(eCtx) if err != nil { panic("no search results") @@ -98,7 +98,7 @@ func (orSearch *OrSearch) MustFirst(eCtx Context) types.EntityID { return id } -func (orSearch *OrSearch) Count(eCtx Context) (int, error) { +func (orSearch *OrSearch) Count(eCtx WorldContext) (int, error) { ids, err := orSearch.Collect(eCtx) if err != nil { return 0, err @@ -106,7 +106,7 @@ func (orSearch *OrSearch) Count(eCtx Context) (int, error) { return len(ids), nil } -func (andSearch *AndSearch) Each(eCtx Context, callback CallbackFn) error { +func (andSearch *AndSearch) Each(eCtx WorldContext, callback CallbackFn) error { // count idCount := make(map[types.EntityID]int) for _, search := range andSearch.searches { @@ -139,7 +139,7 @@ func (andSearch *AndSearch) Each(eCtx Context, callback CallbackFn) error { return nil } -func (andSearch *AndSearch) Collect(eCtx Context) ([]types.EntityID, error) { +func (andSearch *AndSearch) Collect(eCtx WorldContext) ([]types.EntityID, error) { // filter results := make([]types.EntityID, 0) err := andSearch.Each(eCtx, func(id types.EntityID) bool { @@ -156,7 +156,7 @@ func (andSearch *AndSearch) Collect(eCtx Context) ([]types.EntityID, error) { return results, nil } -func (andSearch *AndSearch) First(eCtx Context) (types.EntityID, error) { +func (andSearch *AndSearch) First(eCtx WorldContext) (types.EntityID, error) { ids, err := andSearch.Collect(eCtx) if err != nil { return 0, err @@ -167,7 +167,7 @@ func (andSearch *AndSearch) First(eCtx Context) (types.EntityID, error) { return ids[0], nil } -func (andSearch *AndSearch) MustFirst(eCtx Context) types.EntityID { +func (andSearch *AndSearch) MustFirst(eCtx WorldContext) types.EntityID { id, err := andSearch.First(eCtx) if err != nil { panic("No search results") @@ -175,7 +175,7 @@ func (andSearch *AndSearch) MustFirst(eCtx Context) types.EntityID { return id } -func (andSearch *AndSearch) Count(eCtx Context) (int, error) { +func (andSearch *AndSearch) Count(eCtx WorldContext) (int, error) { ids, err := andSearch.Collect(eCtx) if err != nil { return 0, err @@ -183,7 +183,7 @@ func (andSearch *AndSearch) Count(eCtx Context) (int, error) { return len(ids), nil } -func (andSearch *AndSearch) evaluateSearch(eCtx Context) []types.ArchetypeID { +func (andSearch *AndSearch) evaluateSearch(eCtx WorldContext) []types.ArchetypeID { searchCounts := make(map[types.ArchetypeID]int) for _, search := range andSearch.searches { ids := search.evaluateSearch(eCtx) @@ -200,7 +200,7 @@ func (andSearch *AndSearch) evaluateSearch(eCtx Context) []types.ArchetypeID { return acc } -func (notSearch *NotSearch) Each(eCtx Context, callback CallbackFn) error { +func (notSearch *NotSearch) Each(eCtx WorldContext, callback CallbackFn) error { // sort ids, err := notSearch.Collect(eCtx) if err != nil { @@ -217,7 +217,7 @@ func (notSearch *NotSearch) Each(eCtx Context, callback CallbackFn) error { return nil } -func (notSearch *NotSearch) Collect(eCtx Context) ([]types.EntityID, error) { +func (notSearch *NotSearch) Collect(eCtx WorldContext) ([]types.EntityID, error) { // Get all ids allsearch := NewSearch().Entity(filter.All()) allids, err := allsearch.Collect(eCtx) @@ -249,7 +249,7 @@ func (notSearch *NotSearch) Collect(eCtx Context) ([]types.EntityID, error) { return result, nil } -func (notSearch *NotSearch) First(eCtx Context) (types.EntityID, error) { +func (notSearch *NotSearch) First(eCtx WorldContext) (types.EntityID, error) { ids, err := notSearch.Collect(eCtx) if err != nil { return 0, err @@ -260,7 +260,7 @@ func (notSearch *NotSearch) First(eCtx Context) (types.EntityID, error) { return ids[0], nil } -func (notSearch *NotSearch) MustFirst(eCtx Context) types.EntityID { +func (notSearch *NotSearch) MustFirst(eCtx WorldContext) types.EntityID { id, err := notSearch.First(eCtx) if err != nil { panic("No search results") @@ -268,7 +268,7 @@ func (notSearch *NotSearch) MustFirst(eCtx Context) types.EntityID { return id } -func (notSearch *NotSearch) Count(eCtx Context) (int, error) { +func (notSearch *NotSearch) Count(eCtx WorldContext) (int, error) { ids, err := notSearch.Collect(eCtx) if err != nil { return 0, err @@ -276,7 +276,7 @@ func (notSearch *NotSearch) Count(eCtx Context) (int, error) { return len(ids), nil } -func (notSearch *NotSearch) evaluateSearch(eCtx Context) []types.ArchetypeID { +func (notSearch *NotSearch) evaluateSearch(eCtx WorldContext) []types.ArchetypeID { searchBuilder := NewSearch() allResults := searchBuilder.Entity(filter.All()).evaluateSearch(eCtx) allResultsMap := make(map[types.ArchetypeID]bool) diff --git a/cardinal/ecs_test.go b/cardinal/ecs_test.go index f50117d63..d76f25a1f 100644 --- a/cardinal/ecs_test.go +++ b/cardinal/ecs_test.go @@ -73,7 +73,7 @@ func (WeaponEnergy) Name() string { return "weaponsEnergy" } -func UpdateEnergySystem(wCtx cardinal.Context) error { +func UpdateEnergySystem(wCtx cardinal.WorldContext) error { var errs []error q := cardinal.NewSearch().Entity(filter.Contains(filter.Component[EnergyComponent]())) err := q.Each(wCtx, diff --git a/cardinal/engine_test.go b/cardinal/engine_test.go index b478c6b2f..53ebed459 100644 --- a/cardinal/engine_test.go +++ b/cardinal/engine_test.go @@ -139,7 +139,7 @@ func TestCannotWaitForNextTickAfterEngineIsShutDown(t *testing.T) { var returnErr error err := cardinal.RegisterSystems( world, - func(wCtx cardinal.Context) error { + func(wCtx cardinal.WorldContext) error { return cardinal.EachMessage[FooIn, FooOut]( wCtx, func(cardinal.TxData[FooIn]) (FooOut, error) { return returnVal, returnErr @@ -201,7 +201,7 @@ func TestEVMTxConsume(t *testing.T) { var returnVal FooOut var returnErr error err = cardinal.RegisterSystems(world, - func(eCtx cardinal.Context) error { + func(eCtx cardinal.WorldContext) error { return cardinal.EachMessage[FooIn, FooOut]( eCtx, func(cardinal.TxData[FooIn]) (FooOut, error) { return returnVal, returnErr @@ -250,15 +250,15 @@ func TestEVMTxConsume(t *testing.T) { func TestAddSystems(t *testing.T) { count := 0 - sys1 := func(cardinal.Context) error { + sys1 := func(cardinal.WorldContext) error { count++ return nil } - sys2 := func(cardinal.Context) error { + sys2 := func(cardinal.WorldContext) error { count++ return nil } - sys3 := func(cardinal.Context) error { + sys3 := func(cardinal.WorldContext) error { count++ return nil } @@ -282,13 +282,13 @@ func TestSystemExecutionOrder(t *testing.T) { order := make([]int, 0, 3) err := cardinal.RegisterSystems( world, - func(cardinal.Context) error { + func(cardinal.WorldContext) error { order = append(order, 1) return nil - }, func(cardinal.Context) error { + }, func(cardinal.WorldContext) error { order = append(order, 2) return nil - }, func(cardinal.Context) error { + }, func(cardinal.WorldContext) error { order = append(order, 3) return nil }, @@ -446,7 +446,7 @@ func TestRecoverFromChain(t *testing.T) { assert.NilError(t, cardinal.RegisterMessage[fooMsg, fooMsgRes](world, fooMsgName)) fooMessages := 0 - err := cardinal.RegisterSystems(world, func(engineContext cardinal.Context) error { + err := cardinal.RegisterSystems(world, func(engineContext cardinal.WorldContext) error { return cardinal.EachMessage[fooMsg, fooMsgRes](engineContext, func(cardinal.TxData[fooMsg]) (fooMsgRes, error) { fooMessages++ return fooMsgRes{}, nil diff --git a/cardinal/errors_test.go b/cardinal/errors_test.go index d83d52a8e..58e4f58fc 100644 --- a/cardinal/errors_test.go +++ b/cardinal/errors_test.go @@ -18,19 +18,19 @@ func TestSystemsReturnNonFatalErrors(t *testing.T) { const nonExistentEntityID = 999 testCases := []struct { name string - testFn func(cardinal.Context) error + testFn func(cardinal.WorldContext) error wantErr error }{ { name: "AddComponentTo_BadEntity", - testFn: func(wCtx cardinal.Context) error { + testFn: func(wCtx cardinal.WorldContext) error { return cardinal.AddComponentTo[Foo](wCtx, nonExistentEntityID) }, wantErr: cardinal.ErrEntityDoesNotExist, }, { name: "AddComponentTo_ComponentAlreadyOnEntity", - testFn: func(wCtx cardinal.Context) error { + testFn: func(wCtx cardinal.WorldContext) error { id, err := cardinal.Create(wCtx, Foo{}) assert.Check(t, err == nil) return cardinal.AddComponentTo[Foo](wCtx, id) @@ -39,14 +39,14 @@ func TestSystemsReturnNonFatalErrors(t *testing.T) { }, { name: "RemoveComponentFrom_BadEntity", - testFn: func(wCtx cardinal.Context) error { + testFn: func(wCtx cardinal.WorldContext) error { return cardinal.RemoveComponentFrom[Foo](wCtx, nonExistentEntityID) }, wantErr: cardinal.ErrEntityDoesNotExist, }, { name: "RemoveComponentFrom_ComponentNotOnEntity", - testFn: func(wCtx cardinal.Context) error { + testFn: func(wCtx cardinal.WorldContext) error { id, err := cardinal.Create(wCtx, Foo{}) assert.Check(t, err == nil) return cardinal.RemoveComponentFrom[Bar](wCtx, id) @@ -55,7 +55,7 @@ func TestSystemsReturnNonFatalErrors(t *testing.T) { }, { name: "RemoveComponentFrom_EntityMustHaveAtLeastOneComponent", - testFn: func(wCtx cardinal.Context) error { + testFn: func(wCtx cardinal.WorldContext) error { id, err := cardinal.Create(wCtx, Foo{}) assert.Check(t, err == nil) return cardinal.RemoveComponentFrom[Foo](wCtx, id) @@ -64,7 +64,7 @@ func TestSystemsReturnNonFatalErrors(t *testing.T) { }, { name: "cardinal.GetComponent_BadEntity", - testFn: func(wCtx cardinal.Context) error { + testFn: func(wCtx cardinal.WorldContext) error { _, err := cardinal.GetComponent[Foo](wCtx, nonExistentEntityID) return err }, @@ -72,7 +72,7 @@ func TestSystemsReturnNonFatalErrors(t *testing.T) { }, { name: "cardinal.GetComponent_ComponentNotOnEntity", - testFn: func(wCtx cardinal.Context) error { + testFn: func(wCtx cardinal.WorldContext) error { id, err := cardinal.Create(wCtx, Foo{}) assert.Check(t, err == nil) _, err = cardinal.GetComponent[Bar](wCtx, id) @@ -82,14 +82,14 @@ func TestSystemsReturnNonFatalErrors(t *testing.T) { }, { name: "SetComponent_BadEntity", - testFn: func(wCtx cardinal.Context) error { + testFn: func(wCtx cardinal.WorldContext) error { return cardinal.SetComponent[Foo](wCtx, nonExistentEntityID, &Foo{}) }, wantErr: cardinal.ErrEntityDoesNotExist, }, { name: "SetComponent_ComponentNotOnEntity", - testFn: func(wCtx cardinal.Context) error { + testFn: func(wCtx cardinal.WorldContext) error { id, err := cardinal.Create(wCtx, Foo{}) assert.Check(t, err == nil) return cardinal.SetComponent[Bar](wCtx, id, &Bar{}) @@ -98,7 +98,7 @@ func TestSystemsReturnNonFatalErrors(t *testing.T) { }, { name: "UpdateComponent_BadEntity", - testFn: func(wCtx cardinal.Context) error { + testFn: func(wCtx cardinal.WorldContext) error { return cardinal.UpdateComponent[Foo](wCtx, nonExistentEntityID, func(f *Foo) *Foo { return f }) @@ -107,7 +107,7 @@ func TestSystemsReturnNonFatalErrors(t *testing.T) { }, { name: "UpdateComponent_ComponentNotOnEntity", - testFn: func(wCtx cardinal.Context) error { + testFn: func(wCtx cardinal.WorldContext) error { id, err := cardinal.Create(wCtx, Foo{}) assert.Check(t, err == nil) return cardinal.UpdateComponent[Bar](wCtx, id, func(b *Bar) *Bar { @@ -118,7 +118,7 @@ func TestSystemsReturnNonFatalErrors(t *testing.T) { }, { name: "Remove_EntityDoesNotExist", - testFn: func(wCtx cardinal.Context) error { + testFn: func(wCtx cardinal.WorldContext) error { return cardinal.Remove(wCtx, nonExistentEntityID) }, wantErr: cardinal.ErrEntityDoesNotExist, @@ -131,7 +131,7 @@ func TestSystemsReturnNonFatalErrors(t *testing.T) { world, tick := tf.World, tf.DoTick assert.NilError(t, cardinal.RegisterComponent[Foo](world)) assert.NilError(t, cardinal.RegisterComponent[Bar](world)) - err := cardinal.RegisterInitSystems(world, func(wCtx cardinal.Context) error { + err := cardinal.RegisterInitSystems(world, func(wCtx cardinal.WorldContext) error { defer func() { // In systems, Cardinal is designed to panic when a fatal error is encountered. // This test is not supposed to panic, but if it does panic it happens in a non-main thread which @@ -163,11 +163,11 @@ func TestSystemsPanicOnComponentHasNotBeenRegistered(t *testing.T) { testCases := []struct { name string // Every test is expected to panic, so no return error is needed - panicFn func(cardinal.Context) + panicFn func(cardinal.WorldContext) }{ { name: "cardinal.AddComponentTo", - panicFn: func(wCtx cardinal.Context) { + panicFn: func(wCtx cardinal.WorldContext) { id, err := cardinal.Create(wCtx, Foo{}) assert.Check(t, err == nil) _ = cardinal.AddComponentTo[UnregisteredComp](wCtx, id) @@ -175,7 +175,7 @@ func TestSystemsPanicOnComponentHasNotBeenRegistered(t *testing.T) { }, { name: "cardinal.RemoveComponentFrom", - panicFn: func(wCtx cardinal.Context) { + panicFn: func(wCtx cardinal.WorldContext) { id, err := cardinal.Create(wCtx, Foo{}, Bar{}) assert.Check(t, err == nil) _ = cardinal.RemoveComponentFrom[UnregisteredComp](wCtx, id) @@ -183,7 +183,7 @@ func TestSystemsPanicOnComponentHasNotBeenRegistered(t *testing.T) { }, { name: "cardinal.GetComponent", - panicFn: func(wCtx cardinal.Context) { + panicFn: func(wCtx cardinal.WorldContext) { id, err := cardinal.Create(wCtx, Foo{}) assert.Check(t, err == nil) _, _ = cardinal.GetComponent[UnregisteredComp](wCtx, id) @@ -191,7 +191,7 @@ func TestSystemsPanicOnComponentHasNotBeenRegistered(t *testing.T) { }, { name: "cardinal.SetComponent", - panicFn: func(wCtx cardinal.Context) { + panicFn: func(wCtx cardinal.WorldContext) { id, err := cardinal.Create(wCtx, Foo{}) assert.Check(t, err == nil) _ = cardinal.SetComponent[UnregisteredComp](wCtx, id, &UnregisteredComp{}) @@ -199,7 +199,7 @@ func TestSystemsPanicOnComponentHasNotBeenRegistered(t *testing.T) { }, { name: "cardinal.UpdateComponent", - panicFn: func(wCtx cardinal.Context) { + panicFn: func(wCtx cardinal.WorldContext) { id, err := cardinal.Create(wCtx, Foo{}) assert.Check(t, err == nil) _ = cardinal.UpdateComponent[UnregisteredComp](wCtx, id, @@ -210,13 +210,13 @@ func TestSystemsPanicOnComponentHasNotBeenRegistered(t *testing.T) { }, { name: "cardinal.Create", - panicFn: func(wCtx cardinal.Context) { + panicFn: func(wCtx cardinal.WorldContext) { _, _ = cardinal.Create(wCtx, Foo{}, UnregisteredComp{}) }, }, { name: "cardinal.CreateMany", - panicFn: func(wCtx cardinal.Context) { + panicFn: func(wCtx cardinal.WorldContext) { _, _ = cardinal.CreateMany(wCtx, 10, Foo{}, UnregisteredComp{}) }, }, @@ -227,7 +227,7 @@ func TestSystemsPanicOnComponentHasNotBeenRegistered(t *testing.T) { tf := testutils.NewTestFixture(t, nil) world, tick := tf.World, tf.DoTick assert.NilError(t, cardinal.RegisterComponent[Foo](world)) - err := cardinal.RegisterInitSystems(world, func(wCtx cardinal.Context) error { + err := cardinal.RegisterInitSystems(world, func(wCtx cardinal.WorldContext) error { defer func() { err := recover() // assert.Check is required here because this is happening in a non-main thread. @@ -259,11 +259,11 @@ type QueryResponse struct{} func TestQueriesDoNotPanicOnComponentHasNotBeenRegistered(t *testing.T) { testCases := []struct { name string - testFn func(cardinal.Context) error + testFn func(cardinal.WorldContext) error }{ { name: "cardinal.GetComponent", - testFn: func(wCtx cardinal.Context) error { + testFn: func(wCtx cardinal.WorldContext) error { // Get a valid entity to ensure the error we find is related to the component and NOT // due to an invalid entity. id, err := cardinal.NewSearch().Entity(filter.Exact(filter.Component[Foo]())).First(wCtx) @@ -287,7 +287,7 @@ func TestQueriesDoNotPanicOnComponentHasNotBeenRegistered(t *testing.T) { tf := testutils.NewTestFixture(t, nil) world, tick := tf.World, tf.DoTick assert.NilError(t, cardinal.RegisterComponent[Foo](world)) - err := cardinal.RegisterInitSystems(world, func(wCtx cardinal.Context) error { + err := cardinal.RegisterInitSystems(world, func(wCtx cardinal.WorldContext) error { // Make an entity so the test functions are operating on a valid entity. _, err := cardinal.Create(wCtx, Foo{}) assert.Check(t, err == nil) @@ -297,7 +297,7 @@ func TestQueriesDoNotPanicOnComponentHasNotBeenRegistered(t *testing.T) { err = cardinal.RegisterQuery[QueryRequest, QueryResponse]( world, queryName, - func(wCtx cardinal.Context, _ *QueryRequest) (*QueryResponse, error) { + func(wCtx cardinal.WorldContext, _ *QueryRequest) (*QueryResponse, error) { return nil, tc.testFn(wCtx) }) assert.Check(t, err == nil) @@ -322,7 +322,7 @@ func TestGetComponentInQueryDoesNotPanicOnRedisError(t *testing.T) { world, tick := tf.World, tf.DoTick assert.NilError(t, cardinal.RegisterComponent[Foo](world)) - err := cardinal.RegisterSystems(world, func(wCtx cardinal.Context) error { + err := cardinal.RegisterSystems(world, func(wCtx cardinal.WorldContext) error { _, err := cardinal.Create(wCtx, Foo{}) assert.Check(t, err == nil) return nil @@ -333,7 +333,7 @@ func TestGetComponentInQueryDoesNotPanicOnRedisError(t *testing.T) { assert.NilError(t, cardinal.RegisterQuery[QueryRequest, QueryResponse]( world, queryName, - func(wCtx cardinal.Context, _ *QueryRequest) (*QueryResponse, error) { + func(wCtx cardinal.WorldContext, _ *QueryRequest) (*QueryResponse, error) { id, err := cardinal.NewSearch().Entity(filter.Exact(filter.Component[Foo]())).First(wCtx) assert.Check(t, err == nil) _, err = cardinal.GetComponent[Foo](wCtx, id) diff --git a/cardinal/example_messagetype_test.go b/cardinal/example_messagetype_test.go index 29cb9cb3d..21d94265a 100644 --- a/cardinal/example_messagetype_test.go +++ b/cardinal/example_messagetype_test.go @@ -29,7 +29,7 @@ func ExampleMessageType() { panic(err) } - err = cardinal.RegisterSystems(world, func(wCtx cardinal.Context) error { + err = cardinal.RegisterSystems(world, func(wCtx cardinal.WorldContext) error { return cardinal.EachMessage[MovePlayerMsg, MovePlayerResult](wCtx, func(txData cardinal.TxData[MovePlayerMsg]) (MovePlayerResult, error) { // handle the transaction diff --git a/cardinal/filtercomponent.go b/cardinal/filtercomponent.go index f54a07cf8..283ee261f 100644 --- a/cardinal/filtercomponent.go +++ b/cardinal/filtercomponent.go @@ -10,11 +10,11 @@ import ( // It involves creating and combining primitives that represent // filtering properties on components. -type FilterFn func(wCtx Context, id types.EntityID) (bool, error) +type FilterFn func(wCtx WorldContext, id types.EntityID) (bool, error) //revive:disable-next-line:unexported-return func ComponentFilter[T types.Component](f func(comp T) bool) FilterFn { - return func(wCtx Context, id types.EntityID) (bool, error) { + return func(wCtx WorldContext, id types.EntityID) (bool, error) { var t T c, err := wCtx.getComponentByName(t.Name()) if err != nil { @@ -43,7 +43,7 @@ func ComponentFilter[T types.Component](f func(comp T) bool) FilterFn { //revive:disable-next-line:unexported-return func AndFilter(fns ...FilterFn) FilterFn { - return func(wCtx Context, id types.EntityID) (bool, error) { + return func(wCtx WorldContext, id types.EntityID) (bool, error) { var result = true var errCount = 0 for _, fn := range fns { @@ -63,7 +63,7 @@ func AndFilter(fns ...FilterFn) FilterFn { //revive:disable-next-line:unexported-return func OrFilter(fns ...FilterFn) FilterFn { - return func(wCtx Context, id types.EntityID) (bool, error) { + return func(wCtx WorldContext, id types.EntityID) (bool, error) { var result = false var errCount = 0 for _, fn := range fns { diff --git a/cardinal/log/log_test.go b/cardinal/log/log_test.go index d29f6d3ca..937453074 100644 --- a/cardinal/log/log_test.go +++ b/cardinal/log/log_test.go @@ -32,7 +32,7 @@ func (EnergyComp) Name() string { return "EnergyComp" } -func testSystem(wCtx cardinal.Context) error { +func testSystem(wCtx cardinal.WorldContext) error { wCtx.Logger().Log().Msg("test") q := cardinal.NewSearch().Entity(filter.Contains(filter.Component[EnergyComp]())) err := q.Each(wCtx, @@ -53,7 +53,7 @@ func testSystem(wCtx cardinal.Context) error { return nil } -func testSystemWarningTrigger(wCtx cardinal.Context) error { +func testSystemWarningTrigger(wCtx cardinal.WorldContext) error { time.Sleep(time.Millisecond * 400) return testSystem(wCtx) } diff --git a/cardinal/message.go b/cardinal/message.go index ada795857..5da48b6df 100644 --- a/cardinal/message.go +++ b/cardinal/message.go @@ -103,15 +103,15 @@ func (t *MessageType[In, Out]) SetID(id types.MessageID) error { return nil } -func (t *MessageType[In, Out]) AddError(wCtx Context, hash types.TxHash, err error) { +func (t *MessageType[In, Out]) AddError(wCtx WorldContext, hash types.TxHash, err error) { wCtx.addMessageError(hash, err) } -func (t *MessageType[In, Out]) SetResult(wCtx Context, hash types.TxHash, result Out) { +func (t *MessageType[In, Out]) SetResult(wCtx WorldContext, hash types.TxHash, result Out) { wCtx.setMessageResult(hash, result) } -func (t *MessageType[In, Out]) GetReceipt(wCtx Context, hash types.TxHash) ( +func (t *MessageType[In, Out]) GetReceipt(wCtx WorldContext, hash types.TxHash) ( v Out, errs []error, ok bool, ) { iface, errs, ok := wCtx.getTransactionReceipt(hash) @@ -129,7 +129,7 @@ func (t *MessageType[In, Out]) GetReceipt(wCtx Context, hash types.TxHash) ( return value, errs, true } -func (t *MessageType[In, Out]) Each(wCtx Context, fn func(TxData[In]) (Out, error)) { +func (t *MessageType[In, Out]) Each(wCtx WorldContext, fn func(TxData[In]) (Out, error)) { for _, txData := range t.In(wCtx) { if result, err := fn(txData); err != nil { err = eris.Wrap(err, "") @@ -147,7 +147,7 @@ func (t *MessageType[In, Out]) Each(wCtx Context, fn func(TxData[In]) (Out, erro } // In extracts all the TxData in the tx pool that match this MessageType's ID. -func (t *MessageType[In, Out]) In(wCtx Context) []TxData[In] { +func (t *MessageType[In, Out]) In(wCtx WorldContext) []TxData[In] { tq := wCtx.getTxPool() var txs []TxData[In] for _, txData := range tq.ForID(t.ID()) { diff --git a/cardinal/persona_signer.go b/cardinal/persona_signer.go index f5d64affe..d904e1cb3 100644 --- a/cardinal/persona_signer.go +++ b/cardinal/persona_signer.go @@ -27,7 +27,7 @@ type PersonaSignerQueryResponse struct { SignerAddress string `json:"signerAddress"` } -func PersonaSignerQuery(wCtx Context, req *PersonaSignerQueryRequest) (*PersonaSignerQueryResponse, error) { +func PersonaSignerQuery(wCtx WorldContext, req *PersonaSignerQueryRequest) (*PersonaSignerQueryResponse, error) { var status string addr, err := wCtx.getSignerForPersonaTag(req.PersonaTag, req.Tick) diff --git a/cardinal/plugin_persona.go b/cardinal/plugin_persona.go index 48e884556..3dee044fb 100644 --- a/cardinal/plugin_persona.go +++ b/cardinal/plugin_persona.go @@ -111,7 +111,7 @@ func (p *personaPlugin) RegisterMessages(world *World) error { // authorizePersonaAddressSystem enables users to authorize an address to a persona tag. This is mostly used so that // users who want to interact with the game via smart contract can link their EVM address to their persona tag, enabling // them to mutate their owned state from the context of the EVM. -func authorizePersonaAddressSystem(wCtx Context) error { +func authorizePersonaAddressSystem(wCtx WorldContext) error { if err := buildGlobalPersonaIndex(wCtx); err != nil { return err } @@ -164,7 +164,7 @@ func authorizePersonaAddressSystem(wCtx Context) error { // createPersonaSystem is a system that will associate persona tags with signature addresses. Each persona tag // may have at most 1 signer, so additional attempts to register a signer with a persona tag will be ignored. -func createPersonaSystem(wCtx Context) error { +func createPersonaSystem(wCtx WorldContext) error { if err := buildGlobalPersonaIndex(wCtx); err != nil { return err } @@ -217,7 +217,7 @@ func createPersonaSystem(wCtx Context) error { // Persona Index // ----------------------------------------------------------------------------- -func buildGlobalPersonaIndex(wCtx Context) error { +func buildGlobalPersonaIndex(wCtx WorldContext) error { // Rebuild the index if we haven't built it yet OR if we're in test and the CurrentTick has been reset. if globalPersonaTagToAddressIndex != nil && tickOfPersonaTagToAddressIndex < wCtx.CurrentTick() { return nil diff --git a/cardinal/query.go b/cardinal/query.go index 7d0970cd4..a362cade7 100644 --- a/cardinal/query.go +++ b/cardinal/query.go @@ -19,10 +19,10 @@ type query interface { // Group returns the group of the query. Group() string // HandleQuery handles queries with concrete types, rather than encoded bytes. - handleQuery(Context, any) (any, error) + handleQuery(WorldContext, any) (any, error) // HandleQueryRaw is given a reference to the engine, json encoded bytes that represent a query request // and is expected to return a json encoded response struct. - handleQueryRaw(Context, []byte) ([]byte, error) + handleQueryRaw(WorldContext, []byte) ([]byte, error) // DecodeEVMRequest decodes bytes originating from the evm into the request type, which will be ABI encoded. DecodeEVMRequest([]byte) (any, error) // EncodeEVMReply encodes the reply as an abi encoded struct. @@ -42,7 +42,7 @@ type QueryOption[Request, Reply any] func(qt *queryType[Request, Reply]) type queryType[Request any, Reply any] struct { name string group string - handler func(wCtx Context, req *Request) (*Reply, error) + handler func(wCtx WorldContext, req *Request) (*Reply, error) requestABI *ethereumAbi.Type replyABI *ethereumAbi.Type } @@ -67,7 +67,7 @@ func WithCustomQueryGroup[Request, Reply any](group string) QueryOption[Request, func newQueryType[Request any, Reply any]( name string, - handler func(wCtx Context, req *Request) (*Reply, error), + handler func(wCtx WorldContext, req *Request) (*Reply, error), opts ...QueryOption[Request, Reply], ) (query, error) { err := validateQuery[Request, Reply](name, handler) @@ -114,7 +114,7 @@ func (r *queryType[req, rep]) Group() string { return r.group } -func (r *queryType[req, rep]) handleQuery(wCtx Context, a any) (any, error) { +func (r *queryType[req, rep]) handleQuery(wCtx WorldContext, a any) (any, error) { var request *req if reflect.TypeOf(a).Kind() == reflect.Pointer { ptrRequest, ok := a.(*req) @@ -133,7 +133,7 @@ func (r *queryType[req, rep]) handleQuery(wCtx Context, a any) (any, error) { return reply, err } -func (r *queryType[req, rep]) handleQueryRaw(wCtx Context, bz []byte) ([]byte, error) { +func (r *queryType[req, rep]) handleQueryRaw(wCtx WorldContext, bz []byte) ([]byte, error) { request := new(req) err := json.Unmarshal(bz, request) if err != nil { @@ -231,7 +231,7 @@ func (r *queryType[Request, Reply]) GetRequestFieldInformation() map[string]any func validateQuery[Request any, Reply any]( name string, - handler func(wCtx Context, req *Request) (*Reply, error), + handler func(wCtx WorldContext, req *Request) (*Reply, error), ) error { if name == "" { return eris.New("cannot create query without name") diff --git a/cardinal/query_test.go b/cardinal/query_test.go index 102eff25d..91a40b0ba 100644 --- a/cardinal/query_test.go +++ b/cardinal/query_test.go @@ -28,7 +28,7 @@ type QueryHealthResponse struct { } func handleQueryHealth( - wCtx cardinal.Context, + wCtx cardinal.WorldContext, request *QueryHealthRequest, ) (*QueryHealthResponse, error) { resp := &QueryHealthResponse{} @@ -64,7 +64,7 @@ func TestNewQueryTypeWithEVMSupport(t *testing.T) { testutils.NewTestFixture(t, nil).World, "query_health", func( - _ cardinal.Context, + _ cardinal.WorldContext, _ *FooReq, ) (*FooReply, error) { return &FooReply{}, errors.New("this function should never get called") @@ -121,7 +121,7 @@ func TestQueryTypeNotStructs(t *testing.T) { err := cardinal.RegisterQuery[string, string]( testutils.NewTestFixture(t, nil).World, "foo", - func(cardinal.Context, *string) (*string, error) { + func(cardinal.WorldContext, *string) (*string, error) { return &str, nil }, ) @@ -147,7 +147,7 @@ func TestQueryEVM(t *testing.T) { world, "foo", func( - _ cardinal.Context, _ *FooRequest, + _ cardinal.WorldContext, _ *FooRequest, ) (*FooReply, error) { return &expectedReply, nil }, diff --git a/cardinal/search.go b/cardinal/search.go index 861d901f8..df079f422 100644 --- a/cardinal/search.go +++ b/cardinal/search.go @@ -22,12 +22,12 @@ type EntitySearch interface { } type Searchable interface { - evaluateSearch(eCtx Context) []types.ArchetypeID - Each(eCtx Context, callback CallbackFn) error - First(eCtx Context) (types.EntityID, error) - MustFirst(eCtx Context) types.EntityID - Count(eCtx Context) (int, error) - Collect(eCtx Context) ([]types.EntityID, error) + evaluateSearch(eCtx WorldContext) []types.ArchetypeID + Each(eCtx WorldContext, callback CallbackFn) error + First(eCtx WorldContext) (types.EntityID, error) + MustFirst(eCtx WorldContext) types.EntityID + Count(eCtx WorldContext) (int, error) + Collect(eCtx WorldContext) ([]types.EntityID, error) } type CallbackFn func(types.EntityID) bool @@ -147,7 +147,7 @@ func (s *Search) Where(componentFilter FilterFn) EntitySearch { // Each iterates over all entities that match the search. // If you would like to stop the iteration, return false to the callback. To continue iterating, return true. -func (s *Search) Each(eCtx Context, callback CallbackFn) (err error) { +func (s *Search) Each(eCtx WorldContext, callback CallbackFn) (err error) { defer func() { defer panicOnFatalError(eCtx, err) }() result := s.evaluateSearch(eCtx) @@ -183,7 +183,7 @@ func fastSortIDs(ids []types.EntityID) { slices.Sort(ids) } -func (s *Search) Collect(eCtx Context) ([]types.EntityID, error) { +func (s *Search) Collect(eCtx WorldContext) ([]types.EntityID, error) { acc := make([]types.EntityID, 0) err := s.Each(eCtx, func(id types.EntityID) bool { acc = append(acc, id) @@ -197,7 +197,7 @@ func (s *Search) Collect(eCtx Context) ([]types.EntityID, error) { } // Count returns the number of entities that match the search. -func (s *Search) Count(eCtx Context) (ret int, err error) { +func (s *Search) Count(eCtx WorldContext) (ret int, err error) { defer func() { defer panicOnFatalError(eCtx, err) }() result := s.evaluateSearch(eCtx) @@ -226,7 +226,7 @@ func (s *Search) Count(eCtx Context) (ret int, err error) { } // First returns the first entity that matches the search. -func (s *Search) First(eCtx Context) (id types.EntityID, err error) { +func (s *Search) First(eCtx WorldContext) (id types.EntityID, err error) { defer func() { defer panicOnFatalError(eCtx, err) }() result := s.evaluateSearch(eCtx) @@ -257,7 +257,7 @@ func (s *Search) First(eCtx Context) (id types.EntityID, err error) { return iterators.BadID, eris.Wrap(err, "") } -func (s *Search) MustFirst(eCtx Context) types.EntityID { +func (s *Search) MustFirst(eCtx WorldContext) types.EntityID { id, err := s.First(eCtx) if err != nil { panic("no entity matches the search") @@ -265,7 +265,7 @@ func (s *Search) MustFirst(eCtx Context) types.EntityID { return id } -func (s *Search) evaluateSearch(eCtx Context) []types.ArchetypeID { +func (s *Search) evaluateSearch(eCtx WorldContext) []types.ArchetypeID { cache := s.archMatches for it := eCtx.storeReader().SearchFrom(s.filter, cache.seen); it.HasNext(); { cache.archetypes = append(cache.archetypes, it.Next()) diff --git a/cardinal/search_test.go b/cardinal/search_test.go index 05261d398..227580a83 100644 --- a/cardinal/search_test.go +++ b/cardinal/search_test.go @@ -88,7 +88,7 @@ func TestSearchUsingAllMethods(t *testing.T) { filter.Contains(filter.Component[AlphaTest]()), filter.Contains(filter.Component[BetaTest]()), filter.Contains(filter.Component[GammaTest]())), - )).Where(func(_ cardinal.Context, _ types.EntityID) (bool, error) { + )).Where(func(_ cardinal.WorldContext, _ types.EntityID) (bool, error) { return true, nil }).Count(worldCtx) assert.NilError(t, err) @@ -97,7 +97,7 @@ func TestSearchUsingAllMethods(t *testing.T) { filter.Contains(filter.Component[AlphaTest]()), filter.Contains(filter.Component[BetaTest]()), filter.Contains(filter.Component[GammaTest]())), - )).Where(func(wCtx cardinal.Context, id types.EntityID) (bool, error) { + )).Where(func(wCtx cardinal.WorldContext, id types.EntityID) (bool, error) { c, err := cardinal.GetComponent[HP](wCtx, id) if err != nil { return false, err @@ -485,7 +485,7 @@ func TestWhereClauseOnSearch(t *testing.T) { _, err = cardinal.CreateMany(worldCtx, 10, AlphaTest{}, BetaTest{}, GammaTest{}) assert.NilError(t, err) - q1 := cardinal.NewSearch().Entity(filter.All()).Where(func(wCtx cardinal.Context, id types.EntityID) (bool, error) { + q1 := cardinal.NewSearch().Entity(filter.All()).Where(func(wCtx cardinal.WorldContext, id types.EntityID) (bool, error) { _, err := cardinal.GetComponent[AlphaTest](wCtx, id) if err != nil { return false, err diff --git a/cardinal/server/event_test.go b/cardinal/server/event_test.go index f6f92ce7b..acdcaa6af 100644 --- a/cardinal/server/event_test.go +++ b/cardinal/server/event_test.go @@ -41,31 +41,31 @@ func TestEventsThroughSystems(t *testing.T) { counter1 := atomic.Int32{} counter1.Store(0) event := map[string]any{"message": "test"} - sys1 := func(wCtx cardinal.Context) error { + sys1 := func(wCtx cardinal.WorldContext) error { err := wCtx.EmitEvent(event) assert.Check(t, err == nil, "emit event encountered error is system 1: %v", err) counter1.Add(1) return nil } - sys2 := func(wCtx cardinal.Context) error { + sys2 := func(wCtx cardinal.WorldContext) error { err := wCtx.EmitEvent(event) assert.Check(t, err == nil, "emit event encountered error is system 2: %v", err) counter1.Add(1) return nil } - sys3 := func(wCtx cardinal.Context) error { + sys3 := func(wCtx cardinal.WorldContext) error { err := wCtx.EmitEvent(event) assert.Check(t, err == nil, "emit event encountered error is system 3: %v", err) counter1.Add(1) return nil } - sys4 := func(wCtx cardinal.Context) error { + sys4 := func(wCtx cardinal.WorldContext) error { err := wCtx.EmitEvent(event) assert.Check(t, err == nil, "emit event encountered error is system 4: %v", err) counter1.Add(1) return nil } - sys5 := func(wCtx cardinal.Context) error { + sys5 := func(wCtx cardinal.WorldContext) error { err := wCtx.EmitEvent(event) assert.Check(t, err == nil, "emit event encountered error is system 5: %v", err) counter1.Add(1) diff --git a/cardinal/server/receipts_test.go b/cardinal/server/receipts_test.go index 9312ed2da..f2f76da4c 100644 --- a/cardinal/server/receipts_test.go +++ b/cardinal/server/receipts_test.go @@ -19,7 +19,7 @@ func (s *ServerTestSuite) TestReceiptsQuery() { err := cardinal.RegisterMessage[fooIn, fooOut](world, msgName) s.Require().NoError(err) wantErrorMessage := "THIS_ERROR_MESSAGE_SHOULD_BE_IN_THE_RECEIPT" - err = cardinal.RegisterSystems(world, func(ctx cardinal.Context) error { + err = cardinal.RegisterSystems(world, func(ctx cardinal.WorldContext) error { return cardinal.EachMessage[fooIn, fooOut](ctx, func(cardinal.TxData[fooIn]) (fooOut, error) { if ctx.CurrentTick()%2 == 0 { return fooOut{Y: 4}, nil diff --git a/cardinal/server/server_test.go b/cardinal/server/server_test.go index 3db2fd1a8..5cd5221ce 100644 --- a/cardinal/server/server_test.go +++ b/cardinal/server/server_test.go @@ -203,7 +203,7 @@ func (s *ServerTestSuite) TestQueryCustomGroup() { err := cardinal.RegisterQuery[SomeRequest, SomeResponse]( s.world, name, - func(_ cardinal.Context, _ *SomeRequest) (*SomeResponse, error) { + func(_ cardinal.WorldContext, _ *SomeRequest) (*SomeResponse, error) { called = true return &SomeResponse{}, nil }, @@ -279,7 +279,7 @@ func (s *ServerTestSuite) setupWorld(opts ...cardinal.WorldOption) { err = cardinal.RegisterMessage[MoveMsgInput, MoveMessageOutput](s.world, moveMsgName) s.Require().NoError(err) personaToPosition := make(map[string]types.EntityID) - err = cardinal.RegisterSystems(s.world, func(context cardinal.Context) error { + err = cardinal.RegisterSystems(s.world, func(context cardinal.WorldContext) error { return cardinal.EachMessage[MoveMsgInput, MoveMessageOutput](context, func(tx cardinal.TxData[MoveMsgInput]) (MoveMessageOutput, error) { posID, exists := personaToPosition[tx.Tx.PersonaTag] @@ -313,7 +313,7 @@ func (s *ServerTestSuite) setupWorld(opts ...cardinal.WorldOption) { err = cardinal.RegisterQuery[QueryLocationRequest, QueryLocationResponse]( s.world, "location", - func(wCtx cardinal.Context, req *QueryLocationRequest) (*QueryLocationResponse, error) { + func(wCtx cardinal.WorldContext, req *QueryLocationRequest) (*QueryLocationResponse, error) { locID, exists := personaToPosition[req.Persona] if !exists { return nil, fmt.Errorf("location for %q does not exists", req.Persona) diff --git a/cardinal/state_test.go b/cardinal/state_test.go index 91569446f..80e5a42fb 100644 --- a/cardinal/state_test.go +++ b/cardinal/state_test.go @@ -231,7 +231,7 @@ func TestCanReloadState(t *testing.T) { err := cardinal.RegisterSystems( world1, - func(wCtx cardinal.Context) error { + func(wCtx cardinal.WorldContext) error { q := cardinal.NewSearch().Entity(filter.Contains(filter.Component[oneAlphaNumComp]())) assert.NilError( t, q.Each(wCtx, @@ -308,7 +308,7 @@ func TestCanFindTransactionsAfterReloadingEngine(t *testing.T) { assert.NilError(t, cardinal.RegisterMessage[Msg, Result](world, msgName)) err := cardinal.RegisterSystems( world, - func(wCtx cardinal.Context) error { + func(wCtx cardinal.WorldContext) error { someTx, err := cardinal.GetMessage[Msg, Result](wCtx) return cardinal.EachMessage[Msg, Result](wCtx, func(tx cardinal.TxData[Msg]) (Result, error) { someTx.SetResult(wCtx, tx.Hash, Result{}) diff --git a/cardinal/system.go b/cardinal/system.go index 08d48d616..962c0c37e 100644 --- a/cardinal/system.go +++ b/cardinal/system.go @@ -19,7 +19,7 @@ const ( var _ SystemManager = &systemManager{} // System is a user-defined function that is executed at every tick. -type System func(ctx Context) error +type System func(ctx WorldContext) error // systemType is an internal entry used to track registered systems. type systemType struct { @@ -38,7 +38,7 @@ type SystemManager interface { // These methods are intentionally made private to avoid other // packages from trying to modify the system manager in the middle of a tick. registerSystems(isInit bool, systems ...System) error - runSystems(wCtx Context) error + runSystems(wCtx WorldContext) error } type systemManager struct { @@ -105,7 +105,7 @@ func (m *systemManager) registerSystems(isInit bool, systemFuncs ...System) erro } // RunSystems runs all the registered system in the order that they were registered. -func (m *systemManager) runSystems(wCtx Context) error { +func (m *systemManager) runSystems(wCtx WorldContext) error { var systemsToRun []systemType if wCtx.CurrentTick() == 0 { systemsToRun = slices.Concat(m.registeredInitSystems, m.registeredSystems) diff --git a/cardinal/system_test.go b/cardinal/system_test.go index d737c9d18..69de0a7e2 100644 --- a/cardinal/system_test.go +++ b/cardinal/system_test.go @@ -11,7 +11,7 @@ import ( "pkg.world.dev/world-engine/cardinal/types" ) -func HealthSystem(wCtx cardinal.Context) error { +func HealthSystem(wCtx cardinal.WorldContext) error { var errs []error errs = append(errs, cardinal.NewSearch().Entity(filter. Exact(filter.Component[Health]())). @@ -66,11 +66,11 @@ func TestCanRegisterMultipleSystem(t *testing.T) { var firstSystemCalled bool var secondSystemCalled bool - firstSystem := func(cardinal.Context) error { + firstSystem := func(cardinal.WorldContext) error { firstSystemCalled = true return nil } - secondSystem := func(cardinal.Context) error { + secondSystem := func(cardinal.WorldContext) error { secondSystemCalled = true return nil } @@ -89,10 +89,10 @@ func TestInitSystemRunsOnce(t *testing.T) { w := tf.World count := 0 count2 := 0 - err := cardinal.RegisterInitSystems(w, func(_ cardinal.Context) error { + err := cardinal.RegisterInitSystems(w, func(_ cardinal.WorldContext) error { count++ return nil - }, func(_ cardinal.Context) error { + }, func(_ cardinal.WorldContext) error { count2 += 2 return nil }) diff --git a/cardinal/util.go b/cardinal/util.go index 6221537b8..76877c33b 100644 --- a/cardinal/util.go +++ b/cardinal/util.go @@ -37,7 +37,7 @@ func separateOptions(opts []WorldOption) ( } // panicOnFatalError is a helper function to panic on non-deterministic errors (i.e. Redis error). -func panicOnFatalError(wCtx Context, err error) { +func panicOnFatalError(wCtx WorldContext, err error) { if err != nil && !wCtx.isReadOnly() && isFatalError(err) { wCtx.Logger().Panic().Err(err).Msgf("fatal error: %v", eris.ToString(err, true)) panic(err) @@ -53,7 +53,7 @@ func isFatalError(err error) bool { return true } -func GetMessage[In any, Out any](wCtx Context) (*MessageType[In, Out], error) { +func GetMessage[In any, Out any](wCtx WorldContext) (*MessageType[In, Out], error) { var msg MessageType[In, Out] msgType := reflect.TypeOf(msg) tempRes, ok := wCtx.getMessageByType(msgType) @@ -68,7 +68,7 @@ func GetMessage[In any, Out any](wCtx Context) (*MessageType[In, Out], error) { return res, nil } -func GetTransactionReceiptsForTick(wCtx Context, tick uint64) ([]receipt.Receipt, error) { +func GetTransactionReceiptsForTick(wCtx WorldContext, tick uint64) ([]receipt.Receipt, error) { ctx, ok := wCtx.(*worldContext) if !ok { return nil, eris.New("error in test type assertion.") @@ -76,14 +76,14 @@ func GetTransactionReceiptsForTick(wCtx Context, tick uint64) ([]receipt.Receipt return ctx.world.GetTransactionReceiptsForTick(tick) } -func GetStoreManagerFromContext(wCtx Context) gamestate.Manager { +func GetStoreManagerFromContext(wCtx WorldContext) gamestate.Manager { return wCtx.storeManager() } -func GetComponentByNameFromContext(wCtx Context, name string) (types.ComponentMetadata, error) { +func GetComponentByNameFromContext(wCtx WorldContext, name string) (types.ComponentMetadata, error) { return wCtx.getComponentByName(name) } -func HandleQuery(wCtx Context, query query, a any) (any, error) { +func HandleQuery(wCtx WorldContext, query query, a any) (any, error) { return query.handleQuery(wCtx, a) } diff --git a/cardinal/world.go b/cardinal/world.go index 4f6984040..aa4ff6efd 100644 --- a/cardinal/world.go +++ b/cardinal/world.go @@ -644,7 +644,7 @@ func (w *World) GetRegisteredComponents() []types.ComponentMetadata { return w.componentManager.GetComponents() } -func (w *World) GetReadOnlyCtx() Context { +func (w *World) GetReadOnlyCtx() WorldContext { return NewReadOnlyWorldContext(w) } diff --git a/cardinal/world_context.go b/cardinal/world_context.go index 8d614e3eb..d628440d1 100644 --- a/cardinal/world_context.go +++ b/cardinal/world_context.go @@ -15,10 +15,10 @@ import ( ) // interface guard -var _ Context = (*worldContext)(nil) +var _ WorldContext = (*worldContext)(nil) //go:generate mockgen -source=context.go -package mocks -destination=mocks/context.go -type Context interface { +type WorldContext interface { // Timestamp returns the UNIX timestamp of the tick. Timestamp() uint64 // CurrentTick returns the current tick. @@ -60,7 +60,7 @@ type worldContext struct { readOnly bool } -func newWorldContextForTick(world *World, txPool *txpool.TxPool) Context { +func newWorldContextForTick(world *World, txPool *txpool.TxPool) WorldContext { return &worldContext{ world: world, txPool: txPool, @@ -69,7 +69,7 @@ func newWorldContextForTick(world *World, txPool *txpool.TxPool) Context { } } -func NewWorldContext(world *World) Context { +func NewWorldContext(world *World) WorldContext { return &worldContext{ world: world, txPool: nil, @@ -78,7 +78,7 @@ func NewWorldContext(world *World) Context { } } -func NewReadOnlyWorldContext(world *World) Context { +func NewReadOnlyWorldContext(world *World) WorldContext { return &worldContext{ world: world, txPool: nil, diff --git a/cardinal/world_persona_test.go b/cardinal/world_persona_test.go index bdcedca0c..35b24c938 100644 --- a/cardinal/world_persona_test.go +++ b/cardinal/world_persona_test.go @@ -97,7 +97,7 @@ func TestCreatePersonaSystem_WhenCardinalIsRestarted_PersonaTagsAreStillRegister // emitNumberOfPersonaTagsSystem is a system that finds all the registered persona tags and sends them // across a channel. - emitNumberOfPersonaTagsSystem := func(wCtx cardinal.Context) error { + emitNumberOfPersonaTagsSystem := func(wCtx cardinal.WorldContext) error { result := countPersonaTagsResult{personaTags: map[string]bool{}} err := cardinal.NewSearch(). Entity(filter.Exact(filter.Component[component.SignerComponent]())). diff --git a/cardinal/world_test.go b/cardinal/world_test.go index 0d598761c..989e0276a 100644 --- a/cardinal/world_test.go +++ b/cardinal/world_test.go @@ -47,7 +47,7 @@ func TestIfPanicMessageLogged(t *testing.T) { errorTxt := "BIG ERROR OH NO" err = RegisterSystems( world, - func(Context) error { + func(WorldContext) error { panic(errorTxt) }, ) @@ -119,7 +119,7 @@ func TestCanRecoverStateAfterFailedArchetypeChange(t *testing.T) { errorToggleComponent := errors.New("problem with toggle component") err = RegisterSystems( world, - func(wCtx Context) error { + func(wCtx WorldContext) error { // Get the one and only entity ID q := NewSearch().Entity(filter.Contains(filter.Component[ScalarComponentStatic]())) id, err := q.First(wCtx) @@ -212,7 +212,7 @@ func TestCanRecoverTransactionsFromFailedSystemRun(t *testing.T) { err = RegisterSystems( world, - func(wCtx Context) error { + func(wCtx WorldContext) error { q := NewSearch().Entity(filter.Contains(filter.Component[PowerComp]())) id := q.MustFirst(wCtx) entityPower, err := GetComponent[PowerComp](wCtx, id) @@ -317,7 +317,7 @@ func TestCanIdentifyAndFixSystemError(t *testing.T) { // In this test, our "buggy" system fails once Power reaches 3 err = RegisterSystems( world, - func(wCtx Context) error { + func(wCtx WorldContext) error { searchObject := NewSearch().Entity(filter.Exact(filter.Component[onePowerComponent]())) id := searchObject.MustFirst(wCtx) p, err := GetComponent[onePowerComponent](wCtx, id) @@ -361,7 +361,7 @@ func TestCanIdentifyAndFixSystemError(t *testing.T) { // this is our fixed system that can handle Power levels of 3 and higher err = RegisterSystems( world2, - func(wCtx Context) error { + func(wCtx WorldContext) error { p, err := GetComponent[onePowerComponent](wCtx, id) if err != nil { return err @@ -411,35 +411,35 @@ func TestSystemsPanicOnRedisError(t *testing.T) { testCases := []struct { name string // the failFn will be called at a time when the ECB is empty of cached data and redis is down. - failFn func(wCtx Context, goodID types.EntityID) + failFn func(wCtx WorldContext, goodID types.EntityID) }{ { name: "AddComponentTo", - failFn: func(wCtx Context, goodID types.EntityID) { + failFn: func(wCtx WorldContext, goodID types.EntityID) { _ = AddComponentTo[Qux](wCtx, goodID) }, }, { name: "RemoveComponentFrom", - failFn: func(wCtx Context, goodID types.EntityID) { + failFn: func(wCtx WorldContext, goodID types.EntityID) { _ = RemoveComponentFrom[Bar](wCtx, goodID) }, }, { name: "GetComponent", - failFn: func(wCtx Context, goodID types.EntityID) { + failFn: func(wCtx WorldContext, goodID types.EntityID) { _, _ = GetComponent[Foo](wCtx, goodID) }, }, { name: "SetComponent", - failFn: func(wCtx Context, goodID types.EntityID) { + failFn: func(wCtx WorldContext, goodID types.EntityID) { _ = SetComponent[Foo](wCtx, goodID, &Foo{}) }, }, { name: "UpdateComponent", - failFn: func(wCtx Context, goodID types.EntityID) { + failFn: func(wCtx WorldContext, goodID types.EntityID) { _ = UpdateComponent[Foo](wCtx, goodID, func(f *Foo) *Foo { return f }) @@ -464,7 +464,7 @@ func TestSystemsPanicOnRedisError(t *testing.T) { // This system will be called 2 times. The first time, a single entity is Created. The second time, // the previously Created entity is fetched, and then miniRedis is closed. Subsequent attempts to access // data should panic. - assert.NilError(t, RegisterSystems(world, func(wCtx Context) error { + assert.NilError(t, RegisterSystems(world, func(wCtx WorldContext) error { // Set up the entity in the first tick if wCtx.CurrentTick() == 0 { _, err := Create(wCtx, Foo{}, Bar{}) @@ -536,7 +536,7 @@ func doTickCapturePanic(ctx context.Context, world *World) (err error) { return nil } -func getMessage[In any, Out any](wCtx Context) (*MessageType[In, Out], error) { +func getMessage[In any, Out any](wCtx WorldContext) (*MessageType[In, Out], error) { var msg MessageType[In, Out] msgType := reflect.TypeOf(msg) tempRes, ok := wCtx.getMessageByType(msgType) diff --git a/e2e/testgames/game/query/location.go b/e2e/testgames/game/query/location.go index 8b1ba4706..f1d4bbec4 100644 --- a/e2e/testgames/game/query/location.go +++ b/e2e/testgames/game/query/location.go @@ -21,7 +21,7 @@ func RegisterLocationQuery(world *cardinal.World) error { return cardinal.RegisterQuery[LocationRequest, LocationReply]( world, "location", - func(ctx cardinal.Context, req *LocationRequest) (*LocationReply, error) { + func(ctx cardinal.WorldContext, req *LocationRequest) (*LocationReply, error) { playerEntityID, ok := sys.PlayerEntityID[req.ID] if !ok { ctx.Logger().Info().Msg("listing existing players...") diff --git a/e2e/testgames/game/sys/error.go b/e2e/testgames/game/sys/error.go index 1034f574a..20d74b6fa 100644 --- a/e2e/testgames/game/sys/error.go +++ b/e2e/testgames/game/sys/error.go @@ -10,7 +10,7 @@ import ( // Error is a system that will produce an error for any incoming Error messages. It's // used to test receipt errors. -func Error(ctx cardinal.Context) error { +func Error(ctx cardinal.WorldContext) error { return cardinal.EachMessage[msg.ErrorInput, msg.ErrorOutput]( ctx, func(m cardinal.TxData[msg.ErrorInput]) (msg.ErrorOutput, error) { err := errors.New(m.Msg.ErrorMsg) diff --git a/e2e/testgames/game/sys/join.go b/e2e/testgames/game/sys/join.go index d24eb2c07..6bddbdc29 100644 --- a/e2e/testgames/game/sys/join.go +++ b/e2e/testgames/game/sys/join.go @@ -12,7 +12,7 @@ import ( var PlayerEntityID = make(map[string]types.EntityID) -func Join(ctx cardinal.Context) error { +func Join(ctx cardinal.WorldContext) error { logger := ctx.Logger() return cardinal.EachMessage[msg.JoinInput, msg.JoinOutput]( ctx, func(jtx cardinal.TxData[msg.JoinInput]) (msg.JoinOutput, error) { diff --git a/e2e/testgames/game/sys/move.go b/e2e/testgames/game/sys/move.go index 10523b5d8..7fd096ebc 100644 --- a/e2e/testgames/game/sys/move.go +++ b/e2e/testgames/game/sys/move.go @@ -9,7 +9,7 @@ import ( "pkg.world.dev/world-engine/cardinal" ) -func Move(ctx cardinal.Context) error { +func Move(ctx cardinal.WorldContext) error { logger := ctx.Logger() return cardinal.EachMessage[msg.MoveInput, msg.MoveOutput](ctx, func(mtx cardinal.TxData[msg.MoveInput]) (msg.MoveOutput, error) { diff --git a/e2e/testgames/gamebenchmark/sys/sys.go b/e2e/testgames/gamebenchmark/sys/sys.go index 1d09f88d1..be0d8471b 100644 --- a/e2e/testgames/gamebenchmark/sys/sys.go +++ b/e2e/testgames/gamebenchmark/sys/sys.go @@ -13,7 +13,7 @@ var ( TreeEntityIDs []types.EntityID ) -func InitTenThousandEntities(wCtx cardinal.Context) error { +func InitTenThousandEntities(wCtx cardinal.WorldContext) error { var err error entityAmount := 10000 TenThousandEntityIDs, err = cardinal.CreateMany(wCtx, entityAmount, &comp.SingleNumber{Number: 1}) @@ -23,7 +23,7 @@ func InitTenThousandEntities(wCtx cardinal.Context) error { return nil } -func InitOneHundredEntities(wCtx cardinal.Context) error { +func InitOneHundredEntities(wCtx cardinal.WorldContext) error { var err error entityAmount := 100 OneHundredEntityIDs, err = cardinal.CreateMany(wCtx, entityAmount, &comp.ArrayComp{Numbers: [10000]int{}}) @@ -33,7 +33,7 @@ func InitOneHundredEntities(wCtx cardinal.Context) error { return nil } -func InitTreeEntities(wCtx cardinal.Context) error { +func InitTreeEntities(wCtx cardinal.WorldContext) error { var err error var entityAmount = 100 var treeDepth = 10 @@ -48,7 +48,7 @@ func InitTreeEntities(wCtx cardinal.Context) error { return nil } -func SystemBenchmark(wCtx cardinal.Context) error { +func SystemBenchmark(wCtx cardinal.WorldContext) error { for _, id := range TreeEntityIDs { gotcomp, err := cardinal.GetComponent[comp.Tree](wCtx, id) if err != nil { From ea77849157a15a21f7455869b322ba7624c7bc6b Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Fri, 10 May 2024 14:39:03 -0700 Subject: [PATCH 38/76] change RunCQLSearch to EvaluateCQL --- cardinal/server/handler/cql.go | 2 +- cardinal/server/types/provider.go | 2 +- cardinal/world.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cardinal/server/handler/cql.go b/cardinal/server/handler/cql.go index f2d4b8062..6d41a1745 100644 --- a/cardinal/server/handler/cql.go +++ b/cardinal/server/handler/cql.go @@ -51,7 +51,7 @@ func PostCQL( if err != nil { return fiber.NewError(fiber.StatusBadRequest, err.Error()) } - result, eachError, searchErr := world.RunCQLSearch(resultFilter) + result, eachError, searchErr := world.EvaluateCQL(resultFilter) if searchErr != nil { return fiber.NewError(fiber.StatusInternalServerError, searchErr.Error()) } diff --git a/cardinal/server/types/provider.go b/cardinal/server/types/provider.go index 0885f698d..d7d6be9ef 100644 --- a/cardinal/server/types/provider.go +++ b/cardinal/server/types/provider.go @@ -20,7 +20,7 @@ type ProviderWorld interface { CurrentTick() uint64 ReceiptHistorySize() uint64 GetTransactionReceiptsForTick(tick uint64) ([]receipt.Receipt, error) - RunCQLSearch(filter filter.ComponentFilter) ([]types.CqlData, error, error) + EvaluateCQL(filter filter.ComponentFilter) ([]types.CqlData, error, error) GetDebugState() (types.DebugStateResponse, error, error) BuildQueryFields() []engine.FieldDetail } diff --git a/cardinal/world.go b/cardinal/world.go index aa4ff6efd..556a12355 100644 --- a/cardinal/world.go +++ b/cardinal/world.go @@ -676,7 +676,7 @@ func (w *World) ReceiptHistorySize() uint64 { return w.receiptHistory.Size() } -func (w *World) RunCQLSearch(filter filter.ComponentFilter) ([]types.CqlData, error, error) { +func (w *World) EvaluateCQL(filter filter.ComponentFilter) ([]types.CqlData, error, error) { result := make([]types.CqlData, 0) var eachError error wCtx := NewReadOnlyWorldContext(w) From 140312d4b25386c80677717cfa73a4773b07b908 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Fri, 10 May 2024 15:07:24 -0700 Subject: [PATCH 39/76] get rid of the index. --- cardinal/cardinal.go | 1 - cardinal/query_manager.go | 35 +++++-------------------------- cardinal/server/handler/query.go | 2 +- cardinal/server/types/provider.go | 2 +- cardinal/world.go | 1 - 5 files changed, 7 insertions(+), 34 deletions(-) diff --git a/cardinal/cardinal.go b/cardinal/cardinal.go index 14b1996e1..885298a10 100644 --- a/cardinal/cardinal.go +++ b/cardinal/cardinal.go @@ -147,7 +147,6 @@ func RegisterQuery[Request any, Reply any]( } res := w.RegisterQuery(name, q) - w.BuildQueryIndex(w) return res } diff --git a/cardinal/query_manager.go b/cardinal/query_manager.go index 05bfacc03..a313e1033 100644 --- a/cardinal/query_manager.go +++ b/cardinal/query_manager.go @@ -8,13 +8,10 @@ type QueryManager interface { RegisterQuery(name string, query query) error GetRegisteredQueries() []query GetQueryByName(name string) (query, error) - BuildQueryIndex(world *World) - GetQueryIndex() map[string]map[string]query } type queryManager struct { registeredQueries map[string]query - queryIndex map[string]map[string]query } func newQueryManager() QueryManager { @@ -23,10 +20,6 @@ func newQueryManager() QueryManager { } } -func (m *queryManager) GetQueryIndex() map[string]map[string]query { - return m.queryIndex -} - // RegisterQuery registers a query with the query manager. // There can only be one query with a given name. func (m *queryManager) RegisterQuery(name string, query query) error { @@ -49,31 +42,13 @@ func (m *queryManager) GetRegisteredQueries() []query { return registeredQueries } -func (m *queryManager) BuildQueryIndex(world *World) { - queries := world.GetRegisteredQueries() - m.queryIndex = make(map[string]map[string]query) - // Create query index - for _, q := range queries { - // Initialize inner map if it doesn't exist - if _, ok := m.queryIndex[q.Group()]; !ok { - m.queryIndex[q.Group()] = make(map[string]query) - } - m.queryIndex[q.Group()][q.Name()] = q - } -} -func (w *World) QueryHandler(name string, group string, bz []byte) ([]byte, error) { - index := w.QueryManager.GetQueryIndex() - groupIndex, ok := index[group] - - if !ok { - return nil, eris.Errorf("query with group %s not found", group) - } - query, ok := groupIndex[name] - if !ok { - return nil, eris.Errorf("query with name %s not found", name) +func (w *World) QueryHandler(name string, bz []byte) ([]byte, error) { + q, err := w.GetQueryByName(name) + if err != nil { + return nil, eris.Errorf("could not find query with name: %s", name) } wCtx := NewReadOnlyWorldContext(w) - return query.handleQueryRaw(wCtx, bz) + return q.handleQueryRaw(wCtx, bz) } // GetQueryByName returns a query corresponding to its name. diff --git a/cardinal/server/handler/query.go b/cardinal/server/handler/query.go index 6c61cf414..8673d571e 100644 --- a/cardinal/server/handler/query.go +++ b/cardinal/server/handler/query.go @@ -21,7 +21,7 @@ import ( func PostQuery(world servertypes.ProviderWorld) func(*fiber.Ctx) error { return func(ctx *fiber.Ctx) error { ctx.Set("Content-Type", "application/json") - resBz, err := world.QueryHandler(ctx.Params("name"), ctx.Params("group"), ctx.Body()) + resBz, err := world.QueryHandler(ctx.Params("name"), ctx.Body()) if err != nil { return fiber.NewError(fiber.StatusNotFound, "query not found") } diff --git a/cardinal/server/types/provider.go b/cardinal/server/types/provider.go index d7d6be9ef..3078f6253 100644 --- a/cardinal/server/types/provider.go +++ b/cardinal/server/types/provider.go @@ -16,7 +16,7 @@ type ProviderWorld interface { Namespace() string GetComponentByName(name string) (types.ComponentMetadata, error) StoreReader() gamestate.Reader - QueryHandler(name string, group string, bz []byte) ([]byte, error) + QueryHandler(name string, bz []byte) ([]byte, error) CurrentTick() uint64 ReceiptHistorySize() uint64 GetTransactionReceiptsForTick(tick uint64) ([]receipt.Receipt, error) diff --git a/cardinal/world.go b/cardinal/world.go index 556a12355..8e5e6368b 100644 --- a/cardinal/world.go +++ b/cardinal/world.go @@ -181,7 +181,6 @@ func NewWorld(opts ...WorldOption) (*World, error) { ) } } - world.QueryManager.BuildQueryIndex(world) return world, nil } From 728bd13bcc53f070930b35ee06a182398352ce9b Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Fri, 10 May 2024 15:21:05 -0700 Subject: [PATCH 40/76] moved code block into EvaluateCQL --- cardinal/server/handler/cql.go | 19 +------------------ cardinal/server/types/provider.go | 3 +-- cardinal/world.go | 21 +++++++++++++++++++-- 3 files changed, 21 insertions(+), 22 deletions(-) diff --git a/cardinal/server/handler/cql.go b/cardinal/server/handler/cql.go index 6d41a1745..b8c9aa4bf 100644 --- a/cardinal/server/handler/cql.go +++ b/cardinal/server/handler/cql.go @@ -5,7 +5,6 @@ import "C" import ( "github.com/gofiber/fiber/v2" - "pkg.world.dev/world-engine/cardinal/server/handler/cql" servertypes "pkg.world.dev/world-engine/cardinal/server/types" "pkg.world.dev/world-engine/cardinal/types" ) @@ -35,23 +34,7 @@ func PostCQL( if err := ctx.BodyParser(req); err != nil { return err } - - // getComponentByName is a wrapper function that casts component.ComponentMetadata from ctx.getComponentByName - // to types.Component - getComponentByName := func(name string) (types.Component, error) { - comp, err := world.GetComponentByName(name) - if err != nil { - return nil, err - } - return comp, nil - } - - // Parse the CQL string into a filter - resultFilter, err := cql.Parse(req.CQL, getComponentByName) - if err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) - } - result, eachError, searchErr := world.EvaluateCQL(resultFilter) + result, eachError, searchErr := world.EvaluateCQL(req.CQL) if searchErr != nil { return fiber.NewError(fiber.StatusInternalServerError, searchErr.Error()) } diff --git a/cardinal/server/types/provider.go b/cardinal/server/types/provider.go index 3078f6253..a31421994 100644 --- a/cardinal/server/types/provider.go +++ b/cardinal/server/types/provider.go @@ -3,7 +3,6 @@ package types import ( "pkg.world.dev/world-engine/cardinal/gamestate" "pkg.world.dev/world-engine/cardinal/receipt" - "pkg.world.dev/world-engine/cardinal/search/filter" "pkg.world.dev/world-engine/cardinal/types" "pkg.world.dev/world-engine/cardinal/types/engine" "pkg.world.dev/world-engine/sign" @@ -20,7 +19,7 @@ type ProviderWorld interface { CurrentTick() uint64 ReceiptHistorySize() uint64 GetTransactionReceiptsForTick(tick uint64) ([]receipt.Receipt, error) - EvaluateCQL(filter filter.ComponentFilter) ([]types.CqlData, error, error) + EvaluateCQL(cql string) ([]types.CqlData, error, error) GetDebugState() (types.DebugStateResponse, error, error) BuildQueryFields() []engine.FieldDetail } diff --git a/cardinal/world.go b/cardinal/world.go index 8e5e6368b..999aff4d3 100644 --- a/cardinal/world.go +++ b/cardinal/world.go @@ -24,6 +24,7 @@ import ( "pkg.world.dev/world-engine/cardinal/router" "pkg.world.dev/world-engine/cardinal/search/filter" "pkg.world.dev/world-engine/cardinal/server" + "pkg.world.dev/world-engine/cardinal/server/handler/cql" servertypes "pkg.world.dev/world-engine/cardinal/server/types" "pkg.world.dev/world-engine/cardinal/server/utils" "pkg.world.dev/world-engine/cardinal/statsd" @@ -675,11 +676,27 @@ func (w *World) ReceiptHistorySize() uint64 { return w.receiptHistory.Size() } -func (w *World) EvaluateCQL(filter filter.ComponentFilter) ([]types.CqlData, error, error) { +func (w *World) EvaluateCQL(cqlString string) ([]types.CqlData, error, error) { + + // getComponentByName is a wrapper function that casts component.ComponentMetadata from ctx.getComponentByName + // to types.Component + getComponentByName := func(name string) (types.Component, error) { + comp, err := w.GetComponentByName(name) + if err != nil { + return nil, err + } + return comp, nil + } + + // Parse the CQL string into a filter + cqlFilter, err := cql.Parse(cqlString, getComponentByName) + if err != nil { + return nil, nil, eris.Errorf("failed to parse cql string: %s", cqlString) + } result := make([]types.CqlData, 0) var eachError error wCtx := NewReadOnlyWorldContext(w) - searchErr := w.Search(filter).Each(wCtx, + searchErr := w.Search(cqlFilter).Each(wCtx, func(id types.EntityID) bool { components, err := w.StoreReader().GetComponentTypesForEntity(id) if err != nil { From 14d046005d99028b18aa87671f2a2c53e5425348 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Fri, 10 May 2024 17:09:14 -0700 Subject: [PATCH 41/76] move to query_manager --- cardinal/query_manager.go | 19 +++++++++++++++++++ cardinal/world.go | 17 ----------------- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/cardinal/query_manager.go b/cardinal/query_manager.go index a313e1033..51c5dad63 100644 --- a/cardinal/query_manager.go +++ b/cardinal/query_manager.go @@ -2,12 +2,16 @@ package cardinal import ( "github.com/rotisserie/eris" + + "pkg.world.dev/world-engine/cardinal/server/utils" + "pkg.world.dev/world-engine/cardinal/types/engine" ) type QueryManager interface { RegisterQuery(name string, query query) error GetRegisteredQueries() []query GetQueryByName(name string) (query, error) + BuildQueryFields() []engine.FieldDetail } type queryManager struct { @@ -66,3 +70,18 @@ func (m *queryManager) isQueryNameUnique(name string) error { } return nil } + +func (m *queryManager) BuildQueryFields() []engine.FieldDetail { + // Collecting the structure of all queries + queries := m.GetRegisteredQueries() + queriesFields := make([]engine.FieldDetail, 0, len(queries)) + for _, q := range queries { + // Extracting the fields of the q + queriesFields = append(queriesFields, engine.FieldDetail{ + Name: q.Name(), + Fields: q.GetRequestFieldInformation(), + URL: utils.GetQueryURL(q.Group(), q.Name()), + }) + } + return queriesFields +} diff --git a/cardinal/world.go b/cardinal/world.go index 999aff4d3..fab124252 100644 --- a/cardinal/world.go +++ b/cardinal/world.go @@ -26,11 +26,9 @@ import ( "pkg.world.dev/world-engine/cardinal/server" "pkg.world.dev/world-engine/cardinal/server/handler/cql" servertypes "pkg.world.dev/world-engine/cardinal/server/types" - "pkg.world.dev/world-engine/cardinal/server/utils" "pkg.world.dev/world-engine/cardinal/statsd" "pkg.world.dev/world-engine/cardinal/storage/redis" "pkg.world.dev/world-engine/cardinal/types" - "pkg.world.dev/world-engine/cardinal/types/engine" "pkg.world.dev/world-engine/cardinal/types/txpool" "pkg.world.dev/world-engine/cardinal/worldstage" "pkg.world.dev/world-engine/sign" @@ -379,21 +377,6 @@ func (w *World) startServer() { }() } -func (w *World) BuildQueryFields() []engine.FieldDetail { - // Collecting the structure of all queries - queries := w.GetRegisteredQueries() - queriesFields := make([]engine.FieldDetail, 0, len(queries)) - for _, query := range queries { - // Extracting the fields of the query - queriesFields = append(queriesFields, engine.FieldDetail{ - Name: query.Name(), - Fields: query.GetRequestFieldInformation(), - URL: utils.GetQueryURL(query.Group(), query.Name()), - }) - } - return queriesFields -} - func (w *World) startGameLoop(ctx context.Context, tickStart <-chan time.Time, tickDone chan<- uint64) { log.Info().Msg("Game loop started") go func() { From 5be1575c9bfac52216098d54e54a7d4c5386bff8 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Fri, 10 May 2024 17:11:28 -0700 Subject: [PATCH 42/76] lint stuff. --- cardinal/search_test.go | 3 ++- cardinal/world.go | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cardinal/search_test.go b/cardinal/search_test.go index 227580a83..1febfb1bc 100644 --- a/cardinal/search_test.go +++ b/cardinal/search_test.go @@ -485,7 +485,8 @@ func TestWhereClauseOnSearch(t *testing.T) { _, err = cardinal.CreateMany(worldCtx, 10, AlphaTest{}, BetaTest{}, GammaTest{}) assert.NilError(t, err) - q1 := cardinal.NewSearch().Entity(filter.All()).Where(func(wCtx cardinal.WorldContext, id types.EntityID) (bool, error) { + q1 := cardinal.NewSearch().Entity(filter.All()).Where(func( + wCtx cardinal.WorldContext, id types.EntityID) (bool, error) { _, err := cardinal.GetComponent[AlphaTest](wCtx, id) if err != nil { return false, err diff --git a/cardinal/world.go b/cardinal/world.go index fab124252..a216db08e 100644 --- a/cardinal/world.go +++ b/cardinal/world.go @@ -660,7 +660,6 @@ func (w *World) ReceiptHistorySize() uint64 { } func (w *World) EvaluateCQL(cqlString string) ([]types.CqlData, error, error) { - // getComponentByName is a wrapper function that casts component.ComponentMetadata from ctx.getComponentByName // to types.Component getComponentByName := func(name string) (types.Component, error) { From d3cc295dd8edd2f94d2d020b71f5d78d202d1ca0 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Mon, 13 May 2024 10:48:43 -0700 Subject: [PATCH 43/76] change GetDebugState to return single error. --- cardinal/server/handler/debug.go | 12 ++++-------- cardinal/server/types/provider.go | 2 +- cardinal/world.go | 10 ++++++++-- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/cardinal/server/handler/debug.go b/cardinal/server/handler/debug.go index 4f49e9414..587dad6db 100644 --- a/cardinal/server/handler/debug.go +++ b/cardinal/server/handler/debug.go @@ -19,15 +19,11 @@ type DebugStateResponse = types.DebugStateResponse func GetState(world servertypes.ProviderWorld) func(*fiber.Ctx) error { return func(ctx *fiber.Ctx) error { var result DebugStateResponse - var eachClosureErr error - var searchEachErr error - result, eachClosureErr, searchEachErr = world.GetDebugState() - if eachClosureErr != nil { - return eachClosureErr - } - if searchEachErr != nil { - return searchEachErr + result, err := world.GetDebugState() + if err != nil { + return err } + return ctx.JSON(&result) } } diff --git a/cardinal/server/types/provider.go b/cardinal/server/types/provider.go index a31421994..ea0fcfda5 100644 --- a/cardinal/server/types/provider.go +++ b/cardinal/server/types/provider.go @@ -20,6 +20,6 @@ type ProviderWorld interface { ReceiptHistorySize() uint64 GetTransactionReceiptsForTick(tick uint64) ([]receipt.Receipt, error) EvaluateCQL(cql string) ([]types.CqlData, error, error) - GetDebugState() (types.DebugStateResponse, error, error) + GetDebugState() (types.DebugStateResponse, error) BuildQueryFields() []engine.FieldDetail } diff --git a/cardinal/world.go b/cardinal/world.go index a216db08e..38df7a2a5 100644 --- a/cardinal/world.go +++ b/cardinal/world.go @@ -548,7 +548,7 @@ func (w *World) UseNonce(signerAddress string, nonce uint64) error { return w.redisStorage.UseNonce(signerAddress, nonce) } -func (w *World) GetDebugState() (types.DebugStateResponse, error, error) { +func (w *World) GetDebugState() (types.DebugStateResponse, error) { result := make(types.DebugStateResponse, 0) s := w.Search(filter.All()) var eachClosureErr error @@ -576,7 +576,13 @@ func (w *World) GetDebugState() (types.DebugStateResponse, error, error) { return true }, ) - return result, eachClosureErr, searchEachErr + if eachClosureErr != nil { + return nil, eachClosureErr + } + if searchEachErr != nil { + return nil, searchEachErr + } + return result, nil } func (w *World) Namespace() string { From ad204649f5f734cde65db7ad323f0fa0c484b44a Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Mon, 13 May 2024 11:32:02 -0700 Subject: [PATCH 44/76] make test.mk original for swagger-check. --- makefiles/test.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/makefiles/test.mk b/makefiles/test.mk index dbf1e9407..820cccc64 100644 --- a/makefiles/test.mk +++ b/makefiles/test.mk @@ -108,7 +108,7 @@ swagger-check: @echo "--> Generate latest Swagger specs" mkdir -p .tmp/swagger - swag init -g cardinal/server/server.go -o .tmp/swagger + swag init -g cardinal/server/server.go -o .tmp/swagger --parseInternal --parseDependency @echo "--> Compare existing and latest Swagger specs" docker run --rm -v ./:/local-repo ghcr.io/argus-labs/devops-infra-swagger-diff:2.0.0 \ From fb23e3bf785b4e61ef6a3b7c895cbaada7c36651 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Mon, 13 May 2024 11:45:13 -0700 Subject: [PATCH 45/76] better error handling. --- cardinal/query_manager.go | 2 +- cardinal/server/handler/query.go | 6 +++++- cardinal/types/engine/query.go | 14 ++++++++++++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/cardinal/query_manager.go b/cardinal/query_manager.go index 51c5dad63..b280471b9 100644 --- a/cardinal/query_manager.go +++ b/cardinal/query_manager.go @@ -49,7 +49,7 @@ func (m *queryManager) GetRegisteredQueries() []query { func (w *World) QueryHandler(name string, bz []byte) ([]byte, error) { q, err := w.GetQueryByName(name) if err != nil { - return nil, eris.Errorf("could not find query with name: %s", name) + return nil, eris.Wrap(engine.NewQueryNotFoundError(name), "") } wCtx := NewReadOnlyWorldContext(w) return q.handleQueryRaw(wCtx, bz) diff --git a/cardinal/server/handler/query.go b/cardinal/server/handler/query.go index 8673d571e..c2ba4b14a 100644 --- a/cardinal/server/handler/query.go +++ b/cardinal/server/handler/query.go @@ -2,8 +2,10 @@ package handler import ( "github.com/gofiber/fiber/v2" + "github.com/rotisserie/eris" servertypes "pkg.world.dev/world-engine/cardinal/server/types" + "pkg.world.dev/world-engine/cardinal/types/engine" ) // PostQuery godoc @@ -22,8 +24,10 @@ func PostQuery(world servertypes.ProviderWorld) func(*fiber.Ctx) error { return func(ctx *fiber.Ctx) error { ctx.Set("Content-Type", "application/json") resBz, err := world.QueryHandler(ctx.Params("name"), ctx.Body()) - if err != nil { + if eris.Is(err, &engine.QueryNotFoundError{}) { return fiber.NewError(fiber.StatusNotFound, "query not found") + } else if err != nil { + return fiber.NewError(fiber.StatusBadRequest, "encountered an error in query: "+err.Error()) } return ctx.Send(resBz) } diff --git a/cardinal/types/engine/query.go b/cardinal/types/engine/query.go index c2b333560..b28e7c354 100644 --- a/cardinal/types/engine/query.go +++ b/cardinal/types/engine/query.go @@ -1,3 +1,17 @@ package engine +import "fmt" + type QueryHandler = func(name string, group string, bz []byte) ([]byte, error) + +type QueryNotFoundError struct { + name string +} + +func NewQueryNotFoundError(name string) *QueryNotFoundError { + return &QueryNotFoundError{name: name} +} + +func (e *QueryNotFoundError) Error() string { + return fmt.Sprintf("could not find query with name: %s", e.name) +} From 3006832d06388757b242e6b080603ff89a44fb37 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Mon, 13 May 2024 11:47:59 -0700 Subject: [PATCH 46/76] add comment. --- cardinal/types/cql.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cardinal/types/cql.go b/cardinal/types/cql.go index db487ff02..3eac8f2e8 100644 --- a/cardinal/types/cql.go +++ b/cardinal/types/cql.go @@ -2,6 +2,7 @@ package types import "encoding/json" +// CqlData is the json result type that is returned to the user after executing cql. type CqlData struct { ID EntityID `json:"id"` Data []json.RawMessage `json:"data" swaggertype:"object"` From bdec3c216036b5516f6a1de57abf34f1857384c0 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Mon, 13 May 2024 12:23:44 -0700 Subject: [PATCH 47/76] mover some types out of engine. --- cardinal/query_manager.go | 9 +++++---- cardinal/server/handler/world.go | 11 +++++------ cardinal/server/server_test.go | 9 ++++----- cardinal/server/types/provider.go | 3 +-- cardinal/types/{engine => }/info.go | 3 ++- 5 files changed, 17 insertions(+), 18 deletions(-) rename cardinal/types/{engine => }/info.go (86%) diff --git a/cardinal/query_manager.go b/cardinal/query_manager.go index b280471b9..7bc911a4c 100644 --- a/cardinal/query_manager.go +++ b/cardinal/query_manager.go @@ -4,6 +4,7 @@ import ( "github.com/rotisserie/eris" "pkg.world.dev/world-engine/cardinal/server/utils" + "pkg.world.dev/world-engine/cardinal/types" "pkg.world.dev/world-engine/cardinal/types/engine" ) @@ -11,7 +12,7 @@ type QueryManager interface { RegisterQuery(name string, query query) error GetRegisteredQueries() []query GetQueryByName(name string) (query, error) - BuildQueryFields() []engine.FieldDetail + BuildQueryFields() []types.FieldDetail } type queryManager struct { @@ -71,13 +72,13 @@ func (m *queryManager) isQueryNameUnique(name string) error { return nil } -func (m *queryManager) BuildQueryFields() []engine.FieldDetail { +func (m *queryManager) BuildQueryFields() []types.FieldDetail { // Collecting the structure of all queries queries := m.GetRegisteredQueries() - queriesFields := make([]engine.FieldDetail, 0, len(queries)) + queriesFields := make([]types.FieldDetail, 0, len(queries)) for _, q := range queries { // Extracting the fields of the q - queriesFields = append(queriesFields, engine.FieldDetail{ + queriesFields = append(queriesFields, types.FieldDetail{ Name: q.Name(), Fields: q.GetRequestFieldInformation(), URL: utils.GetQueryURL(q.Group(), q.Name()), diff --git a/cardinal/server/handler/world.go b/cardinal/server/handler/world.go index 65c6f2637..9c3c8d2de 100644 --- a/cardinal/server/handler/world.go +++ b/cardinal/server/handler/world.go @@ -8,10 +8,9 @@ import ( servertypes "pkg.world.dev/world-engine/cardinal/server/types" "pkg.world.dev/world-engine/cardinal/server/utils" "pkg.world.dev/world-engine/cardinal/types" - "pkg.world.dev/world-engine/cardinal/types/engine" ) -type GetWorldResponse = engine.GetWorldResponse +type GetWorldResponse = types.GetWorldResponse // GetWorld godoc // @@ -29,20 +28,20 @@ func GetWorld( namespace string, ) func(*fiber.Ctx) error { // Collecting name of all registered components - comps := make([]engine.FieldDetail, 0, len(components)) + comps := make([]types.FieldDetail, 0, len(components)) for _, component := range components { c, _ := component.Decode(component.GetSchema()) - comps = append(comps, engine.FieldDetail{ + comps = append(comps, types.FieldDetail{ Name: component.Name(), Fields: types.GetFieldInformation(reflect.TypeOf(c)), }) } // Collecting the structure of all messages - messagesFields := make([]engine.FieldDetail, 0, len(messages)) + messagesFields := make([]types.FieldDetail, 0, len(messages)) for _, message := range messages { // Extracting the fields of the message - messagesFields = append(messagesFields, engine.FieldDetail{ + messagesFields = append(messagesFields, types.FieldDetail{ Name: message.Name(), Fields: message.GetInFieldInformation(), URL: utils.GetTxURL(message.Group(), message.Name()), diff --git a/cardinal/server/server_test.go b/cardinal/server/server_test.go index 5cd5221ce..9eba2345f 100644 --- a/cardinal/server/server_test.go +++ b/cardinal/server/server_test.go @@ -24,7 +24,6 @@ import ( "pkg.world.dev/world-engine/cardinal/server/utils" "pkg.world.dev/world-engine/cardinal/testutils" "pkg.world.dev/world-engine/cardinal/types" - "pkg.world.dev/world-engine/cardinal/types/engine" "pkg.world.dev/world-engine/sign" ) @@ -96,7 +95,7 @@ func (s *ServerTestSuite) TestGetWorld() { s.setupWorld() s.fixture.DoTick() res := s.fixture.Get("/world") - var result engine.GetWorldResponse + var result types.GetWorldResponse err := json.Unmarshal([]byte(s.readBody(res.Body)), &result) s.Require().NoError(err) comps := s.world.GetRegisteredComponents() @@ -109,17 +108,17 @@ func (s *ServerTestSuite) TestGetWorld() { // check that the component, message, query name are in the list for _, comp := range comps { - assert.True(s.T(), slices.ContainsFunc(result.Components, func(field engine.FieldDetail) bool { + assert.True(s.T(), slices.ContainsFunc(result.Components, func(field types.FieldDetail) bool { return comp.Name() == field.Name })) } for _, msg := range msgs { - assert.True(s.T(), slices.ContainsFunc(result.Messages, func(field engine.FieldDetail) bool { + assert.True(s.T(), slices.ContainsFunc(result.Messages, func(field types.FieldDetail) bool { return msg.Name() == field.Name })) } for _, query := range queries { - assert.True(s.T(), slices.ContainsFunc(result.Queries, func(field engine.FieldDetail) bool { + assert.True(s.T(), slices.ContainsFunc(result.Queries, func(field types.FieldDetail) bool { return query.Name() == field.Name })) } diff --git a/cardinal/server/types/provider.go b/cardinal/server/types/provider.go index ea0fcfda5..91b968949 100644 --- a/cardinal/server/types/provider.go +++ b/cardinal/server/types/provider.go @@ -4,7 +4,6 @@ import ( "pkg.world.dev/world-engine/cardinal/gamestate" "pkg.world.dev/world-engine/cardinal/receipt" "pkg.world.dev/world-engine/cardinal/types" - "pkg.world.dev/world-engine/cardinal/types/engine" "pkg.world.dev/world-engine/sign" ) @@ -21,5 +20,5 @@ type ProviderWorld interface { GetTransactionReceiptsForTick(tick uint64) ([]receipt.Receipt, error) EvaluateCQL(cql string) ([]types.CqlData, error, error) GetDebugState() (types.DebugStateResponse, error) - BuildQueryFields() []engine.FieldDetail + BuildQueryFields() []types.FieldDetail } diff --git a/cardinal/types/engine/info.go b/cardinal/types/info.go similarity index 86% rename from cardinal/types/engine/info.go rename to cardinal/types/info.go index 0ee8bd1b5..fd70d1ca9 100644 --- a/cardinal/types/engine/info.go +++ b/cardinal/types/info.go @@ -1,4 +1,4 @@ -package engine +package types type GetWorldResponse struct { Namespace string `json:"namespace"` @@ -7,6 +7,7 @@ type GetWorldResponse struct { Queries []FieldDetail `json:"queries"` } +// FieldDetail represents a field from a url request. type FieldDetail struct { Name string `json:"name"` // name of the message or query Fields map[string]any `json:"fields"` // variable name and type From 5825ccd859913295e9475f683198564f93353243 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Mon, 13 May 2024 13:35:59 -0700 Subject: [PATCH 48/76] Move GetWorldResponse to server. --- cardinal/query_manager.go | 3 +-- cardinal/server/handler/query.go | 4 ++-- cardinal/server/handler/world.go | 2 +- cardinal/server/server_test.go | 3 ++- cardinal/server/types/provider.go | 9 +++++++++ cardinal/types/info.go | 7 ------- cardinal/types/{engine => }/query.go | 2 +- 7 files changed, 16 insertions(+), 14 deletions(-) rename cardinal/types/{engine => }/query.go (96%) diff --git a/cardinal/query_manager.go b/cardinal/query_manager.go index 7bc911a4c..969256517 100644 --- a/cardinal/query_manager.go +++ b/cardinal/query_manager.go @@ -5,7 +5,6 @@ import ( "pkg.world.dev/world-engine/cardinal/server/utils" "pkg.world.dev/world-engine/cardinal/types" - "pkg.world.dev/world-engine/cardinal/types/engine" ) type QueryManager interface { @@ -50,7 +49,7 @@ func (m *queryManager) GetRegisteredQueries() []query { func (w *World) QueryHandler(name string, bz []byte) ([]byte, error) { q, err := w.GetQueryByName(name) if err != nil { - return nil, eris.Wrap(engine.NewQueryNotFoundError(name), "") + return nil, eris.Wrap(types.NewQueryNotFoundError(name), "") } wCtx := NewReadOnlyWorldContext(w) return q.handleQueryRaw(wCtx, bz) diff --git a/cardinal/server/handler/query.go b/cardinal/server/handler/query.go index c2ba4b14a..3565d9d90 100644 --- a/cardinal/server/handler/query.go +++ b/cardinal/server/handler/query.go @@ -5,7 +5,7 @@ import ( "github.com/rotisserie/eris" servertypes "pkg.world.dev/world-engine/cardinal/server/types" - "pkg.world.dev/world-engine/cardinal/types/engine" + "pkg.world.dev/world-engine/cardinal/types" ) // PostQuery godoc @@ -24,7 +24,7 @@ func PostQuery(world servertypes.ProviderWorld) func(*fiber.Ctx) error { return func(ctx *fiber.Ctx) error { ctx.Set("Content-Type", "application/json") resBz, err := world.QueryHandler(ctx.Params("name"), ctx.Body()) - if eris.Is(err, &engine.QueryNotFoundError{}) { + if eris.Is(err, &types.QueryNotFoundError{}) { return fiber.NewError(fiber.StatusNotFound, "query not found") } else if err != nil { return fiber.NewError(fiber.StatusBadRequest, "encountered an error in query: "+err.Error()) diff --git a/cardinal/server/handler/world.go b/cardinal/server/handler/world.go index 9c3c8d2de..2def3b47b 100644 --- a/cardinal/server/handler/world.go +++ b/cardinal/server/handler/world.go @@ -10,7 +10,7 @@ import ( "pkg.world.dev/world-engine/cardinal/types" ) -type GetWorldResponse = types.GetWorldResponse +type GetWorldResponse = servertypes.GetWorldResponse // GetWorld godoc // diff --git a/cardinal/server/server_test.go b/cardinal/server/server_test.go index 9eba2345f..629badfbb 100644 --- a/cardinal/server/server_test.go +++ b/cardinal/server/server_test.go @@ -21,6 +21,7 @@ import ( "pkg.world.dev/world-engine/cardinal" "pkg.world.dev/world-engine/cardinal/persona/msg" "pkg.world.dev/world-engine/cardinal/server/handler" + servertypes "pkg.world.dev/world-engine/cardinal/server/types" "pkg.world.dev/world-engine/cardinal/server/utils" "pkg.world.dev/world-engine/cardinal/testutils" "pkg.world.dev/world-engine/cardinal/types" @@ -95,7 +96,7 @@ func (s *ServerTestSuite) TestGetWorld() { s.setupWorld() s.fixture.DoTick() res := s.fixture.Get("/world") - var result types.GetWorldResponse + var result servertypes.GetWorldResponse err := json.Unmarshal([]byte(s.readBody(res.Body)), &result) s.Require().NoError(err) comps := s.world.GetRegisteredComponents() diff --git a/cardinal/server/types/provider.go b/cardinal/server/types/provider.go index 91b968949..42eec9dff 100644 --- a/cardinal/server/types/provider.go +++ b/cardinal/server/types/provider.go @@ -22,3 +22,12 @@ type ProviderWorld interface { GetDebugState() (types.DebugStateResponse, error) BuildQueryFields() []types.FieldDetail } + +// GetWorldResponse is a type representing the json super structure that contains +// all info about the world. +type GetWorldResponse struct { + Namespace string `json:"namespace"` + Components []types.FieldDetail `json:"components"` // list of component names + Messages []types.FieldDetail `json:"messages"` + Queries []types.FieldDetail `json:"queries"` +} diff --git a/cardinal/types/info.go b/cardinal/types/info.go index fd70d1ca9..0f5344cae 100644 --- a/cardinal/types/info.go +++ b/cardinal/types/info.go @@ -1,12 +1,5 @@ package types -type GetWorldResponse struct { - Namespace string `json:"namespace"` - Components []FieldDetail `json:"components"` // list of component names - Messages []FieldDetail `json:"messages"` - Queries []FieldDetail `json:"queries"` -} - // FieldDetail represents a field from a url request. type FieldDetail struct { Name string `json:"name"` // name of the message or query diff --git a/cardinal/types/engine/query.go b/cardinal/types/query.go similarity index 96% rename from cardinal/types/engine/query.go rename to cardinal/types/query.go index b28e7c354..78990ac1d 100644 --- a/cardinal/types/engine/query.go +++ b/cardinal/types/query.go @@ -1,4 +1,4 @@ -package engine +package types import "fmt" From 00f5d83c2f94b4125984b34a50a3eebe3af1749b Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Mon, 13 May 2024 16:40:27 -0700 Subject: [PATCH 49/76] change all eCtx to wCtx. --- cardinal/composedsearch.go | 76 +++++++++++++++---------------- cardinal/engine_test.go | 4 +- cardinal/query_manager.go | 2 +- cardinal/search.go | 56 +++++++++++------------ cardinal/server/handler/query.go | 2 +- cardinal/server/types/provider.go | 2 +- 6 files changed, 71 insertions(+), 71 deletions(-) diff --git a/cardinal/composedsearch.go b/cardinal/composedsearch.go index d81b15ac7..e73575ab6 100644 --- a/cardinal/composedsearch.go +++ b/cardinal/composedsearch.go @@ -19,19 +19,19 @@ type NotSearch struct { search Searchable } -func (orSearch *OrSearch) evaluateSearch(eCtx WorldContext) []types.ArchetypeID { +func (orSearch *OrSearch) evaluateSearch(wCtx WorldContext) []types.ArchetypeID { acc := make([]types.ArchetypeID, 0) for _, search := range orSearch.searches { - acc = append(acc, search.evaluateSearch(eCtx)...) + acc = append(acc, search.evaluateSearch(wCtx)...) } return acc } -func (orSearch *OrSearch) Each(eCtx WorldContext, callback CallbackFn) error { +func (orSearch *OrSearch) Each(wCtx WorldContext, callback CallbackFn) error { // deduplicate idCount := make(map[types.EntityID]int) for _, search := range orSearch.searches { - subids, err := search.Collect(eCtx) + subids, err := search.Collect(wCtx) if err != nil { return err } @@ -56,12 +56,12 @@ func (orSearch *OrSearch) Each(eCtx WorldContext, callback CallbackFn) error { return nil } -func (orSearch *OrSearch) Collect(eCtx WorldContext) ([]types.EntityID, error) { +func (orSearch *OrSearch) Collect(wCtx WorldContext) ([]types.EntityID, error) { // deduplicate idExists := make(map[types.EntityID]bool) res := make([]types.EntityID, 0) for _, search := range orSearch.searches { - ids, err := search.Collect(eCtx) + ids, err := search.Collect(wCtx) if err != nil { return nil, err } @@ -79,8 +79,8 @@ func (orSearch *OrSearch) Collect(eCtx WorldContext) ([]types.EntityID, error) { return res, nil } -func (orSearch *OrSearch) First(eCtx WorldContext) (types.EntityID, error) { - ids, err := orSearch.Collect(eCtx) +func (orSearch *OrSearch) First(wCtx WorldContext) (types.EntityID, error) { + ids, err := orSearch.Collect(wCtx) if err != nil { return 0, err } @@ -90,27 +90,27 @@ func (orSearch *OrSearch) First(eCtx WorldContext) (types.EntityID, error) { return ids[0], nil } -func (orSearch *OrSearch) MustFirst(eCtx WorldContext) types.EntityID { - id, err := orSearch.First(eCtx) +func (orSearch *OrSearch) MustFirst(wCtx WorldContext) types.EntityID { + id, err := orSearch.First(wCtx) if err != nil { panic("no search results") } return id } -func (orSearch *OrSearch) Count(eCtx WorldContext) (int, error) { - ids, err := orSearch.Collect(eCtx) +func (orSearch *OrSearch) Count(wCtx WorldContext) (int, error) { + ids, err := orSearch.Collect(wCtx) if err != nil { return 0, err } return len(ids), nil } -func (andSearch *AndSearch) Each(eCtx WorldContext, callback CallbackFn) error { +func (andSearch *AndSearch) Each(wCtx WorldContext, callback CallbackFn) error { // count idCount := make(map[types.EntityID]int) for _, search := range andSearch.searches { - subIDs, err := search.Collect(eCtx) + subIDs, err := search.Collect(wCtx) if err != nil { return err } @@ -139,10 +139,10 @@ func (andSearch *AndSearch) Each(eCtx WorldContext, callback CallbackFn) error { return nil } -func (andSearch *AndSearch) Collect(eCtx WorldContext) ([]types.EntityID, error) { +func (andSearch *AndSearch) Collect(wCtx WorldContext) ([]types.EntityID, error) { // filter results := make([]types.EntityID, 0) - err := andSearch.Each(eCtx, func(id types.EntityID) bool { + err := andSearch.Each(wCtx, func(id types.EntityID) bool { results = append(results, id) return true }) @@ -156,8 +156,8 @@ func (andSearch *AndSearch) Collect(eCtx WorldContext) ([]types.EntityID, error) return results, nil } -func (andSearch *AndSearch) First(eCtx WorldContext) (types.EntityID, error) { - ids, err := andSearch.Collect(eCtx) +func (andSearch *AndSearch) First(wCtx WorldContext) (types.EntityID, error) { + ids, err := andSearch.Collect(wCtx) if err != nil { return 0, err } @@ -167,26 +167,26 @@ func (andSearch *AndSearch) First(eCtx WorldContext) (types.EntityID, error) { return ids[0], nil } -func (andSearch *AndSearch) MustFirst(eCtx WorldContext) types.EntityID { - id, err := andSearch.First(eCtx) +func (andSearch *AndSearch) MustFirst(wCtx WorldContext) types.EntityID { + id, err := andSearch.First(wCtx) if err != nil { panic("No search results") } return id } -func (andSearch *AndSearch) Count(eCtx WorldContext) (int, error) { - ids, err := andSearch.Collect(eCtx) +func (andSearch *AndSearch) Count(wCtx WorldContext) (int, error) { + ids, err := andSearch.Collect(wCtx) if err != nil { return 0, err } return len(ids), nil } -func (andSearch *AndSearch) evaluateSearch(eCtx WorldContext) []types.ArchetypeID { +func (andSearch *AndSearch) evaluateSearch(wCtx WorldContext) []types.ArchetypeID { searchCounts := make(map[types.ArchetypeID]int) for _, search := range andSearch.searches { - ids := search.evaluateSearch(eCtx) + ids := search.evaluateSearch(wCtx) for _, id := range ids { searchCounts[id]++ } @@ -200,9 +200,9 @@ func (andSearch *AndSearch) evaluateSearch(eCtx WorldContext) []types.ArchetypeI return acc } -func (notSearch *NotSearch) Each(eCtx WorldContext, callback CallbackFn) error { +func (notSearch *NotSearch) Each(wCtx WorldContext, callback CallbackFn) error { // sort - ids, err := notSearch.Collect(eCtx) + ids, err := notSearch.Collect(wCtx) if err != nil { return err } @@ -217,16 +217,16 @@ func (notSearch *NotSearch) Each(eCtx WorldContext, callback CallbackFn) error { return nil } -func (notSearch *NotSearch) Collect(eCtx WorldContext) ([]types.EntityID, error) { +func (notSearch *NotSearch) Collect(wCtx WorldContext) ([]types.EntityID, error) { // Get all ids allsearch := NewSearch().Entity(filter.All()) - allids, err := allsearch.Collect(eCtx) + allids, err := allsearch.Collect(wCtx) if err != nil { return nil, err } // Get ids to exclude excludedIDsMap := make(map[types.EntityID]bool) - excludedids, err := notSearch.search.Collect(eCtx) + excludedids, err := notSearch.search.Collect(wCtx) if err != nil { return nil, err } @@ -249,8 +249,8 @@ func (notSearch *NotSearch) Collect(eCtx WorldContext) ([]types.EntityID, error) return result, nil } -func (notSearch *NotSearch) First(eCtx WorldContext) (types.EntityID, error) { - ids, err := notSearch.Collect(eCtx) +func (notSearch *NotSearch) First(wCtx WorldContext) (types.EntityID, error) { + ids, err := notSearch.Collect(wCtx) if err != nil { return 0, err } @@ -260,30 +260,30 @@ func (notSearch *NotSearch) First(eCtx WorldContext) (types.EntityID, error) { return ids[0], nil } -func (notSearch *NotSearch) MustFirst(eCtx WorldContext) types.EntityID { - id, err := notSearch.First(eCtx) +func (notSearch *NotSearch) MustFirst(wCtx WorldContext) types.EntityID { + id, err := notSearch.First(wCtx) if err != nil { panic("No search results") } return id } -func (notSearch *NotSearch) Count(eCtx WorldContext) (int, error) { - ids, err := notSearch.Collect(eCtx) +func (notSearch *NotSearch) Count(wCtx WorldContext) (int, error) { + ids, err := notSearch.Collect(wCtx) if err != nil { return 0, err } return len(ids), nil } -func (notSearch *NotSearch) evaluateSearch(eCtx WorldContext) []types.ArchetypeID { +func (notSearch *NotSearch) evaluateSearch(wCtx WorldContext) []types.ArchetypeID { searchBuilder := NewSearch() - allResults := searchBuilder.Entity(filter.All()).evaluateSearch(eCtx) + allResults := searchBuilder.Entity(filter.All()).evaluateSearch(wCtx) allResultsMap := make(map[types.ArchetypeID]bool) for _, result := range allResults { allResultsMap[result] = true } - subResults := notSearch.search.evaluateSearch(eCtx) + subResults := notSearch.search.evaluateSearch(wCtx) finalResult := make([]types.ArchetypeID, 0) for _, subResult := range subResults { _, ok := allResultsMap[subResult] diff --git a/cardinal/engine_test.go b/cardinal/engine_test.go index 53ebed459..c36815c62 100644 --- a/cardinal/engine_test.go +++ b/cardinal/engine_test.go @@ -201,9 +201,9 @@ func TestEVMTxConsume(t *testing.T) { var returnVal FooOut var returnErr error err = cardinal.RegisterSystems(world, - func(eCtx cardinal.WorldContext) error { + func(wCtx cardinal.WorldContext) error { return cardinal.EachMessage[FooIn, FooOut]( - eCtx, func(cardinal.TxData[FooIn]) (FooOut, error) { + wCtx, func(cardinal.TxData[FooIn]) (FooOut, error) { return returnVal, returnErr }, ) diff --git a/cardinal/query_manager.go b/cardinal/query_manager.go index 969256517..ed26a6e87 100644 --- a/cardinal/query_manager.go +++ b/cardinal/query_manager.go @@ -46,7 +46,7 @@ func (m *queryManager) GetRegisteredQueries() []query { return registeredQueries } -func (w *World) QueryHandler(name string, bz []byte) ([]byte, error) { +func (w *World) HandleQuery(name string, bz []byte) ([]byte, error) { q, err := w.GetQueryByName(name) if err != nil { return nil, eris.Wrap(types.NewQueryNotFoundError(name), "") diff --git a/cardinal/search.go b/cardinal/search.go index df079f422..319204fde 100644 --- a/cardinal/search.go +++ b/cardinal/search.go @@ -22,12 +22,12 @@ type EntitySearch interface { } type Searchable interface { - evaluateSearch(eCtx WorldContext) []types.ArchetypeID - Each(eCtx WorldContext, callback CallbackFn) error - First(eCtx WorldContext) (types.EntityID, error) - MustFirst(eCtx WorldContext) types.EntityID - Count(eCtx WorldContext) (int, error) - Collect(eCtx WorldContext) ([]types.EntityID, error) + evaluateSearch(wCtx WorldContext) []types.ArchetypeID + Each(wCtx WorldContext, callback CallbackFn) error + First(wCtx WorldContext) (types.EntityID, error) + MustFirst(wCtx WorldContext) types.EntityID + Count(wCtx WorldContext) (int, error) + Collect(wCtx WorldContext) ([]types.EntityID, error) } type CallbackFn func(types.EntityID) bool @@ -147,11 +147,11 @@ func (s *Search) Where(componentFilter FilterFn) EntitySearch { // Each iterates over all entities that match the search. // If you would like to stop the iteration, return false to the callback. To continue iterating, return true. -func (s *Search) Each(eCtx WorldContext, callback CallbackFn) (err error) { - defer func() { defer panicOnFatalError(eCtx, err) }() +func (s *Search) Each(wCtx WorldContext, callback CallbackFn) (err error) { + defer func() { defer panicOnFatalError(wCtx, err) }() - result := s.evaluateSearch(eCtx) - iter := iterators.NewEntityIterator(0, eCtx.storeReader(), result) + result := s.evaluateSearch(wCtx) + iter := iterators.NewEntityIterator(0, wCtx.storeReader(), result) for iter.HasNext() { entities, err := iter.Next() if err != nil { @@ -160,7 +160,7 @@ func (s *Search) Each(eCtx WorldContext, callback CallbackFn) (err error) { for _, id := range entities { var filterValue bool if s.componentPropertyFilter != nil { - filterValue, err = s.componentPropertyFilter(eCtx, id) + filterValue, err = s.componentPropertyFilter(wCtx, id) if err != nil { continue } @@ -183,9 +183,9 @@ func fastSortIDs(ids []types.EntityID) { slices.Sort(ids) } -func (s *Search) Collect(eCtx WorldContext) ([]types.EntityID, error) { +func (s *Search) Collect(wCtx WorldContext) ([]types.EntityID, error) { acc := make([]types.EntityID, 0) - err := s.Each(eCtx, func(id types.EntityID) bool { + err := s.Each(wCtx, func(id types.EntityID) bool { acc = append(acc, id) return true }) @@ -197,11 +197,11 @@ func (s *Search) Collect(eCtx WorldContext) ([]types.EntityID, error) { } // Count returns the number of entities that match the search. -func (s *Search) Count(eCtx WorldContext) (ret int, err error) { - defer func() { defer panicOnFatalError(eCtx, err) }() +func (s *Search) Count(wCtx WorldContext) (ret int, err error) { + defer func() { defer panicOnFatalError(wCtx, err) }() - result := s.evaluateSearch(eCtx) - iter := iterators.NewEntityIterator(0, eCtx.storeReader(), result) + result := s.evaluateSearch(wCtx) + iter := iterators.NewEntityIterator(0, wCtx.storeReader(), result) for iter.HasNext() { entities, err := iter.Next() if err != nil { @@ -210,7 +210,7 @@ func (s *Search) Count(eCtx WorldContext) (ret int, err error) { for _, id := range entities { var filterValue bool if s.componentPropertyFilter != nil { - filterValue, err = s.componentPropertyFilter(eCtx, id) + filterValue, err = s.componentPropertyFilter(wCtx, id) if err != nil { continue } @@ -226,11 +226,11 @@ func (s *Search) Count(eCtx WorldContext) (ret int, err error) { } // First returns the first entity that matches the search. -func (s *Search) First(eCtx WorldContext) (id types.EntityID, err error) { - defer func() { defer panicOnFatalError(eCtx, err) }() +func (s *Search) First(wCtx WorldContext) (id types.EntityID, err error) { + defer func() { defer panicOnFatalError(wCtx, err) }() - result := s.evaluateSearch(eCtx) - iter := iterators.NewEntityIterator(0, eCtx.storeReader(), result) + result := s.evaluateSearch(wCtx) + iter := iterators.NewEntityIterator(0, wCtx.storeReader(), result) if !iter.HasNext() { return iterators.BadID, eris.Wrap(err, "") } @@ -242,7 +242,7 @@ func (s *Search) First(eCtx WorldContext) (id types.EntityID, err error) { for _, id := range entities { var filterValue bool if s.componentPropertyFilter != nil { - filterValue, err = s.componentPropertyFilter(eCtx, id) + filterValue, err = s.componentPropertyFilter(wCtx, id) if err != nil { continue } @@ -257,19 +257,19 @@ func (s *Search) First(eCtx WorldContext) (id types.EntityID, err error) { return iterators.BadID, eris.Wrap(err, "") } -func (s *Search) MustFirst(eCtx WorldContext) types.EntityID { - id, err := s.First(eCtx) +func (s *Search) MustFirst(wCtx WorldContext) types.EntityID { + id, err := s.First(wCtx) if err != nil { panic("no entity matches the search") } return id } -func (s *Search) evaluateSearch(eCtx WorldContext) []types.ArchetypeID { +func (s *Search) evaluateSearch(wCtx WorldContext) []types.ArchetypeID { cache := s.archMatches - for it := eCtx.storeReader().SearchFrom(s.filter, cache.seen); it.HasNext(); { + for it := wCtx.storeReader().SearchFrom(s.filter, cache.seen); it.HasNext(); { cache.archetypes = append(cache.archetypes, it.Next()) } - cache.seen = eCtx.storeReader().ArchetypeCount() + cache.seen = wCtx.storeReader().ArchetypeCount() return cache.archetypes } diff --git a/cardinal/server/handler/query.go b/cardinal/server/handler/query.go index 3565d9d90..54c8aec0c 100644 --- a/cardinal/server/handler/query.go +++ b/cardinal/server/handler/query.go @@ -23,7 +23,7 @@ import ( func PostQuery(world servertypes.ProviderWorld) func(*fiber.Ctx) error { return func(ctx *fiber.Ctx) error { ctx.Set("Content-Type", "application/json") - resBz, err := world.QueryHandler(ctx.Params("name"), ctx.Body()) + resBz, err := world.HandleQuery(ctx.Params("name"), ctx.Body()) if eris.Is(err, &types.QueryNotFoundError{}) { return fiber.NewError(fiber.StatusNotFound, "query not found") } else if err != nil { diff --git a/cardinal/server/types/provider.go b/cardinal/server/types/provider.go index 42eec9dff..b29047126 100644 --- a/cardinal/server/types/provider.go +++ b/cardinal/server/types/provider.go @@ -14,7 +14,7 @@ type ProviderWorld interface { Namespace() string GetComponentByName(name string) (types.ComponentMetadata, error) StoreReader() gamestate.Reader - QueryHandler(name string, bz []byte) ([]byte, error) + HandleQuery(name string, bz []byte) ([]byte, error) CurrentTick() uint64 ReceiptHistorySize() uint64 GetTransactionReceiptsForTick(tick uint64) ([]receipt.Receipt, error) From 46afa0fc0afc2543629e05d050a4819069a40c36 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Mon, 13 May 2024 16:54:41 -0700 Subject: [PATCH 50/76] rename to a more general type. --- cardinal/server/debug_test.go | 4 ++-- cardinal/server/handler/debug.go | 2 +- cardinal/server/types/provider.go | 2 +- cardinal/types/debug.go | 2 +- cardinal/world.go | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/cardinal/server/debug_test.go b/cardinal/server/debug_test.go index ced02b44b..75a2398b9 100644 --- a/cardinal/server/debug_test.go +++ b/cardinal/server/debug_test.go @@ -24,7 +24,7 @@ func (s *ServerTestSuite) TestDebugStateQuery() { s.Require().NoError(err) s.Require().Equal(res.StatusCode, 200) - var results types.DebugStateResponse + var results types.EntityStateResponse s.Require().NoError(json.NewDecoder(res.Body).Decode(&results)) numOfZeroLocation := 0 @@ -53,7 +53,7 @@ func (s *ServerTestSuite) TestDebugStateQuery_NoState() { res := s.fixture.Post("debug/state", types.DebugStateRequest{}) s.Require().Equal(res.StatusCode, 200) - var results types.DebugStateResponse + var results types.EntityStateResponse s.Require().NoError(json.NewDecoder(res.Body).Decode(&results)) s.Require().Equal(len(results), 0) diff --git a/cardinal/server/handler/debug.go b/cardinal/server/handler/debug.go index 587dad6db..3fb174584 100644 --- a/cardinal/server/handler/debug.go +++ b/cardinal/server/handler/debug.go @@ -7,7 +7,7 @@ import ( "pkg.world.dev/world-engine/cardinal/types" ) -type DebugStateResponse = types.DebugStateResponse +type DebugStateResponse = types.EntityStateResponse // GetState godoc // diff --git a/cardinal/server/types/provider.go b/cardinal/server/types/provider.go index b29047126..71c569ed8 100644 --- a/cardinal/server/types/provider.go +++ b/cardinal/server/types/provider.go @@ -19,7 +19,7 @@ type ProviderWorld interface { ReceiptHistorySize() uint64 GetTransactionReceiptsForTick(tick uint64) ([]receipt.Receipt, error) EvaluateCQL(cql string) ([]types.CqlData, error, error) - GetDebugState() (types.DebugStateResponse, error) + GetDebugState() (types.EntityStateResponse, error) BuildQueryFields() []types.FieldDetail } diff --git a/cardinal/types/debug.go b/cardinal/types/debug.go index 82bedcbb5..e54d6235e 100644 --- a/cardinal/types/debug.go +++ b/cardinal/types/debug.go @@ -9,4 +9,4 @@ type DebugStateElement struct { Components map[string]json.RawMessage `json:"components" swaggertype:"object"` } -type DebugStateResponse []DebugStateElement +type EntityStateResponse []DebugStateElement diff --git a/cardinal/world.go b/cardinal/world.go index 38df7a2a5..65a4dd510 100644 --- a/cardinal/world.go +++ b/cardinal/world.go @@ -548,8 +548,8 @@ func (w *World) UseNonce(signerAddress string, nonce uint64) error { return w.redisStorage.UseNonce(signerAddress, nonce) } -func (w *World) GetDebugState() (types.DebugStateResponse, error) { - result := make(types.DebugStateResponse, 0) +func (w *World) GetDebugState() (types.EntityStateResponse, error) { + result := make(types.EntityStateResponse, 0) s := w.Search(filter.All()) var eachClosureErr error wCtx := NewReadOnlyWorldContext(w) From 572522488bafc696a243bf3a34411601b81ea4f1 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Mon, 13 May 2024 17:00:32 -0700 Subject: [PATCH 51/76] get rid of debug.go --- cardinal/server/debug_test.go | 4 ++-- cardinal/types/debug.go | 12 ------------ cardinal/types/entity.go | 11 +++++++++++ cardinal/world.go | 2 +- 4 files changed, 14 insertions(+), 15 deletions(-) delete mode 100644 cardinal/types/debug.go diff --git a/cardinal/server/debug_test.go b/cardinal/server/debug_test.go index 75a2398b9..0b16bd676 100644 --- a/cardinal/server/debug_test.go +++ b/cardinal/server/debug_test.go @@ -20,7 +20,7 @@ func (s *ServerTestSuite) TestDebugStateQuery() { // This will create 1 additional location for this particular persona tag s.runTx(personaTag, moveMessage, MoveMsgInput{Direction: "up"}) - res := s.fixture.Post("debug/state", types.DebugStateRequest{}) + res := s.fixture.Post("debug/state", types.EntityStateRequest{}) s.Require().NoError(err) s.Require().Equal(res.StatusCode, 200) @@ -50,7 +50,7 @@ func (s *ServerTestSuite) TestDebugStateQuery_NoState() { s.setupWorld() s.fixture.DoTick() - res := s.fixture.Post("debug/state", types.DebugStateRequest{}) + res := s.fixture.Post("debug/state", types.EntityStateRequest{}) s.Require().Equal(res.StatusCode, 200) var results types.EntityStateResponse diff --git a/cardinal/types/debug.go b/cardinal/types/debug.go deleted file mode 100644 index e54d6235e..000000000 --- a/cardinal/types/debug.go +++ /dev/null @@ -1,12 +0,0 @@ -package types - -import "encoding/json" - -type DebugStateRequest struct{} - -type DebugStateElement struct { - ID EntityID `json:"id"` - Components map[string]json.RawMessage `json:"components" swaggertype:"object"` -} - -type EntityStateResponse []DebugStateElement diff --git a/cardinal/types/entity.go b/cardinal/types/entity.go index 3177d7a5d..73297dbae 100644 --- a/cardinal/types/entity.go +++ b/cardinal/types/entity.go @@ -1,3 +1,14 @@ package types +import "encoding/json" + type EntityID uint64 + +type EntityStateResponse []EntityStateElement + +type EntityStateRequest struct{} + +type EntityStateElement struct { + ID EntityID `json:"id"` + Components map[string]json.RawMessage `json:"components" swaggertype:"object"` +} diff --git a/cardinal/world.go b/cardinal/world.go index 65a4dd510..cbd3f3b79 100644 --- a/cardinal/world.go +++ b/cardinal/world.go @@ -560,7 +560,7 @@ func (w *World) GetDebugState() (types.EntityStateResponse, error) { if eachClosureErr != nil { return false } - resultElement := types.DebugStateElement{ + resultElement := types.EntityStateElement{ ID: id, Components: make(map[string]json.RawMessage), } From 0f316bba5833485718e6707d3081599b93144a31 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Mon, 13 May 2024 17:33:29 -0700 Subject: [PATCH 52/76] handle new entity state element type. --- cardinal/gamestate/doc.go | 4 ++-- cardinal/gamestate/manager.go | 6 +++--- cardinal/search/filter/helper.go | 2 +- cardinal/server/debug_test.go | 14 ++++++++------ cardinal/testutils/world.go | 2 +- cardinal/types/entity.go | 4 ++-- cardinal/world.go | 6 +++--- 7 files changed, 20 insertions(+), 18 deletions(-) diff --git a/cardinal/gamestate/doc.go b/cardinal/gamestate/doc.go index 2ac14b5cf..412df73c8 100644 --- a/cardinal/gamestate/doc.go +++ b/cardinal/gamestate/doc.go @@ -69,7 +69,7 @@ number. The in-memory data model roughly matches the model that is stored in redis, but there are some differences: -Components are stored as generic interfaces and not as serialized JSON. +Data are stored as generic interfaces and not as serialized JSON. # Potential Improvements @@ -77,7 +77,7 @@ In redis, the ECB:ACTIVE-ENTITY-IDS and ECB:ARCHETYPE-ID:ENTITY-ID keys contains mapping of one another. The amount of data in redis, and the data written can likely be reduced if we abandon one of these keys and rebuild the other mapping in memory. -In memory, compValues are written to redis during a FinalizeTick cycle. Components that were not actually changed (e.g. +In memory, compValues are written to redis during a FinalizeTick cycle. Data that were not actually changed (e.g. only read operations were performed) are still written to the DB. */ package gamestate diff --git a/cardinal/gamestate/manager.go b/cardinal/gamestate/manager.go index 88c61cf71..ffd45d506 100644 --- a/cardinal/gamestate/manager.go +++ b/cardinal/gamestate/manager.go @@ -15,10 +15,10 @@ type Reader interface { GetComponentForEntity(cType types.ComponentMetadata, id types.EntityID) (any, error) GetComponentForEntityInRawJSON(cType types.ComponentMetadata, id types.EntityID) (json.RawMessage, error) - // Many Components One Entity + // Many Data One Entity GetComponentTypesForEntity(id types.EntityID) ([]types.ComponentMetadata, error) - // One Archetype Many Components + // One Archetype Many Data GetComponentTypesForArchID(archID types.ArchetypeID) ([]types.ComponentMetadata, error) GetArchIDForComponents(components []types.ComponentMetadata) (types.ArchetypeID, error) @@ -34,7 +34,7 @@ type Writer interface { // One Entity RemoveEntity(id types.EntityID) error - // Many Components + // Many Data CreateEntity(comps ...types.ComponentMetadata) (types.EntityID, error) CreateManyEntities(num int, comps ...types.ComponentMetadata) ([]types.EntityID, error) diff --git a/cardinal/search/filter/helper.go b/cardinal/search/filter/helper.go index a85855b28..41a0a5ddd 100644 --- a/cardinal/search/filter/helper.go +++ b/cardinal/search/filter/helper.go @@ -5,7 +5,7 @@ import ( ) // MatchComponentMetadata returns true if the given slice of components contains the given component. -// Components are the same if they have the same Name. +// Data are the same if they have the same Name. func MatchComponentMetadata( components []types.ComponentMetadata, cType types.ComponentMetadata, diff --git a/cardinal/server/debug_test.go b/cardinal/server/debug_test.go index 0b16bd676..6ad76206a 100644 --- a/cardinal/server/debug_test.go +++ b/cardinal/server/debug_test.go @@ -29,17 +29,19 @@ func (s *ServerTestSuite) TestDebugStateQuery() { numOfZeroLocation := 0 numOfNonZeroLocation := 0 - for _, result := range results { - comp := result.Components["location"] + for i, result := range results { + comp := result.Data[0] if comp == nil { continue } var loc LocationComponent s.Require().NoError(json.Unmarshal(comp, &loc)) - if loc.Y == 0 { - numOfZeroLocation++ - } else { - numOfNonZeroLocation++ + if i != 6 { + if loc.Y == 0 { + numOfZeroLocation++ + } else { + numOfNonZeroLocation++ + } } } s.Require().Equal(numOfZeroLocation, wantNumOfZeroLocation) diff --git a/cardinal/testutils/world.go b/cardinal/testutils/world.go index 1ec223d28..95c2a86ae 100644 --- a/cardinal/testutils/world.go +++ b/cardinal/testutils/world.go @@ -92,7 +92,7 @@ func NewTestFixture(t testing.TB, redis *miniredis.Miniredis, opts ...cardinal.W } // StartWorld starts the game world and registers a cleanup function that will shut down -// the cardinal World at the end of the test. Components/Systems/Queries, etc should +// the cardinal World at the end of the test. Data/Systems/Queries, etc should // be registered before calling this function. func (t *TestFixture) StartWorld() { t.startOnce.Do(func() { diff --git a/cardinal/types/entity.go b/cardinal/types/entity.go index 73297dbae..790f475a7 100644 --- a/cardinal/types/entity.go +++ b/cardinal/types/entity.go @@ -9,6 +9,6 @@ type EntityStateResponse []EntityStateElement type EntityStateRequest struct{} type EntityStateElement struct { - ID EntityID `json:"id"` - Components map[string]json.RawMessage `json:"components" swaggertype:"object"` + ID EntityID `json:"id"` + Data []json.RawMessage `json:"data" swaggertype:"object"` } diff --git a/cardinal/world.go b/cardinal/world.go index cbd3f3b79..631c352ee 100644 --- a/cardinal/world.go +++ b/cardinal/world.go @@ -561,8 +561,8 @@ func (w *World) GetDebugState() (types.EntityStateResponse, error) { return false } resultElement := types.EntityStateElement{ - ID: id, - Components: make(map[string]json.RawMessage), + ID: id, + Data: make([]json.RawMessage, 0), } for _, c := range components { var data json.RawMessage @@ -570,7 +570,7 @@ func (w *World) GetDebugState() (types.EntityStateResponse, error) { if eachClosureErr != nil { return false } - resultElement.Components[c.Name()] = data + resultElement.Data = append(resultElement.Data, data) } result = append(result, resultElement) return true From be09497ee2667c9d8d49897b31733d688f12b9aa Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Mon, 13 May 2024 17:37:45 -0700 Subject: [PATCH 53/76] remove cql.go. Consolidate similar type. --- cardinal/server/handler/cql.go | 2 +- cardinal/server/types/provider.go | 2 +- cardinal/types/cql.go | 9 --------- cardinal/world.go | 6 +++--- 4 files changed, 5 insertions(+), 14 deletions(-) delete mode 100644 cardinal/types/cql.go diff --git a/cardinal/server/handler/cql.go b/cardinal/server/handler/cql.go index b8c9aa4bf..873f76266 100644 --- a/cardinal/server/handler/cql.go +++ b/cardinal/server/handler/cql.go @@ -14,7 +14,7 @@ type CQLQueryRequest struct { } type CQLQueryResponse struct { - Results []types.CqlData `json:"results"` + Results []types.EntityStateElement `json:"results"` } // PostCQL godoc diff --git a/cardinal/server/types/provider.go b/cardinal/server/types/provider.go index 71c569ed8..aaf1a5934 100644 --- a/cardinal/server/types/provider.go +++ b/cardinal/server/types/provider.go @@ -18,7 +18,7 @@ type ProviderWorld interface { CurrentTick() uint64 ReceiptHistorySize() uint64 GetTransactionReceiptsForTick(tick uint64) ([]receipt.Receipt, error) - EvaluateCQL(cql string) ([]types.CqlData, error, error) + EvaluateCQL(cql string) ([]types.EntityStateElement, error, error) GetDebugState() (types.EntityStateResponse, error) BuildQueryFields() []types.FieldDetail } diff --git a/cardinal/types/cql.go b/cardinal/types/cql.go deleted file mode 100644 index 3eac8f2e8..000000000 --- a/cardinal/types/cql.go +++ /dev/null @@ -1,9 +0,0 @@ -package types - -import "encoding/json" - -// CqlData is the json result type that is returned to the user after executing cql. -type CqlData struct { - ID EntityID `json:"id"` - Data []json.RawMessage `json:"data" swaggertype:"object"` -} diff --git a/cardinal/world.go b/cardinal/world.go index 631c352ee..10857129d 100644 --- a/cardinal/world.go +++ b/cardinal/world.go @@ -665,7 +665,7 @@ func (w *World) ReceiptHistorySize() uint64 { return w.receiptHistory.Size() } -func (w *World) EvaluateCQL(cqlString string) ([]types.CqlData, error, error) { +func (w *World) EvaluateCQL(cqlString string) ([]types.EntityStateElement, error, error) { // getComponentByName is a wrapper function that casts component.ComponentMetadata from ctx.getComponentByName // to types.Component getComponentByName := func(name string) (types.Component, error) { @@ -681,7 +681,7 @@ func (w *World) EvaluateCQL(cqlString string) ([]types.CqlData, error, error) { if err != nil { return nil, nil, eris.Errorf("failed to parse cql string: %s", cqlString) } - result := make([]types.CqlData, 0) + result := make([]types.EntityStateElement, 0) var eachError error wCtx := NewReadOnlyWorldContext(w) searchErr := w.Search(cqlFilter).Each(wCtx, @@ -691,7 +691,7 @@ func (w *World) EvaluateCQL(cqlString string) ([]types.CqlData, error, error) { eachError = err return false } - resultElement := types.CqlData{ + resultElement := types.EntityStateElement{ ID: id, Data: make([]json.RawMessage, 0), } From 634c5889fafcae6d53cf7bb61a1242b04eda124d Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Mon, 13 May 2024 17:50:07 -0700 Subject: [PATCH 54/76] update swagger. --- cardinal/server/docs/docs.go | 89 ++++++++++++++----------------- cardinal/server/docs/swagger.json | 89 ++++++++++++++----------------- cardinal/server/docs/swagger.yaml | 81 +++++++++++++--------------- makefiles/test.mk | 2 +- 4 files changed, 116 insertions(+), 145 deletions(-) diff --git a/cardinal/server/docs/docs.go b/cardinal/server/docs/docs.go index 29946f2c7..6a126115d 100644 --- a/cardinal/server/docs/docs.go +++ b/cardinal/server/docs/docs.go @@ -32,7 +32,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/handler.CQLQueryRequest" + "$ref": "#/definitions/cardinal_server_handler.CQLQueryRequest" } } ], @@ -40,7 +40,7 @@ const docTemplate = `{ "200": { "description": "Results of the executed CQL query", "schema": { - "$ref": "#/definitions/handler.CQLQueryResponse" + "$ref": "#/definitions/cardinal_server_handler.CQLQueryResponse" } }, "400": { @@ -65,7 +65,7 @@ const docTemplate = `{ "schema": { "type": "array", "items": { - "$ref": "#/definitions/types.DebugStateElement" + "$ref": "#/definitions/pkg_world_dev_world-engine_cardinal_types.EntityStateElement" } } } @@ -100,7 +100,7 @@ const docTemplate = `{ "200": { "description": "Server and game loop status", "schema": { - "$ref": "#/definitions/handler.GetHealthResponse" + "$ref": "#/definitions/cardinal_server_handler.GetHealthResponse" } } } @@ -123,7 +123,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/handler.ListTxReceiptsRequest" + "$ref": "#/definitions/cardinal_server_handler.ListTxReceiptsRequest" } } ], @@ -131,7 +131,7 @@ const docTemplate = `{ "200": { "description": "List of receipts", "schema": { - "$ref": "#/definitions/handler.ListTxReceiptsResponse" + "$ref": "#/definitions/cardinal_server_handler.ListTxReceiptsResponse" } }, "400": { @@ -218,7 +218,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/handler.Transaction" + "$ref": "#/definitions/cardinal_server_handler.Transaction" } } ], @@ -226,7 +226,7 @@ const docTemplate = `{ "200": { "description": "Transaction hash and tick", "schema": { - "$ref": "#/definitions/handler.PostTransactionResponse" + "$ref": "#/definitions/cardinal_server_handler.PostTransactionResponse" } }, "400": { @@ -255,7 +255,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/handler.Transaction" + "$ref": "#/definitions/cardinal_server_handler.Transaction" } } ], @@ -263,7 +263,7 @@ const docTemplate = `{ "200": { "description": "Transaction hash and tick", "schema": { - "$ref": "#/definitions/handler.PostTransactionResponse" + "$ref": "#/definitions/cardinal_server_handler.PostTransactionResponse" } }, "400": { @@ -306,7 +306,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/handler.Transaction" + "$ref": "#/definitions/cardinal_server_handler.Transaction" } } ], @@ -314,7 +314,7 @@ const docTemplate = `{ "200": { "description": "Transaction hash and tick", "schema": { - "$ref": "#/definitions/handler.PostTransactionResponse" + "$ref": "#/definitions/cardinal_server_handler.PostTransactionResponse" } }, "400": { @@ -340,7 +340,7 @@ const docTemplate = `{ "200": { "description": "Details of the game world", "schema": { - "$ref": "#/definitions/handler.GetWorldResponse" + "$ref": "#/definitions/cardinal_server_handler.GetWorldResponse" } }, "400": { @@ -354,24 +354,7 @@ const docTemplate = `{ } }, "definitions": { - "engine.FieldDetail": { - "type": "object", - "properties": { - "fields": { - "description": "variable name and type", - "type": "object", - "additionalProperties": {} - }, - "name": { - "description": "name of the message or query", - "type": "string" - }, - "url": { - "type": "string" - } - } - }, - "handler.CQLQueryRequest": { + "cardinal_server_handler.CQLQueryRequest": { "type": "object", "properties": { "cql": { @@ -379,18 +362,18 @@ const docTemplate = `{ } } }, - "handler.CQLQueryResponse": { + "cardinal_server_handler.CQLQueryResponse": { "type": "object", "properties": { "results": { "type": "array", "items": { - "$ref": "#/definitions/types.CqlData" + "$ref": "#/definitions/pkg_world_dev_world-engine_cardinal_types.EntityStateElement" } } } }, - "handler.GetHealthResponse": { + "cardinal_server_handler.GetHealthResponse": { "type": "object", "properties": { "isGameLoopRunning": { @@ -401,20 +384,20 @@ const docTemplate = `{ } } }, - "handler.GetWorldResponse": { + "cardinal_server_handler.GetWorldResponse": { "type": "object", "properties": { "components": { "description": "list of component names", "type": "array", "items": { - "$ref": "#/definitions/engine.FieldDetail" + "$ref": "#/definitions/pkg_world_dev_world-engine_cardinal_types.FieldDetail" } }, "messages": { "type": "array", "items": { - "$ref": "#/definitions/engine.FieldDetail" + "$ref": "#/definitions/pkg_world_dev_world-engine_cardinal_types.FieldDetail" } }, "namespace": { @@ -423,12 +406,12 @@ const docTemplate = `{ "queries": { "type": "array", "items": { - "$ref": "#/definitions/engine.FieldDetail" + "$ref": "#/definitions/pkg_world_dev_world-engine_cardinal_types.FieldDetail" } } } }, - "handler.ListTxReceiptsRequest": { + "cardinal_server_handler.ListTxReceiptsRequest": { "type": "object", "properties": { "startTick": { @@ -436,7 +419,7 @@ const docTemplate = `{ } } }, - "handler.ListTxReceiptsResponse": { + "cardinal_server_handler.ListTxReceiptsResponse": { "type": "object", "properties": { "endTick": { @@ -445,7 +428,7 @@ const docTemplate = `{ "receipts": { "type": "array", "items": { - "$ref": "#/definitions/handler.ReceiptEntry" + "$ref": "#/definitions/cardinal_server_handler.ReceiptEntry" } }, "startTick": { @@ -453,7 +436,7 @@ const docTemplate = `{ } } }, - "handler.PostTransactionResponse": { + "cardinal_server_handler.PostTransactionResponse": { "type": "object", "properties": { "tick": { @@ -464,7 +447,7 @@ const docTemplate = `{ } } }, - "handler.ReceiptEntry": { + "cardinal_server_handler.ReceiptEntry": { "type": "object", "properties": { "errors": { @@ -482,7 +465,7 @@ const docTemplate = `{ } } }, - "handler.Transaction": { + "cardinal_server_handler.Transaction": { "type": "object", "properties": { "body": { @@ -507,7 +490,7 @@ const docTemplate = `{ } } }, - "types.CqlData": { + "pkg_world_dev_world-engine_cardinal_types.EntityStateElement": { "type": "object", "properties": { "data": { @@ -518,14 +501,20 @@ const docTemplate = `{ } } }, - "types.DebugStateElement": { + "pkg_world_dev_world-engine_cardinal_types.FieldDetail": { "type": "object", "properties": { - "components": { - "type": "object" + "fields": { + "description": "variable name and type", + "type": "object", + "additionalProperties": {} }, - "id": { - "type": "integer" + "name": { + "description": "name of the message or query", + "type": "string" + }, + "url": { + "type": "string" } } } diff --git a/cardinal/server/docs/swagger.json b/cardinal/server/docs/swagger.json index 7f38dbfdd..854790a96 100644 --- a/cardinal/server/docs/swagger.json +++ b/cardinal/server/docs/swagger.json @@ -29,7 +29,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/handler.CQLQueryRequest" + "$ref": "#/definitions/cardinal_server_handler.CQLQueryRequest" } } ], @@ -37,7 +37,7 @@ "200": { "description": "Results of the executed CQL query", "schema": { - "$ref": "#/definitions/handler.CQLQueryResponse" + "$ref": "#/definitions/cardinal_server_handler.CQLQueryResponse" } }, "400": { @@ -62,7 +62,7 @@ "schema": { "type": "array", "items": { - "$ref": "#/definitions/types.DebugStateElement" + "$ref": "#/definitions/pkg_world_dev_world-engine_cardinal_types.EntityStateElement" } } } @@ -97,7 +97,7 @@ "200": { "description": "Server and game loop status", "schema": { - "$ref": "#/definitions/handler.GetHealthResponse" + "$ref": "#/definitions/cardinal_server_handler.GetHealthResponse" } } } @@ -120,7 +120,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/handler.ListTxReceiptsRequest" + "$ref": "#/definitions/cardinal_server_handler.ListTxReceiptsRequest" } } ], @@ -128,7 +128,7 @@ "200": { "description": "List of receipts", "schema": { - "$ref": "#/definitions/handler.ListTxReceiptsResponse" + "$ref": "#/definitions/cardinal_server_handler.ListTxReceiptsResponse" } }, "400": { @@ -215,7 +215,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/handler.Transaction" + "$ref": "#/definitions/cardinal_server_handler.Transaction" } } ], @@ -223,7 +223,7 @@ "200": { "description": "Transaction hash and tick", "schema": { - "$ref": "#/definitions/handler.PostTransactionResponse" + "$ref": "#/definitions/cardinal_server_handler.PostTransactionResponse" } }, "400": { @@ -252,7 +252,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/handler.Transaction" + "$ref": "#/definitions/cardinal_server_handler.Transaction" } } ], @@ -260,7 +260,7 @@ "200": { "description": "Transaction hash and tick", "schema": { - "$ref": "#/definitions/handler.PostTransactionResponse" + "$ref": "#/definitions/cardinal_server_handler.PostTransactionResponse" } }, "400": { @@ -303,7 +303,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/handler.Transaction" + "$ref": "#/definitions/cardinal_server_handler.Transaction" } } ], @@ -311,7 +311,7 @@ "200": { "description": "Transaction hash and tick", "schema": { - "$ref": "#/definitions/handler.PostTransactionResponse" + "$ref": "#/definitions/cardinal_server_handler.PostTransactionResponse" } }, "400": { @@ -337,7 +337,7 @@ "200": { "description": "Details of the game world", "schema": { - "$ref": "#/definitions/handler.GetWorldResponse" + "$ref": "#/definitions/cardinal_server_handler.GetWorldResponse" } }, "400": { @@ -351,24 +351,7 @@ } }, "definitions": { - "engine.FieldDetail": { - "type": "object", - "properties": { - "fields": { - "description": "variable name and type", - "type": "object", - "additionalProperties": {} - }, - "name": { - "description": "name of the message or query", - "type": "string" - }, - "url": { - "type": "string" - } - } - }, - "handler.CQLQueryRequest": { + "cardinal_server_handler.CQLQueryRequest": { "type": "object", "properties": { "cql": { @@ -376,18 +359,18 @@ } } }, - "handler.CQLQueryResponse": { + "cardinal_server_handler.CQLQueryResponse": { "type": "object", "properties": { "results": { "type": "array", "items": { - "$ref": "#/definitions/types.CqlData" + "$ref": "#/definitions/pkg_world_dev_world-engine_cardinal_types.EntityStateElement" } } } }, - "handler.GetHealthResponse": { + "cardinal_server_handler.GetHealthResponse": { "type": "object", "properties": { "isGameLoopRunning": { @@ -398,20 +381,20 @@ } } }, - "handler.GetWorldResponse": { + "cardinal_server_handler.GetWorldResponse": { "type": "object", "properties": { "components": { "description": "list of component names", "type": "array", "items": { - "$ref": "#/definitions/engine.FieldDetail" + "$ref": "#/definitions/pkg_world_dev_world-engine_cardinal_types.FieldDetail" } }, "messages": { "type": "array", "items": { - "$ref": "#/definitions/engine.FieldDetail" + "$ref": "#/definitions/pkg_world_dev_world-engine_cardinal_types.FieldDetail" } }, "namespace": { @@ -420,12 +403,12 @@ "queries": { "type": "array", "items": { - "$ref": "#/definitions/engine.FieldDetail" + "$ref": "#/definitions/pkg_world_dev_world-engine_cardinal_types.FieldDetail" } } } }, - "handler.ListTxReceiptsRequest": { + "cardinal_server_handler.ListTxReceiptsRequest": { "type": "object", "properties": { "startTick": { @@ -433,7 +416,7 @@ } } }, - "handler.ListTxReceiptsResponse": { + "cardinal_server_handler.ListTxReceiptsResponse": { "type": "object", "properties": { "endTick": { @@ -442,7 +425,7 @@ "receipts": { "type": "array", "items": { - "$ref": "#/definitions/handler.ReceiptEntry" + "$ref": "#/definitions/cardinal_server_handler.ReceiptEntry" } }, "startTick": { @@ -450,7 +433,7 @@ } } }, - "handler.PostTransactionResponse": { + "cardinal_server_handler.PostTransactionResponse": { "type": "object", "properties": { "tick": { @@ -461,7 +444,7 @@ } } }, - "handler.ReceiptEntry": { + "cardinal_server_handler.ReceiptEntry": { "type": "object", "properties": { "errors": { @@ -479,7 +462,7 @@ } } }, - "handler.Transaction": { + "cardinal_server_handler.Transaction": { "type": "object", "properties": { "body": { @@ -504,7 +487,7 @@ } } }, - "types.CqlData": { + "pkg_world_dev_world-engine_cardinal_types.EntityStateElement": { "type": "object", "properties": { "data": { @@ -515,14 +498,20 @@ } } }, - "types.DebugStateElement": { + "pkg_world_dev_world-engine_cardinal_types.FieldDetail": { "type": "object", "properties": { - "components": { - "type": "object" + "fields": { + "description": "variable name and type", + "type": "object", + "additionalProperties": {} }, - "id": { - "type": "integer" + "name": { + "description": "name of the message or query", + "type": "string" + }, + "url": { + "type": "string" } } } diff --git a/cardinal/server/docs/swagger.yaml b/cardinal/server/docs/swagger.yaml index 889d43084..0a6a71de7 100644 --- a/cardinal/server/docs/swagger.yaml +++ b/cardinal/server/docs/swagger.yaml @@ -1,78 +1,66 @@ basePath: / definitions: - engine.FieldDetail: - properties: - fields: - additionalProperties: {} - description: variable name and type - type: object - name: - description: name of the message or query - type: string - url: - type: string - type: object - handler.CQLQueryRequest: + cardinal_server_handler.CQLQueryRequest: properties: cql: type: string type: object - handler.CQLQueryResponse: + cardinal_server_handler.CQLQueryResponse: properties: results: items: - $ref: '#/definitions/types.CqlData' + $ref: '#/definitions/pkg_world_dev_world-engine_cardinal_types.EntityStateElement' type: array type: object - handler.GetHealthResponse: + cardinal_server_handler.GetHealthResponse: properties: isGameLoopRunning: type: boolean isServerRunning: type: boolean type: object - handler.GetWorldResponse: + cardinal_server_handler.GetWorldResponse: properties: components: description: list of component names items: - $ref: '#/definitions/engine.FieldDetail' + $ref: '#/definitions/pkg_world_dev_world-engine_cardinal_types.FieldDetail' type: array messages: items: - $ref: '#/definitions/engine.FieldDetail' + $ref: '#/definitions/pkg_world_dev_world-engine_cardinal_types.FieldDetail' type: array namespace: type: string queries: items: - $ref: '#/definitions/engine.FieldDetail' + $ref: '#/definitions/pkg_world_dev_world-engine_cardinal_types.FieldDetail' type: array type: object - handler.ListTxReceiptsRequest: + cardinal_server_handler.ListTxReceiptsRequest: properties: startTick: type: integer type: object - handler.ListTxReceiptsResponse: + cardinal_server_handler.ListTxReceiptsResponse: properties: endTick: type: integer receipts: items: - $ref: '#/definitions/handler.ReceiptEntry' + $ref: '#/definitions/cardinal_server_handler.ReceiptEntry' type: array startTick: type: integer type: object - handler.PostTransactionResponse: + cardinal_server_handler.PostTransactionResponse: properties: tick: type: integer txHash: type: string type: object - handler.ReceiptEntry: + cardinal_server_handler.ReceiptEntry: properties: errors: items: @@ -84,7 +72,7 @@ definitions: txHash: type: string type: object - handler.Transaction: + cardinal_server_handler.Transaction: properties: body: description: json string @@ -101,19 +89,24 @@ definitions: description: hex encoded string type: string type: object - types.CqlData: + pkg_world_dev_world-engine_cardinal_types.EntityStateElement: properties: data: type: object id: type: integer type: object - types.DebugStateElement: + pkg_world_dev_world-engine_cardinal_types.FieldDetail: properties: - components: + fields: + additionalProperties: {} + description: variable name and type type: object - id: - type: integer + name: + description: name of the message or query + type: string + url: + type: string type: object info: contact: {} @@ -132,14 +125,14 @@ paths: name: cql required: true schema: - $ref: '#/definitions/handler.CQLQueryRequest' + $ref: '#/definitions/cardinal_server_handler.CQLQueryRequest' produces: - application/json responses: "200": description: Results of the executed CQL query schema: - $ref: '#/definitions/handler.CQLQueryResponse' + $ref: '#/definitions/cardinal_server_handler.CQLQueryResponse' "400": description: Invalid request parameters schema: @@ -155,7 +148,7 @@ paths: description: List of all entities schema: items: - $ref: '#/definitions/types.DebugStateElement' + $ref: '#/definitions/pkg_world_dev_world-engine_cardinal_types.EntityStateElement' type: array summary: Retrieves a list of all entities in the game state /events: @@ -178,7 +171,7 @@ paths: "200": description: Server and game loop status schema: - $ref: '#/definitions/handler.GetHealthResponse' + $ref: '#/definitions/cardinal_server_handler.GetHealthResponse' summary: Retrieves the status of the server and game loop /query/{queryGroup}/{queryName}: post: @@ -225,14 +218,14 @@ paths: name: ListTxReceiptsRequest required: true schema: - $ref: '#/definitions/handler.ListTxReceiptsRequest' + $ref: '#/definitions/cardinal_server_handler.ListTxReceiptsRequest' produces: - application/json responses: "200": description: List of receipts schema: - $ref: '#/definitions/handler.ListTxReceiptsResponse' + $ref: '#/definitions/cardinal_server_handler.ListTxReceiptsResponse' "400": description: Invalid request body schema: @@ -259,14 +252,14 @@ paths: name: txBody required: true schema: - $ref: '#/definitions/handler.Transaction' + $ref: '#/definitions/cardinal_server_handler.Transaction' produces: - application/json responses: "200": description: Transaction hash and tick schema: - $ref: '#/definitions/handler.PostTransactionResponse' + $ref: '#/definitions/cardinal_server_handler.PostTransactionResponse' "400": description: Invalid request parameter schema: @@ -288,14 +281,14 @@ paths: name: txBody required: true schema: - $ref: '#/definitions/handler.Transaction' + $ref: '#/definitions/cardinal_server_handler.Transaction' produces: - application/json responses: "200": description: Transaction hash and tick schema: - $ref: '#/definitions/handler.PostTransactionResponse' + $ref: '#/definitions/cardinal_server_handler.PostTransactionResponse' "400": description: Invalid request parameter schema: @@ -312,14 +305,14 @@ paths: name: txBody required: true schema: - $ref: '#/definitions/handler.Transaction' + $ref: '#/definitions/cardinal_server_handler.Transaction' produces: - application/json responses: "200": description: Transaction hash and tick schema: - $ref: '#/definitions/handler.PostTransactionResponse' + $ref: '#/definitions/cardinal_server_handler.PostTransactionResponse' "400": description: Invalid request parameter schema: @@ -336,7 +329,7 @@ paths: "200": description: Details of the game world schema: - $ref: '#/definitions/handler.GetWorldResponse' + $ref: '#/definitions/cardinal_server_handler.GetWorldResponse' "400": description: Invalid request parameters schema: diff --git a/makefiles/test.mk b/makefiles/test.mk index 820cccc64..4a04a81bf 100644 --- a/makefiles/test.mk +++ b/makefiles/test.mk @@ -101,7 +101,7 @@ swaggo-install: swagger: $(MAKE) swaggo-install - swag init -g cardinal/server/server.go -o cardinal/server/docs/ + swag init -g cardinal/server/server.go -o cardinal/server/docs/ --parseDependency swagger-check: $(MAKE) swaggo-install From bf5a799a72787443f286ada63929fca1462aaa74 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Mon, 13 May 2024 18:24:32 -0700 Subject: [PATCH 55/76] remove empty file. --- cardinal/types/search.go | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 cardinal/types/search.go diff --git a/cardinal/types/search.go b/cardinal/types/search.go deleted file mode 100644 index 30b3615cd..000000000 --- a/cardinal/types/search.go +++ /dev/null @@ -1,3 +0,0 @@ -package types - -//revive:disable-next-line From b2619cbb15700e81a1510df29ddc12b74e8be141 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Mon, 13 May 2024 18:34:43 -0700 Subject: [PATCH 56/76] Remove GetComponentNameFromContext. --- cardinal/search_test.go | 4 +--- cardinal/util.go | 4 ---- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/cardinal/search_test.go b/cardinal/search_test.go index 1febfb1bc..961f328cf 100644 --- a/cardinal/search_test.go +++ b/cardinal/search_test.go @@ -79,9 +79,7 @@ func TestSearchUsingAllMethods(t *testing.T) { hpids, err := cardinal.CreateMany(worldCtx, 10, HP{}) assert.NilError(t, err) for i, id := range hpids { - c, err := cardinal.GetComponentByNameFromContext(worldCtx, HP{}.Name()) - assert.NilError(t, err) - err = cardinal.GetStoreManagerFromContext(worldCtx).SetComponentForEntity(c, id, HP{amount: i}) + err = cardinal.SetComponent[HP](worldCtx, id, &HP{amount: i}) assert.NilError(t, err) } amt, err := cardinal.NewSearch().Entity(filter.Not(filter.Or( diff --git a/cardinal/util.go b/cardinal/util.go index 76877c33b..f8b36cfbe 100644 --- a/cardinal/util.go +++ b/cardinal/util.go @@ -80,10 +80,6 @@ func GetStoreManagerFromContext(wCtx WorldContext) gamestate.Manager { return wCtx.storeManager() } -func GetComponentByNameFromContext(wCtx WorldContext, name string) (types.ComponentMetadata, error) { - return wCtx.getComponentByName(name) -} - func HandleQuery(wCtx WorldContext, query query, a any) (any, error) { return query.handleQuery(wCtx, a) } From a76c6ddbfed6c7acedb7f526f6435250f183a7ba Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Mon, 13 May 2024 18:39:12 -0700 Subject: [PATCH 57/76] remove queryhandler type. --- cardinal/types/query.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/cardinal/types/query.go b/cardinal/types/query.go index 78990ac1d..2ea143e19 100644 --- a/cardinal/types/query.go +++ b/cardinal/types/query.go @@ -2,8 +2,6 @@ package types import "fmt" -type QueryHandler = func(name string, group string, bz []byte) ([]byte, error) - type QueryNotFoundError struct { name string } From 9fd89008389be49b25068746afac8940c0e0bba4 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Tue, 14 May 2024 10:49:37 -0700 Subject: [PATCH 58/76] remove unused structs in tests. --- cardinal/cardinal_test.go | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/cardinal/cardinal_test.go b/cardinal/cardinal_test.go index bebe95afc..4bda442de 100644 --- a/cardinal/cardinal_test.go +++ b/cardinal/cardinal_test.go @@ -46,16 +46,6 @@ type Bar struct{} func (Bar) Name() string { return "bar" } -type Qux struct{} - -func (Qux) Name() string { return "qux" } - -type CardinalTestHealth struct { - Value int -} - -func (CardinalTestHealth) Name() string { return "health" } - func TestForEachTransaction(t *testing.T) { tf := testutils.NewTestFixture(t, nil) world := tf.World From d46adb1b05bdaa95ab3725c3e4e59c1246bc53ea Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Tue, 14 May 2024 10:51:47 -0700 Subject: [PATCH 59/76] fix refactor error in comments. --- cardinal/gamestate/doc.go | 2 +- cardinal/gamestate/manager.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cardinal/gamestate/doc.go b/cardinal/gamestate/doc.go index 412df73c8..d0cd10d13 100644 --- a/cardinal/gamestate/doc.go +++ b/cardinal/gamestate/doc.go @@ -69,7 +69,7 @@ number. The in-memory data model roughly matches the model that is stored in redis, but there are some differences: -Data are stored as generic interfaces and not as serialized JSON. +Components are stored as generic interfaces and not as serialized JSON. # Potential Improvements diff --git a/cardinal/gamestate/manager.go b/cardinal/gamestate/manager.go index ffd45d506..33c6cb8a7 100644 --- a/cardinal/gamestate/manager.go +++ b/cardinal/gamestate/manager.go @@ -15,7 +15,7 @@ type Reader interface { GetComponentForEntity(cType types.ComponentMetadata, id types.EntityID) (any, error) GetComponentForEntityInRawJSON(cType types.ComponentMetadata, id types.EntityID) (json.RawMessage, error) - // Many Data One Entity + // Many Components One Entity GetComponentTypesForEntity(id types.EntityID) ([]types.ComponentMetadata, error) // One Archetype Many Data From 56646e3d2e3b82ae86bbb3f97158101510c4861b Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Tue, 14 May 2024 10:53:13 -0700 Subject: [PATCH 60/76] fix refactor error in comments. --- cardinal/search/filter/helper.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cardinal/search/filter/helper.go b/cardinal/search/filter/helper.go index 41a0a5ddd..a85855b28 100644 --- a/cardinal/search/filter/helper.go +++ b/cardinal/search/filter/helper.go @@ -5,7 +5,7 @@ import ( ) // MatchComponentMetadata returns true if the given slice of components contains the given component. -// Data are the same if they have the same Name. +// Components are the same if they have the same Name. func MatchComponentMetadata( components []types.ComponentMetadata, cType types.ComponentMetadata, From aa1901502a17ded10c5a2770928586b8a3cbddf9 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Tue, 14 May 2024 10:56:40 -0700 Subject: [PATCH 61/76] make error handling more simple. --- cardinal/query_manager.go | 4 +++- cardinal/server/handler/query.go | 2 +- cardinal/types/query.go | 12 +----------- 3 files changed, 5 insertions(+), 13 deletions(-) diff --git a/cardinal/query_manager.go b/cardinal/query_manager.go index ed26a6e87..bfa4e2201 100644 --- a/cardinal/query_manager.go +++ b/cardinal/query_manager.go @@ -1,6 +1,8 @@ package cardinal import ( + "fmt" + "github.com/rotisserie/eris" "pkg.world.dev/world-engine/cardinal/server/utils" @@ -49,7 +51,7 @@ func (m *queryManager) GetRegisteredQueries() []query { func (w *World) HandleQuery(name string, bz []byte) ([]byte, error) { q, err := w.GetQueryByName(name) if err != nil { - return nil, eris.Wrap(types.NewQueryNotFoundError(name), "") + return nil, eris.Wrap(types.ErrQueryNotFound, fmt.Sprintf("could not find query %q", name)) } wCtx := NewReadOnlyWorldContext(w) return q.handleQueryRaw(wCtx, bz) diff --git a/cardinal/server/handler/query.go b/cardinal/server/handler/query.go index 54c8aec0c..2ca97592b 100644 --- a/cardinal/server/handler/query.go +++ b/cardinal/server/handler/query.go @@ -24,7 +24,7 @@ func PostQuery(world servertypes.ProviderWorld) func(*fiber.Ctx) error { return func(ctx *fiber.Ctx) error { ctx.Set("Content-Type", "application/json") resBz, err := world.HandleQuery(ctx.Params("name"), ctx.Body()) - if eris.Is(err, &types.QueryNotFoundError{}) { + if eris.Is(err, types.ErrQueryNotFound) { return fiber.NewError(fiber.StatusNotFound, "query not found") } else if err != nil { return fiber.NewError(fiber.StatusBadRequest, "encountered an error in query: "+err.Error()) diff --git a/cardinal/types/query.go b/cardinal/types/query.go index 2ea143e19..ace2ab324 100644 --- a/cardinal/types/query.go +++ b/cardinal/types/query.go @@ -2,14 +2,4 @@ package types import "fmt" -type QueryNotFoundError struct { - name string -} - -func NewQueryNotFoundError(name string) *QueryNotFoundError { - return &QueryNotFoundError{name: name} -} - -func (e *QueryNotFoundError) Error() string { - return fmt.Sprintf("could not find query with name: %s", e.name) -} +var ErrQueryNotFound = fmt.Errorf("query not found") From aeb64d25baf558699bba1e6edda494e5fa2b8a3f Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Tue, 14 May 2024 11:04:23 -0700 Subject: [PATCH 62/76] move entity requests and responses into server package. --- cardinal/server/debug_test.go | 10 +++++----- cardinal/server/handler/debug.go | 3 +-- cardinal/server/types/entity.go | 7 +++++++ cardinal/server/types/provider.go | 2 +- cardinal/types/entity.go | 4 ---- cardinal/world.go | 4 ++-- 6 files changed, 16 insertions(+), 14 deletions(-) create mode 100644 cardinal/server/types/entity.go diff --git a/cardinal/server/debug_test.go b/cardinal/server/debug_test.go index 6ad76206a..5416f8c3b 100644 --- a/cardinal/server/debug_test.go +++ b/cardinal/server/debug_test.go @@ -4,7 +4,7 @@ import ( "encoding/json" "pkg.world.dev/world-engine/cardinal" - "pkg.world.dev/world-engine/cardinal/types" + servertypes "pkg.world.dev/world-engine/cardinal/server/types" ) func (s *ServerTestSuite) TestDebugStateQuery() { @@ -20,11 +20,11 @@ func (s *ServerTestSuite) TestDebugStateQuery() { // This will create 1 additional location for this particular persona tag s.runTx(personaTag, moveMessage, MoveMsgInput{Direction: "up"}) - res := s.fixture.Post("debug/state", types.EntityStateRequest{}) + res := s.fixture.Post("debug/state", servertypes.EntityStateRequest{}) s.Require().NoError(err) s.Require().Equal(res.StatusCode, 200) - var results types.EntityStateResponse + var results servertypes.EntityStateResponse s.Require().NoError(json.NewDecoder(res.Body).Decode(&results)) numOfZeroLocation := 0 @@ -52,10 +52,10 @@ func (s *ServerTestSuite) TestDebugStateQuery_NoState() { s.setupWorld() s.fixture.DoTick() - res := s.fixture.Post("debug/state", types.EntityStateRequest{}) + res := s.fixture.Post("debug/state", servertypes.EntityStateRequest{}) s.Require().Equal(res.StatusCode, 200) - var results types.EntityStateResponse + var results servertypes.EntityStateResponse s.Require().NoError(json.NewDecoder(res.Body).Decode(&results)) s.Require().Equal(len(results), 0) diff --git a/cardinal/server/handler/debug.go b/cardinal/server/handler/debug.go index 3fb174584..12ac3113a 100644 --- a/cardinal/server/handler/debug.go +++ b/cardinal/server/handler/debug.go @@ -4,10 +4,9 @@ import ( "github.com/gofiber/fiber/v2" servertypes "pkg.world.dev/world-engine/cardinal/server/types" - "pkg.world.dev/world-engine/cardinal/types" ) -type DebugStateResponse = types.EntityStateResponse +type DebugStateResponse = servertypes.EntityStateResponse // GetState godoc // diff --git a/cardinal/server/types/entity.go b/cardinal/server/types/entity.go new file mode 100644 index 000000000..40be143c8 --- /dev/null +++ b/cardinal/server/types/entity.go @@ -0,0 +1,7 @@ +package types + +import "pkg.world.dev/world-engine/cardinal/types" + +type EntityStateResponse []types.EntityStateElement + +type EntityStateRequest struct{} diff --git a/cardinal/server/types/provider.go b/cardinal/server/types/provider.go index aaf1a5934..6988b749b 100644 --- a/cardinal/server/types/provider.go +++ b/cardinal/server/types/provider.go @@ -19,7 +19,7 @@ type ProviderWorld interface { ReceiptHistorySize() uint64 GetTransactionReceiptsForTick(tick uint64) ([]receipt.Receipt, error) EvaluateCQL(cql string) ([]types.EntityStateElement, error, error) - GetDebugState() (types.EntityStateResponse, error) + GetDebugState() (EntityStateResponse, error) BuildQueryFields() []types.FieldDetail } diff --git a/cardinal/types/entity.go b/cardinal/types/entity.go index 790f475a7..c7eccda84 100644 --- a/cardinal/types/entity.go +++ b/cardinal/types/entity.go @@ -4,10 +4,6 @@ import "encoding/json" type EntityID uint64 -type EntityStateResponse []EntityStateElement - -type EntityStateRequest struct{} - type EntityStateElement struct { ID EntityID `json:"id"` Data []json.RawMessage `json:"data" swaggertype:"object"` diff --git a/cardinal/world.go b/cardinal/world.go index 10857129d..56fb7514e 100644 --- a/cardinal/world.go +++ b/cardinal/world.go @@ -548,8 +548,8 @@ func (w *World) UseNonce(signerAddress string, nonce uint64) error { return w.redisStorage.UseNonce(signerAddress, nonce) } -func (w *World) GetDebugState() (types.EntityStateResponse, error) { - result := make(types.EntityStateResponse, 0) +func (w *World) GetDebugState() (servertypes.EntityStateResponse, error) { + result := make(servertypes.EntityStateResponse, 0) s := w.Search(filter.All()) var eachClosureErr error wCtx := NewReadOnlyWorldContext(w) From 94df133d208af4d1ae738be4161c0aaef894ceec Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Tue, 14 May 2024 11:22:00 -0700 Subject: [PATCH 63/76] make single error. --- cardinal/server/handler/cql.go | 10 +++------- cardinal/server/types/provider.go | 2 +- cardinal/world.go | 11 ++++++++--- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/cardinal/server/handler/cql.go b/cardinal/server/handler/cql.go index 873f76266..905d50c22 100644 --- a/cardinal/server/handler/cql.go +++ b/cardinal/server/handler/cql.go @@ -34,14 +34,10 @@ func PostCQL( if err := ctx.BodyParser(req); err != nil { return err } - result, eachError, searchErr := world.EvaluateCQL(req.CQL) - if searchErr != nil { - return fiber.NewError(fiber.StatusInternalServerError, searchErr.Error()) + result, err := world.EvaluateCQL(req.CQL) + if err != nil { + return fiber.NewError(fiber.StatusInternalServerError, err.Error()) } - if eachError != nil { - return fiber.NewError(fiber.StatusInternalServerError, eachError.Error()) - } - return ctx.JSON(CQLQueryResponse{Results: result}) } } diff --git a/cardinal/server/types/provider.go b/cardinal/server/types/provider.go index 6988b749b..5a3d1d763 100644 --- a/cardinal/server/types/provider.go +++ b/cardinal/server/types/provider.go @@ -18,7 +18,7 @@ type ProviderWorld interface { CurrentTick() uint64 ReceiptHistorySize() uint64 GetTransactionReceiptsForTick(tick uint64) ([]receipt.Receipt, error) - EvaluateCQL(cql string) ([]types.EntityStateElement, error, error) + EvaluateCQL(cql string) ([]types.EntityStateElement, error) GetDebugState() (EntityStateResponse, error) BuildQueryFields() []types.FieldDetail } diff --git a/cardinal/world.go b/cardinal/world.go index 56fb7514e..e5ec29a62 100644 --- a/cardinal/world.go +++ b/cardinal/world.go @@ -665,7 +665,7 @@ func (w *World) ReceiptHistorySize() uint64 { return w.receiptHistory.Size() } -func (w *World) EvaluateCQL(cqlString string) ([]types.EntityStateElement, error, error) { +func (w *World) EvaluateCQL(cqlString string) ([]types.EntityStateElement, error) { // getComponentByName is a wrapper function that casts component.ComponentMetadata from ctx.getComponentByName // to types.Component getComponentByName := func(name string) (types.Component, error) { @@ -679,7 +679,7 @@ func (w *World) EvaluateCQL(cqlString string) ([]types.EntityStateElement, error // Parse the CQL string into a filter cqlFilter, err := cql.Parse(cqlString, getComponentByName) if err != nil { - return nil, nil, eris.Errorf("failed to parse cql string: %s", cqlString) + return nil, eris.Errorf("failed to parse cql string: %s", cqlString) } result := make([]types.EntityStateElement, 0) var eachError error @@ -708,5 +708,10 @@ func (w *World) EvaluateCQL(cqlString string) ([]types.EntityStateElement, error return true }, ) - return result, eachError, searchErr + if eachError != nil { + return nil, eachError + } else if searchErr != nil { + return nil, searchErr + } + return result, nil } From 4d7fda1f8b9109cae01e7d938aac2d35e4a5bc18 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Tue, 14 May 2024 11:38:35 -0700 Subject: [PATCH 64/76] move get world response into handler. --- cardinal/server/handler/world.go | 9 ++++++++- cardinal/server/server_test.go | 3 +-- cardinal/server/types/provider.go | 9 --------- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/cardinal/server/handler/world.go b/cardinal/server/handler/world.go index 2def3b47b..2b9f51b5e 100644 --- a/cardinal/server/handler/world.go +++ b/cardinal/server/handler/world.go @@ -10,7 +10,14 @@ import ( "pkg.world.dev/world-engine/cardinal/types" ) -type GetWorldResponse = servertypes.GetWorldResponse +// GetWorldResponse is a type representing the json super structure that contains +// all info about the world. +type GetWorldResponse struct { + Namespace string `json:"namespace"` + Components []types.FieldDetail `json:"components"` // list of component names + Messages []types.FieldDetail `json:"messages"` + Queries []types.FieldDetail `json:"queries"` +} // GetWorld godoc // diff --git a/cardinal/server/server_test.go b/cardinal/server/server_test.go index 629badfbb..b934e645e 100644 --- a/cardinal/server/server_test.go +++ b/cardinal/server/server_test.go @@ -21,7 +21,6 @@ import ( "pkg.world.dev/world-engine/cardinal" "pkg.world.dev/world-engine/cardinal/persona/msg" "pkg.world.dev/world-engine/cardinal/server/handler" - servertypes "pkg.world.dev/world-engine/cardinal/server/types" "pkg.world.dev/world-engine/cardinal/server/utils" "pkg.world.dev/world-engine/cardinal/testutils" "pkg.world.dev/world-engine/cardinal/types" @@ -96,7 +95,7 @@ func (s *ServerTestSuite) TestGetWorld() { s.setupWorld() s.fixture.DoTick() res := s.fixture.Get("/world") - var result servertypes.GetWorldResponse + var result handler.GetWorldResponse err := json.Unmarshal([]byte(s.readBody(res.Body)), &result) s.Require().NoError(err) comps := s.world.GetRegisteredComponents() diff --git a/cardinal/server/types/provider.go b/cardinal/server/types/provider.go index 5a3d1d763..e5f23fa77 100644 --- a/cardinal/server/types/provider.go +++ b/cardinal/server/types/provider.go @@ -22,12 +22,3 @@ type ProviderWorld interface { GetDebugState() (EntityStateResponse, error) BuildQueryFields() []types.FieldDetail } - -// GetWorldResponse is a type representing the json super structure that contains -// all info about the world. -type GetWorldResponse struct { - Namespace string `json:"namespace"` - Components []types.FieldDetail `json:"components"` // list of component names - Messages []types.FieldDetail `json:"messages"` - Queries []types.FieldDetail `json:"queries"` -} From 4a2a20b10e9ef5afc4c34b43c411d2da07e9d1e0 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Wed, 15 May 2024 10:29:13 -0700 Subject: [PATCH 65/76] lint issue. --- cardinal/types/query.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cardinal/types/query.go b/cardinal/types/query.go index ace2ab324..76b45e798 100644 --- a/cardinal/types/query.go +++ b/cardinal/types/query.go @@ -1,5 +1,5 @@ package types -import "fmt" +import "errors" -var ErrQueryNotFound = fmt.Errorf("query not found") +var ErrQueryNotFound = errors.New("query not found") From d3f5da39f1f5b7df6ccff0885b71ac5adbe9ff71 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Wed, 15 May 2024 12:00:08 -0700 Subject: [PATCH 66/76] change cardinal.HandleQuery to cardinal.InternalHandleQuery. --- cardinal/util.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cardinal/util.go b/cardinal/util.go index f8b36cfbe..87c1f2c94 100644 --- a/cardinal/util.go +++ b/cardinal/util.go @@ -80,6 +80,8 @@ func GetStoreManagerFromContext(wCtx WorldContext) gamestate.Manager { return wCtx.storeManager() } -func HandleQuery(wCtx WorldContext, query query, a any) (any, error) { +// InternalHandleQuery is only used for tests it should not be used outside of that context. +// TODO: Tests should be edited and changed such that this is no longer done. +func InternalHandleQuery(wCtx WorldContext, query query, a any) (any, error) { return query.handleQuery(wCtx, a) } From 12832f86edf6507121059bcf8173de5a2c8e5a02 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Wed, 15 May 2024 12:03:37 -0700 Subject: [PATCH 67/76] change to internal handle query. --- cardinal/errors_test.go | 4 ++-- cardinal/persona/persona_test.go | 6 +++--- cardinal/query_test.go | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cardinal/errors_test.go b/cardinal/errors_test.go index 58e4f58fc..38893cc37 100644 --- a/cardinal/errors_test.go +++ b/cardinal/errors_test.go @@ -309,7 +309,7 @@ func TestQueriesDoNotPanicOnComponentHasNotBeenRegistered(t *testing.T) { assert.Check(t, err == nil) readOnlyWorldCtx := cardinal.NewReadOnlyWorldContext(world) - _, err = cardinal.HandleQuery(readOnlyWorldCtx, query, QueryRequest{}) + _, err = cardinal.InternalHandleQuery(readOnlyWorldCtx, query, QueryRequest{}) // Each test case is meant to generate a "ErrComponentNotRegistered" error assert.Check(t, errors.Is(err, component.ErrComponentNotRegistered), "expected a component not registered error, got %v", err) @@ -355,6 +355,6 @@ func TestGetComponentInQueryDoesNotPanicOnRedisError(t *testing.T) { assert.Check(t, recover() == nil, "expected no panic in a query") }() - _, err = cardinal.HandleQuery(readOnlyWorldCtx, query, QueryRequest{}) + _, err = cardinal.InternalHandleQuery(readOnlyWorldCtx, query, QueryRequest{}) assert.ErrorContains(t, err, "connection refused", "expected a connection error") } diff --git a/cardinal/persona/persona_test.go b/cardinal/persona/persona_test.go index 1bf337b16..7665b3aff 100644 --- a/cardinal/persona/persona_test.go +++ b/cardinal/persona/persona_test.go @@ -236,7 +236,7 @@ func TestQuerySigner(t *testing.T) { query, err := world.GetQueryByName("signer") assert.NilError(t, err) - res, err := cardinal.HandleQuery(cardinal.NewReadOnlyWorldContext(world), query, &cardinal.PersonaSignerQueryRequest{ + res, err := cardinal.InternalHandleQuery(cardinal.NewReadOnlyWorldContext(world), query, &cardinal.PersonaSignerQueryRequest{ PersonaTag: personaTag, }) assert.NilError(t, err) @@ -254,7 +254,7 @@ func TestQuerySignerAvailable(t *testing.T) { query, err := world.GetQueryByName("signer") assert.NilError(t, err) - res, err := cardinal.HandleQuery(cardinal.NewReadOnlyWorldContext(world), query, &cardinal.PersonaSignerQueryRequest{ + res, err := cardinal.InternalHandleQuery(cardinal.NewReadOnlyWorldContext(world), query, &cardinal.PersonaSignerQueryRequest{ PersonaTag: "some-random-nonexistent-persona-tag", }) assert.NilError(t, err) @@ -271,7 +271,7 @@ func TestQuerySignerUnknown(t *testing.T) { query, err := engine.GetQueryByName("signer") assert.NilError(t, err) - res, err := cardinal.HandleQuery(cardinal.NewReadOnlyWorldContext(engine), query, + res, err := cardinal.InternalHandleQuery(cardinal.NewReadOnlyWorldContext(engine), query, &cardinal.PersonaSignerQueryRequest{ PersonaTag: "doesnt_matter", Tick: engine.CurrentTick(), diff --git a/cardinal/query_test.go b/cardinal/query_test.go index 91a40b0ba..0d8d95a25 100644 --- a/cardinal/query_test.go +++ b/cardinal/query_test.go @@ -101,17 +101,17 @@ func TestQueryExample(t *testing.T) { q, err := world.GetQueryByName("query_health") assert.NilError(t, err) - resp, err := cardinal.HandleQuery(worldCtx, q, QueryHealthRequest{1_000_000}) + resp, err := cardinal.InternalHandleQuery(worldCtx, q, QueryHealthRequest{1_000_000}) assert.NilError(t, err) assert.Equal(t, 0, len(resp.(*QueryHealthResponse).IDs)) // All entities should have health over -100 - resp, err = cardinal.HandleQuery(worldCtx, q, QueryHealthRequest{-100}) + resp, err = cardinal.InternalHandleQuery(worldCtx, q, QueryHealthRequest{-100}) assert.NilError(t, err) assert.Equal(t, 100, len(resp.(*QueryHealthResponse).IDs)) // Exactly 10 entities should have health at or above 90 - resp, err = cardinal.HandleQuery(worldCtx, q, QueryHealthRequest{90}) + resp, err = cardinal.InternalHandleQuery(worldCtx, q, QueryHealthRequest{90}) assert.NilError(t, err) assert.Equal(t, 10, len(resp.(*QueryHealthResponse).IDs)) } From 2ef44ce6798a89d17f7acd97f6b467e9a03ee161 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Wed, 15 May 2024 12:05:18 -0700 Subject: [PATCH 68/76] lint. --- cardinal/persona/persona_test.go | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/cardinal/persona/persona_test.go b/cardinal/persona/persona_test.go index 7665b3aff..b012d28f6 100644 --- a/cardinal/persona/persona_test.go +++ b/cardinal/persona/persona_test.go @@ -236,9 +236,10 @@ func TestQuerySigner(t *testing.T) { query, err := world.GetQueryByName("signer") assert.NilError(t, err) - res, err := cardinal.InternalHandleQuery(cardinal.NewReadOnlyWorldContext(world), query, &cardinal.PersonaSignerQueryRequest{ - PersonaTag: personaTag, - }) + res, err := cardinal.InternalHandleQuery( + cardinal.NewReadOnlyWorldContext(world), query, &cardinal.PersonaSignerQueryRequest{ + PersonaTag: personaTag, + }) assert.NilError(t, err) response, ok := res.(*cardinal.PersonaSignerQueryResponse) @@ -254,9 +255,10 @@ func TestQuerySignerAvailable(t *testing.T) { query, err := world.GetQueryByName("signer") assert.NilError(t, err) - res, err := cardinal.InternalHandleQuery(cardinal.NewReadOnlyWorldContext(world), query, &cardinal.PersonaSignerQueryRequest{ - PersonaTag: "some-random-nonexistent-persona-tag", - }) + res, err := cardinal.InternalHandleQuery( + cardinal.NewReadOnlyWorldContext(world), query, &cardinal.PersonaSignerQueryRequest{ + PersonaTag: "some-random-nonexistent-persona-tag", + }) assert.NilError(t, err) response, ok := res.(*cardinal.PersonaSignerQueryResponse) assert.True(t, ok) From d73eeac603b30a022370294022da2fba79e95b42 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Wed, 15 May 2024 13:45:38 -0700 Subject: [PATCH 69/76] get rid of entityStateResponse. --- cardinal/go.mod | 8 +++++++- cardinal/go.sum | 11 +++++++++++ cardinal/server/debug_test.go | 5 +++-- cardinal/server/handler/debug.go | 3 ++- cardinal/server/types/entity.go | 4 ---- cardinal/server/types/provider.go | 2 +- cardinal/world.go | 4 ++-- 7 files changed, 26 insertions(+), 11 deletions(-) diff --git a/cardinal/go.mod b/cardinal/go.mod index 38ad1a4c5..f1e353612 100644 --- a/cardinal/go.mod +++ b/cardinal/go.mod @@ -23,7 +23,7 @@ require ( github.com/rotisserie/eris v0.5.4 github.com/rs/zerolog v1.31.0 github.com/stretchr/testify v1.9.0 - github.com/swaggo/swag v1.16.2 + github.com/swaggo/swag v1.16.3 github.com/wI2L/jsondiff v0.5.0 google.golang.org/grpc v1.62.0 google.golang.org/protobuf v1.32.0 @@ -47,6 +47,7 @@ require ( github.com/andybalholm/brotli v1.1.0 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect @@ -74,6 +75,7 @@ require ( github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/rogpeppe/go-internal v1.11.0 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/savsgio/gotils v0.0.0-20240303185622-093b76447511 // indirect github.com/secure-systems-lab/go-securesystemslib v0.7.0 // indirect github.com/swaggo/files/v2 v2.0.0 // indirect @@ -82,9 +84,11 @@ require ( github.com/tidwall/pretty v1.2.1 // indirect github.com/tidwall/sjson v1.2.5 // indirect github.com/tinylib/msgp v1.1.8 // indirect + github.com/urfave/cli/v2 v2.25.7 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasthttp v1.52.0 // indirect github.com/valyala/tcplisten v1.0.0 // indirect + github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect github.com/yuin/gopher-lua v1.1.0 // indirect go.uber.org/atomic v1.11.0 // indirect go4.org/intern v0.0.0-20230525184215-6c62f75575cb // indirect @@ -98,6 +102,8 @@ require ( golang.org/x/tools v0.16.1 // indirect golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect inet.af/netaddr v0.0.0-20230525184311-b8eac61e914a // indirect + sigs.k8s.io/yaml v1.3.0 // indirect ) diff --git a/cardinal/go.sum b/cardinal/go.sum index 58968dde0..7aa920293 100644 --- a/cardinal/go.sum +++ b/cardinal/go.sum @@ -53,6 +53,8 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -186,6 +188,8 @@ github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.31.0 h1:FcTR3NnLWW+NnTwwhFWiJSZr4ECLpqCm6QsEnyvbV4A= github.com/rs/zerolog v1.31.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/savsgio/gotils v0.0.0-20240303185622-093b76447511 h1:KanIMPX0QdEdB4R3CiimCAbxFrhB3j7h0/OvpYGVQa8= github.com/savsgio/gotils v0.0.0-20240303185622-093b76447511/go.mod h1:sM7Mt7uEoCeFSCBM+qBrqvEo+/9vdmj19wzp3yzUhmg= github.com/secure-systems-lab/go-securesystemslib v0.7.0 h1:OwvJ5jQf9LnIAS83waAjPbcMsODrTQUpJ02eNLUoxBg= @@ -213,6 +217,8 @@ github.com/swaggo/files/v2 v2.0.0 h1:hmAt8Dkynw7Ssz46F6pn8ok6YmGZqHSVLZ+HQM7i0kw github.com/swaggo/files/v2 v2.0.0/go.mod h1:24kk2Y9NYEJ5lHuCra6iVwkMjIekMCaFq/0JQj66kyM= github.com/swaggo/swag v1.16.2 h1:28Pp+8DkQoV+HLzLx8RGJZXNGKbFqnuvSbAAtoxiY04= github.com/swaggo/swag v1.16.2/go.mod h1:6YzXnDcpr0767iOejs318CwYkCQqyGer6BizOg03f+E= +github.com/swaggo/swag v1.16.3 h1:PnCYjPCah8FK4I26l2F/KQ4yz3sILcVUN3cTlBFA9Pg= +github.com/swaggo/swag v1.16.3/go.mod h1:DImHIuOFXKpMFAQjcC7FG4m3Dg4+QuUgUzJmKjI/gRk= github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.17.0 h1:/Jocvlh98kcTfpN2+JzGQWQcqrPQwDrVEMApx/M5ZwM= github.com/tidwall/gjson v1.17.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= @@ -226,6 +232,8 @@ github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6 github.com/tinylib/msgp v1.1.8 h1:FCXC1xanKO4I8plpHGH2P7koL/RzZs12l/+r7vakfm0= github.com/tinylib/msgp v1.1.8/go.mod h1:qkpG+2ldGg4xRFmx+jfTvZPxfGFhi64BcnL9vkCm/Tw= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= +github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= +github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.50.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA= @@ -235,6 +243,8 @@ github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVS github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= github.com/wI2L/jsondiff v0.5.0 h1:RRMTi/mH+R2aXcPe1VYyvGINJqQfC3R+KSEakuU1Ikw= github.com/wI2L/jsondiff v0.5.0/go.mod h1:qqG6hnK0Lsrz2BpIVCxWiK9ItsBCpIZQiv0izJjOZ9s= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= @@ -375,4 +385,5 @@ pkg.world.dev/world-engine/rift v1.1.0-beta.0.20240402214846-de1fc179818a h1:P9p pkg.world.dev/world-engine/rift v1.1.0-beta.0.20240402214846-de1fc179818a/go.mod h1:XAD40g4r3qOp3CTa66JBY+ACEUtjr01loyHiUZIheN8= pkg.world.dev/world-engine/sign v1.0.1-beta h1:ZwVeJYdf88t6qIHPurbdKJKVxUN0dfp0gSF7OCA9xt8= pkg.world.dev/world-engine/sign v1.0.1-beta/go.mod h1:U6XdRfjzoodAScJ/bH4qzxY7gbqbgGV2Od+k3tSTekE= +sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/cardinal/server/debug_test.go b/cardinal/server/debug_test.go index 5416f8c3b..37aa932c8 100644 --- a/cardinal/server/debug_test.go +++ b/cardinal/server/debug_test.go @@ -5,6 +5,7 @@ import ( "pkg.world.dev/world-engine/cardinal" servertypes "pkg.world.dev/world-engine/cardinal/server/types" + "pkg.world.dev/world-engine/cardinal/types" ) func (s *ServerTestSuite) TestDebugStateQuery() { @@ -24,7 +25,7 @@ func (s *ServerTestSuite) TestDebugStateQuery() { s.Require().NoError(err) s.Require().Equal(res.StatusCode, 200) - var results servertypes.EntityStateResponse + var results []types.EntityStateElement s.Require().NoError(json.NewDecoder(res.Body).Decode(&results)) numOfZeroLocation := 0 @@ -55,7 +56,7 @@ func (s *ServerTestSuite) TestDebugStateQuery_NoState() { res := s.fixture.Post("debug/state", servertypes.EntityStateRequest{}) s.Require().Equal(res.StatusCode, 200) - var results servertypes.EntityStateResponse + var results []types.EntityStateElement s.Require().NoError(json.NewDecoder(res.Body).Decode(&results)) s.Require().Equal(len(results), 0) diff --git a/cardinal/server/handler/debug.go b/cardinal/server/handler/debug.go index 12ac3113a..c52fedb2e 100644 --- a/cardinal/server/handler/debug.go +++ b/cardinal/server/handler/debug.go @@ -4,9 +4,10 @@ import ( "github.com/gofiber/fiber/v2" servertypes "pkg.world.dev/world-engine/cardinal/server/types" + "pkg.world.dev/world-engine/cardinal/types" ) -type DebugStateResponse = servertypes.EntityStateResponse +type DebugStateResponse = []types.EntityStateElement // GetState godoc // diff --git a/cardinal/server/types/entity.go b/cardinal/server/types/entity.go index 40be143c8..89b7d8f98 100644 --- a/cardinal/server/types/entity.go +++ b/cardinal/server/types/entity.go @@ -1,7 +1,3 @@ package types -import "pkg.world.dev/world-engine/cardinal/types" - -type EntityStateResponse []types.EntityStateElement - type EntityStateRequest struct{} diff --git a/cardinal/server/types/provider.go b/cardinal/server/types/provider.go index e5f23fa77..651384690 100644 --- a/cardinal/server/types/provider.go +++ b/cardinal/server/types/provider.go @@ -19,6 +19,6 @@ type ProviderWorld interface { ReceiptHistorySize() uint64 GetTransactionReceiptsForTick(tick uint64) ([]receipt.Receipt, error) EvaluateCQL(cql string) ([]types.EntityStateElement, error) - GetDebugState() (EntityStateResponse, error) + GetDebugState() ([]types.EntityStateElement, error) BuildQueryFields() []types.FieldDetail } diff --git a/cardinal/world.go b/cardinal/world.go index e5ec29a62..7137a99f1 100644 --- a/cardinal/world.go +++ b/cardinal/world.go @@ -548,8 +548,8 @@ func (w *World) UseNonce(signerAddress string, nonce uint64) error { return w.redisStorage.UseNonce(signerAddress, nonce) } -func (w *World) GetDebugState() (servertypes.EntityStateResponse, error) { - result := make(servertypes.EntityStateResponse, 0) +func (w *World) GetDebugState() ([]types.EntityStateElement, error) { + result := make([]types.EntityStateElement, 0) s := w.Search(filter.All()) var eachClosureErr error wCtx := NewReadOnlyWorldContext(w) From 1973562646765f5fc74bcdc19cbdba24b4d0c77e Mon Sep 17 00:00:00 2001 From: Scott Sunarto Date: Wed, 15 May 2024 15:30:37 -0700 Subject: [PATCH 70/76] clean up --- cardinal/server/debug_test.go | 6 +++--- cardinal/server/handler/debug.go | 2 ++ cardinal/server/types/entity.go | 3 --- 3 files changed, 5 insertions(+), 6 deletions(-) delete mode 100644 cardinal/server/types/entity.go diff --git a/cardinal/server/debug_test.go b/cardinal/server/debug_test.go index 37aa932c8..61485486e 100644 --- a/cardinal/server/debug_test.go +++ b/cardinal/server/debug_test.go @@ -4,7 +4,7 @@ import ( "encoding/json" "pkg.world.dev/world-engine/cardinal" - servertypes "pkg.world.dev/world-engine/cardinal/server/types" + "pkg.world.dev/world-engine/cardinal/server/handler" "pkg.world.dev/world-engine/cardinal/types" ) @@ -21,7 +21,7 @@ func (s *ServerTestSuite) TestDebugStateQuery() { // This will create 1 additional location for this particular persona tag s.runTx(personaTag, moveMessage, MoveMsgInput{Direction: "up"}) - res := s.fixture.Post("debug/state", servertypes.EntityStateRequest{}) + res := s.fixture.Post("debug/state", handler.DebugStateRequest{}) s.Require().NoError(err) s.Require().Equal(res.StatusCode, 200) @@ -53,7 +53,7 @@ func (s *ServerTestSuite) TestDebugStateQuery_NoState() { s.setupWorld() s.fixture.DoTick() - res := s.fixture.Post("debug/state", servertypes.EntityStateRequest{}) + res := s.fixture.Post("debug/state", handler.DebugStateRequest{}) s.Require().Equal(res.StatusCode, 200) var results []types.EntityStateElement diff --git a/cardinal/server/handler/debug.go b/cardinal/server/handler/debug.go index c52fedb2e..c12135bdc 100644 --- a/cardinal/server/handler/debug.go +++ b/cardinal/server/handler/debug.go @@ -7,6 +7,8 @@ import ( "pkg.world.dev/world-engine/cardinal/types" ) +type DebugStateRequest struct{} + type DebugStateResponse = []types.EntityStateElement // GetState godoc diff --git a/cardinal/server/types/entity.go b/cardinal/server/types/entity.go deleted file mode 100644 index 89b7d8f98..000000000 --- a/cardinal/server/types/entity.go +++ /dev/null @@ -1,3 +0,0 @@ -package types - -type EntityStateRequest struct{} From 142107282c0c0a268153ef1d76453ef9334562e6 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Wed, 15 May 2024 16:48:23 -0700 Subject: [PATCH 71/76] change HandleQuery to use groups and have that as the first parameter. --- cardinal/query_manager.go | 5 ++++- cardinal/server/handler/query.go | 2 +- cardinal/server/types/provider.go | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/cardinal/query_manager.go b/cardinal/query_manager.go index bfa4e2201..dff50b9e2 100644 --- a/cardinal/query_manager.go +++ b/cardinal/query_manager.go @@ -48,8 +48,11 @@ func (m *queryManager) GetRegisteredQueries() []query { return registeredQueries } -func (w *World) HandleQuery(name string, bz []byte) ([]byte, error) { +func (w *World) HandleQuery(group string, name string, bz []byte) ([]byte, error) { q, err := w.GetQueryByName(name) + if q.Group() != group { + return nil, eris.Wrapf(err, "Query group: %s with name: %s not found", group, name) + } if err != nil { return nil, eris.Wrap(types.ErrQueryNotFound, fmt.Sprintf("could not find query %q", name)) } diff --git a/cardinal/server/handler/query.go b/cardinal/server/handler/query.go index 2ca97592b..67920e441 100644 --- a/cardinal/server/handler/query.go +++ b/cardinal/server/handler/query.go @@ -23,7 +23,7 @@ import ( func PostQuery(world servertypes.ProviderWorld) func(*fiber.Ctx) error { return func(ctx *fiber.Ctx) error { ctx.Set("Content-Type", "application/json") - resBz, err := world.HandleQuery(ctx.Params("name"), ctx.Body()) + resBz, err := world.HandleQuery(ctx.Params("group"), ctx.Params("name"), ctx.Body()) if eris.Is(err, types.ErrQueryNotFound) { return fiber.NewError(fiber.StatusNotFound, "query not found") } else if err != nil { diff --git a/cardinal/server/types/provider.go b/cardinal/server/types/provider.go index 651384690..a6587057a 100644 --- a/cardinal/server/types/provider.go +++ b/cardinal/server/types/provider.go @@ -14,7 +14,7 @@ type ProviderWorld interface { Namespace() string GetComponentByName(name string) (types.ComponentMetadata, error) StoreReader() gamestate.Reader - HandleQuery(name string, bz []byte) ([]byte, error) + HandleQuery(group string, name string, bz []byte) ([]byte, error) CurrentTick() uint64 ReceiptHistorySize() uint64 GetTransactionReceiptsForTick(tick uint64) ([]receipt.Receipt, error) From 414446c14c99539b526b37eefc442ae0f2554e7f Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Wed, 15 May 2024 17:13:03 -0700 Subject: [PATCH 72/76] rename error to Errorf. --- cardinal/query_manager.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cardinal/query_manager.go b/cardinal/query_manager.go index dff50b9e2..a90385188 100644 --- a/cardinal/query_manager.go +++ b/cardinal/query_manager.go @@ -50,12 +50,12 @@ func (m *queryManager) GetRegisteredQueries() []query { func (w *World) HandleQuery(group string, name string, bz []byte) ([]byte, error) { q, err := w.GetQueryByName(name) - if q.Group() != group { - return nil, eris.Wrapf(err, "Query group: %s with name: %s not found", group, name) - } if err != nil { return nil, eris.Wrap(types.ErrQueryNotFound, fmt.Sprintf("could not find query %q", name)) } + if q.Group() != group { + return nil, eris.Errorf("Query group: %s with name: %s not found", group, name) + } wCtx := NewReadOnlyWorldContext(w) return q.handleQueryRaw(wCtx, bz) } From f5fdf044515f16087dcadbcf1df7de19512ca6c0 Mon Sep 17 00:00:00 2001 From: heronimus Date: Fri, 17 May 2024 02:02:48 +0700 Subject: [PATCH 73/76] ci: enable go pkg cache on swagger-check --- .github/workflows/test.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0bd13c1de..90682203d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -80,8 +80,7 @@ jobs: uses: actions/setup-go@v5 with: go-version: ${{ env.GO_VERSION }} - ## skip cache, use Namespace volume cache - cache: false + cache: true - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Run swagger-check From f4e48eca8802fca8f59332f031953c74a71deac3 Mon Sep 17 00:00:00 2001 From: heronimus Date: Fri, 17 May 2024 02:14:05 +0700 Subject: [PATCH 74/76] ci: add go cache dependency path --- .github/workflows/test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 90682203d..5ca34430c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -81,6 +81,7 @@ jobs: with: go-version: ${{ env.GO_VERSION }} cache: true + cache-dependency-path: "**/*.sum" - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Run swagger-check From c5424ba3335794ce0a8f54c96383ba9c20e4c787 Mon Sep 17 00:00:00 2001 From: Brian Yeh Date: Fri, 17 May 2024 11:22:48 -0700 Subject: [PATCH 75/76] fix components comment refactor. --- cardinal/gamestate/doc.go | 2 +- cardinal/gamestate/manager.go | 4 ++-- cardinal/testutils/world.go | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cardinal/gamestate/doc.go b/cardinal/gamestate/doc.go index d0cd10d13..2ac14b5cf 100644 --- a/cardinal/gamestate/doc.go +++ b/cardinal/gamestate/doc.go @@ -77,7 +77,7 @@ In redis, the ECB:ACTIVE-ENTITY-IDS and ECB:ARCHETYPE-ID:ENTITY-ID keys contains mapping of one another. The amount of data in redis, and the data written can likely be reduced if we abandon one of these keys and rebuild the other mapping in memory. -In memory, compValues are written to redis during a FinalizeTick cycle. Data that were not actually changed (e.g. +In memory, compValues are written to redis during a FinalizeTick cycle. Components that were not actually changed (e.g. only read operations were performed) are still written to the DB. */ package gamestate diff --git a/cardinal/gamestate/manager.go b/cardinal/gamestate/manager.go index 33c6cb8a7..88c61cf71 100644 --- a/cardinal/gamestate/manager.go +++ b/cardinal/gamestate/manager.go @@ -18,7 +18,7 @@ type Reader interface { // Many Components One Entity GetComponentTypesForEntity(id types.EntityID) ([]types.ComponentMetadata, error) - // One Archetype Many Data + // One Archetype Many Components GetComponentTypesForArchID(archID types.ArchetypeID) ([]types.ComponentMetadata, error) GetArchIDForComponents(components []types.ComponentMetadata) (types.ArchetypeID, error) @@ -34,7 +34,7 @@ type Writer interface { // One Entity RemoveEntity(id types.EntityID) error - // Many Data + // Many Components CreateEntity(comps ...types.ComponentMetadata) (types.EntityID, error) CreateManyEntities(num int, comps ...types.ComponentMetadata) ([]types.EntityID, error) diff --git a/cardinal/testutils/world.go b/cardinal/testutils/world.go index 95c2a86ae..1ec223d28 100644 --- a/cardinal/testutils/world.go +++ b/cardinal/testutils/world.go @@ -92,7 +92,7 @@ func NewTestFixture(t testing.TB, redis *miniredis.Miniredis, opts ...cardinal.W } // StartWorld starts the game world and registers a cleanup function that will shut down -// the cardinal World at the end of the test. Data/Systems/Queries, etc should +// the cardinal World at the end of the test. Components/Systems/Queries, etc should // be registered before calling this function. func (t *TestFixture) StartWorld() { t.startOnce.Do(func() { From 4de72dfc24bd88933c22a86a87674411c4f6ba55 Mon Sep 17 00:00:00 2001 From: Heronimus Adie Date: Tue, 21 May 2024 00:51:29 +0700 Subject: [PATCH 76/76] fix: swaggo dependency error (#759) --- makefiles/test.mk | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/makefiles/test.mk b/makefiles/test.mk index 4a04a81bf..8e7990503 100644 --- a/makefiles/test.mk +++ b/makefiles/test.mk @@ -107,12 +107,14 @@ swagger-check: $(MAKE) swaggo-install @echo "--> Generate latest Swagger specs" - mkdir -p .tmp/swagger - swag init -g cardinal/server/server.go -o .tmp/swagger --parseInternal --parseDependency + cd cardinal && \ + mkdir -p .tmp/swagger && \ + swag init -g server/server.go -o .tmp/swagger --parseInternal --parseDependency @echo "--> Compare existing and latest Swagger specs" - docker run --rm -v ./:/local-repo ghcr.io/argus-labs/devops-infra-swagger-diff:2.0.0 \ - /local-repo/cardinal/server/docs/swagger.json /local-repo/.tmp/swagger/swagger.json && \ + cd cardinal && \ + docker run --rm -v ./:/local-repo ghcr.io/argus-labs/devops-infra-swagger-diff:2.0.0 \ + /local-repo/server/docs/swagger.json /local-repo/.tmp/swagger/swagger.json && \ echo "swagger-diff: no changes detected" @echo "--> Cleanup"