Handlers are one of the core features of Pitaya, they are the entities responsible for receiving the requests from the clients and handling them, returning the response if the method is a request handler, or nothing, if the method is a notify handler.
Handlers must be public methods of the struct and have a signature following:
Arguments
context.Context
: the context of the request, which contains the client's session.pointer or []byte
: the payload of the request (optional).
Notify handlers return nothing, while request handlers must return:
pointer or []byte
: the response payloaderror
: an error variable
Handlers must be explicitly registered by the application by calling pitaya.Register
with a instance of the handler component. The handler's name can be defined by calling pitaya/component
.WithName("handlerName"
) and the methods can be renamed by using pitaya/component
.WithNameFunc(func(string) string
).
The clients can call the handler by calling serverType.handlerName.methodName
.
Messages are forwarded by pitaya to the appropriate server type, and custom routers can be added to the application by calling pitaya.AddRoute
, it expects two arguments:
serverType
: the server type of the target requests to be routedroutingFunction
: the routing function with the signaturefunc(*session.Session, *route.Route, []byte, map[string]*cluster.Server) (*cluster.Server, error)
, it receives the user's session, the route being requested, the message and the map of valid servers of the given type, the key being the servers' ids
The server will then use the routing function when routing requests to the given server type.
Handlers can optionally implement the following lifecycle methods:
Init()
- Called by Pitaya when initializing the applicationAfterInit()
- Called by Pitaya after initializing the applicationBeforeShutdown()
- Called by Pitaya when shutting down components, but before calling shutdownShutdown()
- Called by Pitaya after the start of shutdown
Below is a very barebones example of a handler definition, for a complete working example, check the cluster demo.
import (
"github.com/topfreegames/pitaya"
"github.com/topfreegames/pitaya/component"
)
type Handler struct {
component.Base
}
type UserRequestMessage struct {
Name string `json:"name"`
Content string `json:"content"`
}
type UserResponseMessage {
}
type UserPushMessage{
Command string `json:"cmd"`
}
// Init runs on service initialization (not required to be defined)
func (h *Handler) Init() {}
// AfterInit runs after initialization (not required to be defined)
func (h *Handler) AfterInit() {}
// TestRequest can be called by the client by calling <servertype>.testhandler.testrequest
func (h *Handler) TestRequest(ctx context.Context, msg *UserRequestMessage) (*UserResponseMessage, error) {
return &UserResponseMessage{}, nil
}
func (h *Handler) TestPush(ctx context.Context, msg *UserPushMessage) {
}
func main() {
pitaya.Register(
&Handler{}, // struct to register as handler
component.WithName("testhandler"), // name of the handler, used by the clients
component.WithNameFunc(strings.ToLower), // naming conversion scheme to be used by the clients
)
...
}
Remotes are one of the core features of Pitaya, they are the entities responsible for receiving the RPCs from other Pitaya servers.
Remotes must be public methods of the struct and have a signature following:
Arguments
context.Context
: the context of the request.proto.Message
: the payload of the request (optional).
Remote methods must return:
proto.Message
: the response payload in protobuf formaterror
: an error variable
Remotes must be explicitly registered by the application by calling pitaya.RegisterRemote
with a instance of the remote component. The remote's name can be defined by calling pitaya/component
.WithName("remoteName"
) and the methods can be renamed by using pitaya/component
.WithNameFunc(func(string) string
).
The servers can call the remote by calling serverType.remoteName.methodName
.
There are two options when sending RPCs between servers:
- Specify only server type: In this case Pitaya will select one of the available servers at random
- Specify server type and ID: In this scenario Pitaya will send the RPC to the specified server
Remotes can optionally implement the following lifecycle methods:
Init()
- Called by Pitaya when initializing the applicationAfterInit()
- Called by Pitaya after initializing the applicationBeforeShutdown()
- Called by Pitaya when shutting down components, but before calling shutdownShutdown()
- Called by Pitaya after the start of shutdown
For a complete working example, check the cluster demo.