From 1bfce49fbe06ca3144375b160f6b0e0c070e5b46 Mon Sep 17 00:00:00 2001 From: Andrei Mihu Date: Mon, 21 Oct 2024 22:13:43 +0100 Subject: [PATCH] Support for runtime custom HTTP handlers, build with Go 1.23.2, update changelog. --- CHANGELOG.md | 3 + build/Dockerfile | 2 +- build/Dockerfile.arm64 | 2 +- build/Dockerfile.dsym | 2 +- build/Dockerfile.dsym.arm64 | 2 +- build/Dockerfile.local | 2 +- build/pluginbuilder/Dockerfile | 2 +- build/pluginbuilder/Dockerfile.arm64 | 2 +- go.mod | 4 +- go.sum | 4 +- sample_go_module/sample.go | 7 + server/api.go | 54 ++-- server/api_account.go | 4 +- server/api_rpc.go | 11 +- server/console.go | 26 +- server/console_user.go | 8 +- server/metrics.go | 2 +- server/runtime.go | 13 +- server/runtime_go.go | 278 ++++++++++++------ server/runtime_test.go | 2 +- .../nakama-common/runtime/runtime.go | 8 +- .../sql-migrate/test-migrations/1_initial.sql | 8 - .../sql-migrate/test-migrations/2_record.sql | 5 - vendor/modules.txt | 2 +- 24 files changed, 287 insertions(+), 166 deletions(-) delete mode 100644 vendor/github.com/heroiclabs/sql-migrate/test-migrations/1_initial.sql delete mode 100644 vendor/github.com/heroiclabs/sql-migrate/test-migrations/2_record.sql diff --git a/CHANGELOG.md b/CHANGELOG.md index c918c2d444..6042ba7ff5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,10 +6,13 @@ The format is based on [keep a changelog](http://keepachangelog.com) and this pr ## [Unreleased] ### Added - New runtime function to list user notifications. +- Support for runtime registration of custom HTTP handlers. ### Changed - Increased limit on runtimes group users list functions. - Added pagination support to storage index listing. +- Update runtime Satori client for latest API changes. +- Build with Go 1.23.2. ### Fixed - Ensure matchmaker stats behave correctly if matchmaker becomes fully empty and idle. diff --git a/build/Dockerfile b/build/Dockerfile index 6c92eb7625..39385d534b 100644 --- a/build/Dockerfile +++ b/build/Dockerfile @@ -15,7 +15,7 @@ # docker build "$PWD" --build-arg commit="$(git rev-parse --short HEAD)" --build-arg version=v2.1.1 -t heroiclabs/nakama:2.1.1 # docker build "$PWD" --build-arg commit="$(git rev-parse --short HEAD)" --build-arg version="$(git rev-parse --short HEAD)" -t heroiclabs/nakama-prerelease:"$(git rev-parse --short HEAD)" -FROM golang:1.22.5-bookworm as builder +FROM golang:1.23.2-bookworm as builder ARG commit ARG version diff --git a/build/Dockerfile.arm64 b/build/Dockerfile.arm64 index 768497644c..6663b0b6aa 100644 --- a/build/Dockerfile.arm64 +++ b/build/Dockerfile.arm64 @@ -15,7 +15,7 @@ # docker build "$PWD" --build-arg commit="$(git rev-parse --short HEAD)" --build-arg version=v2.1.1 -t heroiclabs/nakama:2.1.1 # docker build "$PWD" --build-arg commit="$(git rev-parse --short HEAD)" --build-arg version="$(git rev-parse --short HEAD)" -t heroiclabs/nakama-prerelease:"$(git rev-parse --short HEAD)" -FROM arm64v8/golang:1.22.5-bookworm as builder +FROM arm64v8/golang:1.23.2-bookworm as builder ARG commit ARG version diff --git a/build/Dockerfile.dsym b/build/Dockerfile.dsym index 1461518bfa..544f51f5cb 100644 --- a/build/Dockerfile.dsym +++ b/build/Dockerfile.dsym @@ -15,7 +15,7 @@ # docker build "$PWD" --build-arg commit="$(git rev-parse --short HEAD)" --build-arg version=v3.19.0 -t heroiclabs/nakama:3.19.0 # docker build "$PWD" --build-arg commit="$(git rev-parse --short HEAD)" --build-arg version="v3.19.0-$(git rev-parse --short HEAD)" -t heroiclabs/nakama-prerelease:"3.19.0-$(git rev-parse --short HEAD)" -FROM golang:1.22.5-bookworm as builder +FROM golang:1.23.2-bookworm as builder ARG commit ARG version diff --git a/build/Dockerfile.dsym.arm64 b/build/Dockerfile.dsym.arm64 index 1a0df95574..6c7688fd56 100644 --- a/build/Dockerfile.dsym.arm64 +++ b/build/Dockerfile.dsym.arm64 @@ -15,7 +15,7 @@ # docker build "$PWD" --build-arg commit="$(git rev-parse --short HEAD)" --build-arg version=v3.19.0 -t heroiclabs/nakama:3.19.0 # docker build "$PWD" --build-arg commit="$(git rev-parse --short HEAD)" --build-arg version="v3.19.0-$(git rev-parse --short HEAD)" -t heroiclabs/nakama-prerelease:"3.19.0-$(git rev-parse --short HEAD)" -FROM arm64v8/golang:1.22.5-bookworm as builder +FROM arm64v8/golang:1.23.2-bookworm as builder ARG commit ARG version diff --git a/build/Dockerfile.local b/build/Dockerfile.local index 6a6482c453..e969834f45 100644 --- a/build/Dockerfile.local +++ b/build/Dockerfile.local @@ -14,7 +14,7 @@ # docker build .. -f Dockerfile.local -t nakama:dev -FROM golang:1.22.5-bookworm AS builder +FROM golang:1.23.2-bookworm AS builder ENV GOOS linux ENV CGO_ENABLED 1 diff --git a/build/pluginbuilder/Dockerfile b/build/pluginbuilder/Dockerfile index 6e02c2ae7f..79d574b6ce 100644 --- a/build/pluginbuilder/Dockerfile +++ b/build/pluginbuilder/Dockerfile @@ -15,7 +15,7 @@ # docker build . --file ./Dockerfile --build-arg version=v2.1.1 -t heroiclabs/nakama-pluginbuilder:2.1.1 # docker build . --file ./Dockerfile --build-arg version="v2.1.1-$(git rev-parse --short HEAD)" -t heroiclabs/nakama-pluginbuilder:"2.1.1-$(git rev-parse --short HEAD)" -FROM golang:1.22.5-bookworm as builder +FROM golang:1.23.2-bookworm as builder MAINTAINER Heroic Labs diff --git a/build/pluginbuilder/Dockerfile.arm64 b/build/pluginbuilder/Dockerfile.arm64 index 832f17737e..38fa5407d5 100644 --- a/build/pluginbuilder/Dockerfile.arm64 +++ b/build/pluginbuilder/Dockerfile.arm64 @@ -15,7 +15,7 @@ # docker build "$PWD" --file ./Dockerfile.pluginbuilder --build-arg commit="$(git rev-parse --short HEAD)" --build-arg version=v2.1.1 -t heroiclabs/nakama-pluginbuilder:2.1.1 # docker build "$PWD" --file ./Dockerfile.pluginbuilder --build-arg commit="$(git rev-parse --short HEAD)" --build-arg version="v2.1.1-$(git rev-parse --short HEAD)" -t heroiclabs/nakama-prerelease:"2.1.1-$(git rev-parse --short HEAD)" -FROM arm64v8/golang:1.22.5-bookworm as builder +FROM arm64v8/golang:1.23.2-bookworm as builder MAINTAINER Heroic Labs diff --git a/go.mod b/go.mod index 2098eb95a9..d87330131a 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/heroiclabs/nakama/v3 -go 1.21 +go 1.23.2 require ( github.com/blugelabs/bluge v0.2.2 @@ -14,7 +14,7 @@ require ( github.com/gorilla/mux v1.8.1 github.com/gorilla/websocket v1.5.1 github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 - github.com/heroiclabs/nakama-common v1.33.1-0.20241021170115-c7b5486ef0aa + github.com/heroiclabs/nakama-common v1.34.0 github.com/heroiclabs/sql-migrate v0.0.0-20240528102547-233afc8cf05a github.com/jackc/pgerrcode v0.0.0-20240316143900-6e2875d9b438 github.com/jackc/pgx/v5 v5.6.0 diff --git a/go.sum b/go.sum index 26e97ee7d1..d5868eb7bb 100644 --- a/go.sum +++ b/go.sum @@ -130,8 +130,8 @@ github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZH github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/heroiclabs/nakama-common v1.33.1-0.20241021170115-c7b5486ef0aa h1:AWkD2AwYSMexj1mPArQvs2xkZTkvXvzqdvHlN4UeHOs= -github.com/heroiclabs/nakama-common v1.33.1-0.20241021170115-c7b5486ef0aa/go.mod h1:lPG64MVCs0/tEkh311Cd6oHX9NLx2vAPx7WW7QCJHQ0= +github.com/heroiclabs/nakama-common v1.34.0 h1:7/F5v5yoCFBMTn5Aih/cqR/GW7hbEbup8blq5OmhzjM= +github.com/heroiclabs/nakama-common v1.34.0/go.mod h1:lPG64MVCs0/tEkh311Cd6oHX9NLx2vAPx7WW7QCJHQ0= github.com/heroiclabs/sql-migrate v0.0.0-20240528102547-233afc8cf05a h1:tuL2ZPaeCbNw8rXmV9ywd00nXRv95V4/FmbIGKLQJAE= github.com/heroiclabs/sql-migrate v0.0.0-20240528102547-233afc8cf05a/go.mod h1:hzCTPoEi/oml2BllVydJcNP63S7b56e5DzeQeLGvw1U= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= diff --git a/sample_go_module/sample.go b/sample_go_module/sample.go index 425320fc94..f68c3b7771 100644 --- a/sample_go_module/sample.go +++ b/sample_go_module/sample.go @@ -17,6 +17,7 @@ package main import ( "context" "database/sql" + "net/http" "github.com/heroiclabs/nakama-common/api" "github.com/heroiclabs/nakama-common/rtapi" @@ -54,6 +55,12 @@ func InitModule(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runti return err } + if err := initializer.RegisterHttp("/test", func(w http.ResponseWriter, r *http.Request) { + _, _ = w.Write([]byte("handling twat")) + }); err != nil { + return err + } + return nil } diff --git a/server/api.go b/server/api.go index 08a8f59cc4..6e93b19315 100644 --- a/server/api.go +++ b/server/api.go @@ -23,9 +23,8 @@ import ( "crypto/x509" "database/sql" "encoding/base64" + "errors" "fmt" - "github.com/heroiclabs/nakama/v3/internal/satori" - "google.golang.org/grpc/grpclog" "math" "net" "net/http" @@ -34,12 +33,13 @@ import ( "time" "github.com/gofrs/uuid/v5" - jwt "github.com/golang-jwt/jwt/v4" + "github.com/golang-jwt/jwt/v4" "github.com/gorilla/handlers" "github.com/gorilla/mux" grpcgw "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" "github.com/heroiclabs/nakama-common/api" "github.com/heroiclabs/nakama/v3/apigrpc" + "github.com/heroiclabs/nakama/v3/internal/satori" "github.com/heroiclabs/nakama/v3/social" "go.uber.org/zap" "google.golang.org/grpc" @@ -47,6 +47,7 @@ import ( "google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials/insecure" _ "google.golang.org/grpc/encoding/gzip" // enable gzip compression on server for grpc + "google.golang.org/grpc/grpclog" "google.golang.org/grpc/metadata" "google.golang.org/grpc/peer" "google.golang.org/grpc/status" @@ -169,7 +170,7 @@ func StartApiServer(logger *zap.Logger, startupLogger *zap.Logger, db *sql.DB, p grpcgw.WithRoutingErrorHandler(handleRoutingError), grpcgw.WithMetadata(func(ctx context.Context, r *http.Request) metadata.MD { // For RPC GET operations pass through any custom query parameters. - if r.Method != "GET" || !strings.HasPrefix(r.URL.Path, "/v2/rpc/") { + if r.Method != http.MethodGet || !strings.HasPrefix(r.URL.Path, "/v2/rpc/") { return metadata.MD{} } @@ -227,12 +228,22 @@ func StartApiServer(logger *zap.Logger, startupLogger *zap.Logger, db *sql.DB, p grpcGatewayRouter := mux.NewRouter() // Special case routes. Do NOT enable compression on WebSocket route, it results in "http: response.Write on hijacked connection" errors. - grpcGatewayRouter.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(200) }).Methods("GET") - grpcGatewayRouter.HandleFunc("/ws", NewSocketWsAcceptor(logger, config, sessionRegistry, sessionCache, statusRegistry, matchmaker, tracker, metrics, runtime, protojsonMarshaler, protojsonUnmarshaler, pipeline)).Methods("GET") + grpcGatewayRouter.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(200) }).Methods(http.MethodGet) + grpcGatewayRouter.HandleFunc("/ws", NewSocketWsAcceptor(logger, config, sessionRegistry, sessionCache, statusRegistry, matchmaker, tracker, metrics, runtime, protojsonMarshaler, protojsonUnmarshaler, pipeline)).Methods(http.MethodGet) // Another nested router to hijack RPC requests bound for GRPC Gateway. grpcGatewayMux := mux.NewRouter() - grpcGatewayMux.HandleFunc("/v2/rpc/{id:.*}", s.RpcFuncHttp).Methods("GET", "POST") + grpcGatewayMux.HandleFunc("/v2/rpc/{id:.*}", s.RpcFuncHttp).Methods(http.MethodGet, http.MethodPost) + for _, handler := range runtime.httpHandlers { + if handler == nil { + continue + } + route := grpcGatewayMux.HandleFunc(handler.PathPattern, handler.Handler) + if len(handler.Methods) > 0 { + route.Methods(handler.Methods...) + } + logger.Info("Registered custom HTTP handler", zap.String("path_pattern", handler.PathPattern)) + } grpcGatewayMux.NewRoute().Handler(grpcGateway) // Enable stats recording on all request paths except: @@ -270,7 +281,7 @@ func StartApiServer(logger *zap.Logger, startupLogger *zap.Logger, db *sql.DB, p // Enable CORS on all requests. CORSHeaders := handlers.AllowedHeaders([]string{"Authorization", "Content-Type", "User-Agent"}) CORSOrigins := handlers.AllowedOrigins([]string{"*"}) - CORSMethods := handlers.AllowedMethods([]string{"GET", "HEAD", "POST", "PUT", "DELETE"}) + CORSMethods := handlers.AllowedMethods([]string{http.MethodGet, http.MethodHead, http.MethodPost, http.MethodPut, http.MethodDelete}) handlerWithCORS := handlers.CORS(CORSHeaders, CORSOrigins, CORSMethods)(grpcGatewayRouter) // Enable configured response headers, if any are set. Do not override values that may have been set by server processing. @@ -310,11 +321,11 @@ func StartApiServer(logger *zap.Logger, startupLogger *zap.Logger, db *sql.DB, p } if config.GetSocket().TLSCert != nil { - if err := s.grpcGatewayServer.ServeTLS(listener, "", ""); err != nil && err != http.ErrServerClosed { + if err := s.grpcGatewayServer.ServeTLS(listener, "", ""); err != nil && !errors.Is(err, http.ErrServerClosed) { startupLogger.Fatal("API server gateway listener failed", zap.Error(err)) } } else { - if err := s.grpcGatewayServer.Serve(listener); err != nil && err != http.ErrServerClosed { + if err := s.grpcGatewayServer.Serve(listener); err != nil && !errors.Is(err, http.ErrServerClosed) { startupLogger.Fatal("API server gateway listener failed", zap.Error(err)) } } @@ -513,7 +524,7 @@ func parseToken(hmacSecretByte []byte, tokenString string) (userID uuid.UUID, us } func decompressHandler(logger *zap.Logger, h http.Handler) http.HandlerFunc { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + return func(w http.ResponseWriter, r *http.Request) { switch r.Header.Get("Content-Encoding") { case "gzip": gr, err := gzip.NewReader(r.Body) @@ -528,7 +539,7 @@ func decompressHandler(logger *zap.Logger, h http.Handler) http.HandlerFunc { // No request compression. } h.ServeHTTP(w, r) - }) + } } func extractClientAddressFromContext(logger *zap.Logger, ctx context.Context) (string, string) { @@ -566,14 +577,17 @@ func extractClientAddress(logger *zap.Logger, clientAddr string, source interfac if host, port, err := net.SplitHostPort(clientAddr); err == nil { clientIP = host clientPort = port - } else if addrErr, ok := err.(*net.AddrError); ok { - switch addrErr.Err { - case "missing port in address": - fallthrough - case "too many colons in address": - clientIP = clientAddr - default: - // Unknown address error, ignore the address. + } else { + var addrErr *net.AddrError + if errors.As(err, &addrErr) { + switch addrErr.Err { + case "missing port in address": + fallthrough + case "too many colons in address": + clientIP = clientAddr + default: + // Unknown address error, ignore the address. + } } } // At this point err may still be a non-nil value that's not a *net.AddrError, ignore the address. diff --git a/server/api_account.go b/server/api_account.go index a5e276b786..3af3d1b786 100644 --- a/server/api_account.go +++ b/server/api_account.go @@ -50,7 +50,7 @@ func (s *ApiServer) GetAccount(ctx context.Context, in *emptypb.Empty) (*api.Acc account, err := GetAccount(ctx, s.logger, s.db, s.statusRegistry, userID) if err != nil { - if err == ErrAccountNotFound { + if errors.Is(err, ErrAccountNotFound) { return nil, status.Error(codes.NotFound, "Account not found.") } return nil, status.Error(codes.Internal, "Error retrieving user account.") @@ -94,7 +94,7 @@ func (s *ApiServer) DeleteAccount(ctx context.Context, in *emptypb.Empty) (*empt } if err := DeleteAccount(ctx, s.logger, s.db, s.config, s.leaderboardCache, s.leaderboardRankCache, s.sessionRegistry, s.sessionCache, s.tracker, userID, false); err != nil { - if err == ErrAccountNotFound { + if errors.Is(err, ErrAccountNotFound) { return nil, status.Error(codes.NotFound, "Account not found.") } return nil, status.Error(codes.Internal, "Error deleting user account.") diff --git a/server/api_rpc.go b/server/api_rpc.go index 5d3663eaaf..29449fdd14 100644 --- a/server/api_rpc.go +++ b/server/api_rpc.go @@ -23,7 +23,6 @@ import ( "time" "github.com/gofrs/uuid/v5" - "github.com/gorilla/mux" grpcgw "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" "github.com/heroiclabs/nakama-common/api" "go.uber.org/zap" @@ -111,8 +110,8 @@ func (s *ApiServer) RpcFuncHttp(w http.ResponseWriter, r *http.Request) { }() // Check the RPC function ID. - maybeID, ok := mux.Vars(r)["id"] - if !ok || maybeID == "" { + maybeID := r.PathValue("id") + if maybeID == "" { // Missing RPC function ID. w.Header().Set("content-type", "application/json") w.WriteHeader(http.StatusBadRequest) @@ -144,7 +143,7 @@ func (s *ApiServer) RpcFuncHttp(w http.ResponseWriter, r *http.Request) { // Prepare input to function. var payload string - if r.Method == "POST" { + if r.Method == http.MethodPost { b, err := io.ReadAll(r.Body) if err != nil { // Request body too large. @@ -272,8 +271,8 @@ func (s *ApiServer) RpcFunc(ctx context.Context, in *api.Rpc) (*api.Rpc, error) return nil, status.Error(codes.NotFound, "RPC function not found") } - headers := make(map[string][]string, 0) - queryParams := make(map[string][]string, 0) + headers := make(map[string][]string) + queryParams := make(map[string][]string) md, ok := metadata.FromIncomingContext(ctx) if !ok { return nil, status.Error(codes.Internal, "RPC function could not get incoming context") diff --git a/server/console.go b/server/console.go index 5cee885d81..90269904bc 100644 --- a/server/console.go +++ b/server/console.go @@ -18,6 +18,7 @@ import ( "context" "crypto" "database/sql" + "errors" "fmt" "io" "math" @@ -318,7 +319,7 @@ func StartConsoleServer(logger *zap.Logger, startupLogger *zap.Logger, db *sql.D // Enable CORS on all requests. CORSHeaders := handlers.AllowedHeaders([]string{"Authorization", "Content-Type", "User-Agent"}) CORSOrigins := handlers.AllowedOrigins([]string{"*"}) - CORSMethods := handlers.AllowedMethods([]string{"GET", "HEAD", "POST", "PUT", "DELETE", "PATCH"}) + CORSMethods := handlers.AllowedMethods([]string{http.MethodGet, http.MethodHead, http.MethodPost, http.MethodPut, http.MethodDelete, http.MethodPatch}) handlerWithCORS := handlers.CORS(CORSHeaders, CORSOrigins, CORSMethods)(grpcGatewayRouter) // Set up and start GRPC Gateway server. @@ -332,7 +333,7 @@ func StartConsoleServer(logger *zap.Logger, startupLogger *zap.Logger, db *sql.D startupLogger.Info("Starting Console server gateway for HTTP requests", zap.Int("port", config.GetConsole().Port)) go func() { - if err := s.grpcGatewayServer.ListenAndServe(); err != nil && err != http.ErrServerClosed { + if err := s.grpcGatewayServer.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) { startupLogger.Fatal("Console server gateway listener failed", zap.Error(err)) } }() @@ -508,13 +509,16 @@ func checkAuth(ctx context.Context, logger *zap.Logger, config Config, auth stri if username == config.GetConsole().Username { if password != config.GetConsole().Password { // Admin password does not match. - if lockout, until := loginAttemptCache.Add(config.GetConsole().Username, ip); lockout != LockoutTypeNone { - switch lockout { - case LockoutTypeAccount: - logger.Info(fmt.Sprintf("Console admin account locked until %v.", until)) - case LockoutTypeIp: - logger.Info(fmt.Sprintf("Console admin IP locked until %v.", until)) - } + lockout, until := loginAttemptCache.Add(config.GetConsole().Username, ip) + switch lockout { + case LockoutTypeAccount: + logger.Info(fmt.Sprintf("Console admin account locked until %v.", until)) + case LockoutTypeIp: + logger.Info(fmt.Sprintf("Console admin IP locked until %v.", until)) + case LockoutTypeNone: + fallthrough + default: + // No lockout. } return ctx, false } @@ -543,10 +547,6 @@ func checkAuth(ctx context.Context, logger *zap.Logger, config Config, auth stri // The token or its claims are invalid. return ctx, false } - if !ok { - // Expiry time claim is invalid. - return ctx, false - } if exp <= time.Now().UTC().Unix() { // Token expired. return ctx, false diff --git a/server/console_user.go b/server/console_user.go index 5cca9cfb55..3810a31eff 100644 --- a/server/console_user.go +++ b/server/console_user.go @@ -26,8 +26,8 @@ import ( "time" "unicode" - uuid "github.com/gofrs/uuid/v5" - jwt "github.com/golang-jwt/jwt/v4" + "github.com/gofrs/uuid/v5" + "github.com/golang-jwt/jwt/v4" "github.com/heroiclabs/nakama/v3/console" "github.com/jackc/pgx/v5/pgconn" "go.uber.org/zap" @@ -78,7 +78,7 @@ func (s *ConsoleServer) AddUser(ctx context.Context, in *console.AddUserRequest) if payloadJson, err := json.Marshal(payload); err != nil { s.logger.Debug("Failed to create newsletter request payload.", zap.Error(err)) } else { - if req, err := http.NewRequest("POST", "https://cloud.heroiclabs.com/v1/nakama-newsletter/subscribe", bytes.NewBuffer(payloadJson)); err != nil { + if req, err := http.NewRequest(http.MethodPost, "https://cloud.heroiclabs.com/v1/nakama-newsletter/subscribe", bytes.NewBuffer(payloadJson)); err != nil { s.logger.Debug("Failed to create newsletter request.", zap.Error(err)) } else { req.Header.Set("Content-Type", "application/json") @@ -165,7 +165,7 @@ func (s *ConsoleServer) dbListConsoleUsers(ctx context.Context) ([]*console.User func (s *ConsoleServer) dbDeleteConsoleUser(ctx context.Context, username string) (bool, uuid.UUID, error) { var deletedID uuid.UUID if err := s.db.QueryRowContext(ctx, "DELETE FROM console_user WHERE username = $1 RETURNING id", username).Scan(&deletedID); err != nil { - if err == sql.ErrNoRows { + if errors.Is(err, sql.ErrNoRows) { return false, uuid.Nil, nil } return false, uuid.Nil, err diff --git a/server/metrics.go b/server/metrics.go index f80d591f4b..892d3071e9 100644 --- a/server/metrics.go +++ b/server/metrics.go @@ -164,7 +164,7 @@ func NewLocalMetrics(logger, startupLogger *zap.Logger, db *sql.DB, config Confi // Create a HTTP server to expose Prometheus metrics through. CORSHeaders := handlers.AllowedHeaders([]string{"Content-Type", "User-Agent"}) CORSOrigins := handlers.AllowedOrigins([]string{"*"}) - CORSMethods := handlers.AllowedMethods([]string{"GET", "HEAD"}) + CORSMethods := handlers.AllowedMethods([]string{http.MethodGet, http.MethodHead}) handlerWithCORS := handlers.CORS(CORSHeaders, CORSOrigins, CORSMethods)(m.refreshDBStats(reporter.HTTPHandler())) m.prometheusHTTPServer = &http.Server{ Addr: fmt.Sprintf(":%d", config.GetMetrics().PrometheusPort), diff --git a/server/runtime.go b/server/runtime.go index 4988d93c27..26c598a4c7 100644 --- a/server/runtime.go +++ b/server/runtime.go @@ -18,6 +18,7 @@ import ( "context" "database/sql" "errors" + "net/http" "os" "path/filepath" "strings" @@ -240,6 +241,12 @@ type ( RuntimeShutdownFunction func(ctx context.Context) ) +type RuntimeHttpHandler struct { + PathPattern string + Handler func(http.ResponseWriter, *http.Request) + Methods []string +} + type RuntimeExecutionMode int const ( @@ -534,6 +541,8 @@ type Runtime struct { storageIndexFilterFunctions map[string]RuntimeStorageIndexFilterFunction + httpHandlers []*RuntimeHttpHandler + leaderboardResetFunction RuntimeLeaderboardResetFunction eventFunctions *RuntimeEventFunctions @@ -656,7 +665,7 @@ func NewRuntime(ctx context.Context, logger, startupLogger *zap.Logger, db *sql. matchProvider := NewMatchProvider() - goModules, goRPCFns, goBeforeRtFns, goAfterRtFns, goBeforeReqFns, goAfterReqFns, goMatchmakerMatchedFn, goMatchmakerCustomMatchingFn, goTournamentEndFn, goTournamentResetFn, goLeaderboardResetFn, goShutdownFn, goPurchaseNotificationAppleFn, goSubscriptionNotificationAppleFn, goPurchaseNotificationGoogleFn, goSubscriptionNotificationGoogleFn, goIndexFilterFns, fleetManager, allEventFns, goMatchNamesListFn, err := NewRuntimeProviderGo(ctx, logger, startupLogger, db, protojsonMarshaler, config, version, socialClient, leaderboardCache, leaderboardRankCache, leaderboardScheduler, sessionRegistry, sessionCache, statusRegistry, matchRegistry, tracker, metrics, streamManager, router, storageIndex, runtimeConfig.Path, paths, eventQueue, matchProvider, fmCallbackHandler) + goModules, goRPCFns, goBeforeRtFns, goAfterRtFns, goBeforeReqFns, goAfterReqFns, goMatchmakerMatchedFn, goMatchmakerCustomMatchingFn, goTournamentEndFn, goTournamentResetFn, goLeaderboardResetFn, goShutdownFn, goPurchaseNotificationAppleFn, goSubscriptionNotificationAppleFn, goPurchaseNotificationGoogleFn, goSubscriptionNotificationGoogleFn, goIndexFilterFns, fleetManager, httpHandlers, allEventFns, goMatchNamesListFn, err := NewRuntimeProviderGo(ctx, logger, startupLogger, db, protojsonMarshaler, config, version, socialClient, leaderboardCache, leaderboardRankCache, leaderboardScheduler, sessionRegistry, sessionCache, statusRegistry, matchRegistry, tracker, metrics, streamManager, router, storageIndex, runtimeConfig.Path, paths, eventQueue, matchProvider, fmCallbackHandler) if err != nil { startupLogger.Error("Error initialising Go runtime provider", zap.Error(err)) return nil, nil, err @@ -2690,6 +2699,8 @@ func NewRuntime(ctx context.Context, logger, startupLogger *zap.Logger, db *sql. subscriptionNotificationGoogleFunction: allSubscriptionNotificationGoogleFunction, storageIndexFilterFunctions: allStorageIndexFilterFunctions, + httpHandlers: httpHandlers, + shutdownFunction: allShutdownFunction, fleetManager: fleetManager, diff --git a/server/runtime_go.go b/server/runtime_go.go index 05f996c629..fe0eefbf8f 100644 --- a/server/runtime_go.go +++ b/server/runtime_go.go @@ -19,6 +19,7 @@ import ( "database/sql" "errors" "fmt" + "net/http" "path/filepath" "plugin" "strings" @@ -62,6 +63,7 @@ type RuntimeGoInitializer struct { subscriptionNotificationGoogle RuntimeSubscriptionNotificationGoogleFunction matchmakerOverride RuntimeMatchmakerOverrideFunction storageIndexFunctions map[string]RuntimeStorageIndexFilterFunction + httpHandlers []*RuntimeHttpHandler fleetManager runtime.FleetManager @@ -98,7 +100,8 @@ func (ri *RuntimeGoInitializer) RegisterRpc(id string, fn func(ctx context.Conte ctx = NewRuntimeGoContext(ctx, ri.node, ri.version, ri.env, RuntimeExecutionModeRPC, headers, queryParams, expiry, userID, username, vars, sessionID, clientIP, clientPort, lang) result, fnErr := fn(ctx, ri.logger.WithField("rpc_id", id), ri.db, ri.nk, payload) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -141,7 +144,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeGetAccount(fn func(ctx context.Con loggerFields := map[string]interface{}{"api_id": "getaccount", "mode": RuntimeExecutionModeBefore.String()} fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return runtimeErr, codes.Internal @@ -171,7 +175,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeUpdateAccount(fn func(ctx context. loggerFields := map[string]interface{}{"api_id": "updateaccount", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -201,7 +206,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeDeleteAccount(fn func(ctx context. loggerFields := map[string]interface{}{"api_id": "deleteaccount", "mode": RuntimeExecutionModeBefore.String()} fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return runtimeErr, codes.Internal @@ -231,7 +237,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeSessionRefresh(fn func(ctx context loggerFields := map[string]interface{}{"api_id": "sessionrefresh", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -261,7 +268,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeSessionLogout(fn func(ctx context. loggerFields := map[string]interface{}{"api_id": "sessionlogout", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -291,7 +299,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeAuthenticateApple(fn func(ctx cont loggerFields := map[string]interface{}{"api_id": "authenticateapple", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -321,7 +330,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeAuthenticateCustom(fn func(ctx con loggerFields := map[string]interface{}{"api_id": "authenticatecustom", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -351,7 +361,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeAuthenticateDevice(fn func(ctx con loggerFields := map[string]interface{}{"api_id": "authenticatedevice", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -381,7 +392,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeAuthenticateEmail(fn func(ctx cont loggerFields := map[string]interface{}{"api_id": "authenticateemail", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -411,7 +423,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeAuthenticateFacebook(fn func(ctx c loggerFields := map[string]interface{}{"api_id": "authenticatefacebook", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -441,7 +454,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeAuthenticateFacebookInstantGame(fn loggerFields := map[string]interface{}{"api_id": "authenticatefacebookinstantgame", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -471,7 +485,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeAuthenticateGameCenter(fn func(ctx loggerFields := map[string]interface{}{"api_id": "authenticategamecenter", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -501,7 +516,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeAuthenticateGoogle(fn func(ctx con loggerFields := map[string]interface{}{"api_id": "authenticategoogle", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -531,7 +547,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeAuthenticateSteam(fn func(ctx cont loggerFields := map[string]interface{}{"api_id": "authenticatesteam", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -561,7 +578,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeListChannelMessages(fn func(ctx co loggerFields := map[string]interface{}{"api_id": "listchannelmessages", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -591,7 +609,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeListFriends(fn func(ctx context.Co loggerFields := map[string]interface{}{"api_id": "listfriends", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -621,7 +640,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeListFriendsOfFriends(fn func(ctx c loggerFields := map[string]interface{}{"api_id": "listfriendsoffriends", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -651,7 +671,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeAddFriends(fn func(ctx context.Con loggerFields := map[string]interface{}{"api_id": "addfriends", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -681,7 +702,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeDeleteFriends(fn func(ctx context. loggerFields := map[string]interface{}{"api_id": "deletefriends", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -711,7 +733,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeBlockFriends(fn func(ctx context.C loggerFields := map[string]interface{}{"api_id": "blockfriends", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -741,7 +764,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeImportFacebookFriends(fn func(ctx loggerFields := map[string]interface{}{"api_id": "importfacebookfriends", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -771,7 +795,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeImportSteamFriends(fn func(ctx con loggerFields := map[string]interface{}{"api_id": "importsteamfriends", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -801,7 +826,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeCreateGroup(fn func(ctx context.Co loggerFields := map[string]interface{}{"api_id": "creategroup", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -831,7 +857,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeUpdateGroup(fn func(ctx context.Co loggerFields := map[string]interface{}{"api_id": "updategroup", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -861,7 +888,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeDeleteGroup(fn func(ctx context.Co loggerFields := map[string]interface{}{"api_id": "deletegroup", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -891,7 +919,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeJoinGroup(fn func(ctx context.Cont loggerFields := map[string]interface{}{"api_id": "joingroup", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -921,7 +950,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeLeaveGroup(fn func(ctx context.Con loggerFields := map[string]interface{}{"api_id": "leavegroup", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -951,7 +981,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeAddGroupUsers(fn func(ctx context. loggerFields := map[string]interface{}{"api_id": "addgroupusers", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -981,7 +1012,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeBanGroupUsers(fn func(ctx context. loggerFields := map[string]interface{}{"api_id": "bangroupusers", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -1011,7 +1043,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeKickGroupUsers(fn func(ctx context loggerFields := map[string]interface{}{"api_id": "kickgroupusers", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -1041,7 +1074,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforePromoteGroupUsers(fn func(ctx cont loggerFields := map[string]interface{}{"api_id": "promotegroupusers", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -1071,7 +1105,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeDemoteGroupUsers(fn func(ctx conte loggerFields := map[string]interface{}{"api_id": "demotegroupusers", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -1101,7 +1136,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeListGroupUsers(fn func(ctx context loggerFields := map[string]interface{}{"api_id": "listgroupusers", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -1131,7 +1167,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeListUserGroups(fn func(ctx context loggerFields := map[string]interface{}{"api_id": "listusergroups", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -1161,7 +1198,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeListGroups(fn func(ctx context.Con loggerFields := map[string]interface{}{"api_id": "listgroups", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -1191,7 +1229,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeDeleteLeaderboardRecord(fn func(ct loggerFields := map[string]interface{}{"api_id": "deleteleaderboardrecord", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -1221,7 +1260,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeDeleteTournamentRecord(fn func(ctx loggerFields := map[string]interface{}{"api_id": "deletetournamentrecord", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -1251,7 +1291,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeListLeaderboardRecords(fn func(ctx loggerFields := map[string]interface{}{"api_id": "listleaderboardrecords", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -1281,7 +1322,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeWriteLeaderboardRecord(fn func(ctx loggerFields := map[string]interface{}{"api_id": "writeleaderboardrecord", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -1311,7 +1353,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeListLeaderboardRecordsAroundOwner( loggerFields := map[string]interface{}{"api_id": "listleaderboardrecordsaroundowner", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -1341,7 +1384,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeLinkApple(fn func(ctx context.Cont loggerFields := map[string]interface{}{"api_id": "linkapple", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -1371,7 +1415,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeLinkCustom(fn func(ctx context.Con loggerFields := map[string]interface{}{"api_id": "linkcustom", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -1401,7 +1446,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeLinkDevice(fn func(ctx context.Con loggerFields := map[string]interface{}{"api_id": "linkdevice", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -1431,7 +1477,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeLinkEmail(fn func(ctx context.Cont loggerFields := map[string]interface{}{"api_id": "linkemail", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -1461,7 +1508,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeLinkFacebook(fn func(ctx context.C loggerFields := map[string]interface{}{"api_id": "linkfacebook", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -1491,7 +1539,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeLinkFacebookInstantGame(fn func(ct loggerFields := map[string]interface{}{"api_id": "linkfacebookinstantgame", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -1521,7 +1570,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeLinkGameCenter(fn func(ctx context loggerFields := map[string]interface{}{"api_id": "linkgamecenter", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -1551,7 +1601,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeLinkGoogle(fn func(ctx context.Con loggerFields := map[string]interface{}{"api_id": "linkgoogle", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -1581,7 +1632,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeLinkSteam(fn func(ctx context.Cont loggerFields := map[string]interface{}{"api_id": "linksteam", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -1611,7 +1663,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeListMatches(fn func(ctx context.Co loggerFields := map[string]interface{}{"api_id": "listmatches", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -1641,7 +1694,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeListNotifications(fn func(ctx cont loggerFields := map[string]interface{}{"api_id": "listnotifications", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -1671,7 +1725,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeDeleteNotifications(fn func(ctx co loggerFields := map[string]interface{}{"api_id": "deletenotifications", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -1701,7 +1756,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeListStorageObjects(fn func(ctx con loggerFields := map[string]interface{}{"api_id": "liststorageobjects", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -1731,7 +1787,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeReadStorageObjects(fn func(ctx con loggerFields := map[string]interface{}{"api_id": "readstorageobjects", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -1761,7 +1818,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeWriteStorageObjects(fn func(ctx co loggerFields := map[string]interface{}{"api_id": "writestorageobjects", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -1791,7 +1849,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeDeleteStorageObjects(fn func(ctx c loggerFields := map[string]interface{}{"api_id": "deletestorageobjects", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -1821,7 +1880,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeJoinTournament(fn func(ctx context loggerFields := map[string]interface{}{"api_id": "jointournament", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -1851,7 +1911,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeListTournamentRecords(fn func(ctx loggerFields := map[string]interface{}{"api_id": "listtournamentrecords", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -1881,7 +1942,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeListTournaments(fn func(ctx contex loggerFields := map[string]interface{}{"api_id": "listtournaments", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -1911,7 +1973,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeWriteTournamentRecord(fn func(ctx loggerFields := map[string]interface{}{"api_id": "writetournamentrecord", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -1941,7 +2004,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeListTournamentRecordsAroundOwner(f loggerFields := map[string]interface{}{"api_id": "listtournamentrecordsaroundowner", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -1971,7 +2035,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeUnlinkApple(fn func(ctx context.Co loggerFields := map[string]interface{}{"api_id": "unlinkapple", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -2001,7 +2066,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeUnlinkCustom(fn func(ctx context.C loggerFields := map[string]interface{}{"api_id": "unlinkcustom", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -2031,7 +2097,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeUnlinkDevice(fn func(ctx context.C loggerFields := map[string]interface{}{"api_id": "unlinkdevice", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -2061,7 +2128,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeUnlinkEmail(fn func(ctx context.Co loggerFields := map[string]interface{}{"api_id": "unlinkemail", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -2091,7 +2159,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeUnlinkFacebook(fn func(ctx context loggerFields := map[string]interface{}{"api_id": "unlinkfacebook", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -2121,7 +2190,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeUnlinkFacebookInstantGame(fn func( loggerFields := map[string]interface{}{"api_id": "unlinkfacebookinstantgame", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -2151,7 +2221,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeUnlinkGameCenter(fn func(ctx conte loggerFields := map[string]interface{}{"api_id": "unlinkgamecenter", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -2181,7 +2252,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeUnlinkGoogle(fn func(ctx context.C loggerFields := map[string]interface{}{"api_id": "unlinkgoogle", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -2211,7 +2283,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeUnlinkSteam(fn func(ctx context.Co loggerFields := map[string]interface{}{"api_id": "unlinksteam", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -2241,7 +2314,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeGetUsers(fn func(ctx context.Conte loggerFields := map[string]interface{}{"api_id": "getusers", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -2271,7 +2345,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeValidatePurchaseApple(fn func(ctx loggerFields := map[string]interface{}{"api_id": "validatepurchaseapple", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -2301,7 +2376,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeValidateSubscriptionApple(fn func( loggerFields := map[string]interface{}{"api_id": "validatesubscriptionapple", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -2331,7 +2407,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeValidateSubscriptionGoogle(fn func loggerFields := map[string]interface{}{"api_id": "validatesubscriptiongoogle", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -2361,7 +2438,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeListSubscriptions(fn func(ctx cont loggerFields := map[string]interface{}{"api_id": "listsubscriptions", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -2391,7 +2469,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeGetSubscription(fn func(ctx contex loggerFields := map[string]interface{}{"api_id": "getsubscription", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -2421,7 +2500,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeValidatePurchaseGoogle(fn func(ctx loggerFields := map[string]interface{}{"api_id": "validatepurchasegoogle", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -2451,7 +2531,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeValidatePurchaseHuawei(fn func(ctx loggerFields := map[string]interface{}{"api_id": "validatepurchasehuawei", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -2481,7 +2562,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeValidatePurchaseFacebookInstant(fn loggerFields := map[string]interface{}{"api_id": "validatepurchasefacebookinstant", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -2511,7 +2593,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeEvent(fn func(ctx context.Context, loggerFields := map[string]interface{}{"api_id": "event", "mode": RuntimeExecutionModeBefore.String()} result, fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk, in) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return result, runtimeErr, codes.Internal @@ -2541,7 +2624,8 @@ func (ri *RuntimeGoInitializer) RegisterBeforeGetMatchmakerStats(fn func(ctx con loggerFields := map[string]interface{}{"api_id": "getmatchmakerstats", "mode": RuntimeExecutionModeBefore.String()} fnErr := fn(ctx, ri.logger.WithFields(loggerFields), ri.db, ri.nk) if fnErr != nil { - if runtimeErr, ok := fnErr.(*runtime.Error); ok { + var runtimeErr *runtime.Error + if errors.As(fnErr, &runtimeErr) { if runtimeErr.Code <= 0 || runtimeErr.Code >= 17 { // If error is present but code is invalid then default to 13 (Internal) as the error code. return runtimeErr, codes.Internal @@ -2711,6 +2795,16 @@ func (ri *RuntimeGoInitializer) RegisterShutdown(fn func(ctx context.Context, lo return nil } +func (ri *RuntimeGoInitializer) RegisterHttp(pathPattern string, handler func(http.ResponseWriter, *http.Request), methods ...string) error { + ri.httpHandlers = append(ri.httpHandlers, &RuntimeHttpHandler{ + PathPattern: pathPattern, + Handler: handler, + Methods: methods, + }) + + return nil +} + func (ri *RuntimeGoInitializer) RegisterMatch(name string, fn func(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule) (runtime.Match, error)) error { ri.matchLock.Lock() ri.match[name] = fn @@ -2718,14 +2812,14 @@ func (ri *RuntimeGoInitializer) RegisterMatch(name string, fn func(ctx context.C return nil } -func NewRuntimeProviderGo(ctx context.Context, logger, startupLogger *zap.Logger, db *sql.DB, protojsonMarshaler *protojson.MarshalOptions, config Config, version string, socialClient *social.Client, leaderboardCache LeaderboardCache, leaderboardRankCache LeaderboardRankCache, leaderboardScheduler LeaderboardScheduler, sessionRegistry SessionRegistry, sessionCache SessionCache, statusRegistry StatusRegistry, matchRegistry MatchRegistry, tracker Tracker, metrics Metrics, streamManager StreamManager, router MessageRouter, storageIndex StorageIndex, rootPath string, paths []string, eventQueue *RuntimeEventQueue, matchProvider *MatchProvider, fmCallbackHandler runtime.FmCallbackHandler) ([]string, map[string]RuntimeRpcFunction, map[string]RuntimeBeforeRtFunction, map[string]RuntimeAfterRtFunction, *RuntimeBeforeReqFunctions, *RuntimeAfterReqFunctions, RuntimeMatchmakerMatchedFunction, RuntimeMatchmakerOverrideFunction, RuntimeTournamentEndFunction, RuntimeTournamentResetFunction, RuntimeLeaderboardResetFunction, RuntimeShutdownFunction, RuntimePurchaseNotificationAppleFunction, RuntimeSubscriptionNotificationAppleFunction, RuntimePurchaseNotificationGoogleFunction, RuntimeSubscriptionNotificationGoogleFunction, map[string]RuntimeStorageIndexFilterFunction, runtime.FleetManager, *RuntimeEventFunctions, func() []string, error) { +func NewRuntimeProviderGo(ctx context.Context, logger, startupLogger *zap.Logger, db *sql.DB, protojsonMarshaler *protojson.MarshalOptions, config Config, version string, socialClient *social.Client, leaderboardCache LeaderboardCache, leaderboardRankCache LeaderboardRankCache, leaderboardScheduler LeaderboardScheduler, sessionRegistry SessionRegistry, sessionCache SessionCache, statusRegistry StatusRegistry, matchRegistry MatchRegistry, tracker Tracker, metrics Metrics, streamManager StreamManager, router MessageRouter, storageIndex StorageIndex, rootPath string, paths []string, eventQueue *RuntimeEventQueue, matchProvider *MatchProvider, fmCallbackHandler runtime.FmCallbackHandler) ([]string, map[string]RuntimeRpcFunction, map[string]RuntimeBeforeRtFunction, map[string]RuntimeAfterRtFunction, *RuntimeBeforeReqFunctions, *RuntimeAfterReqFunctions, RuntimeMatchmakerMatchedFunction, RuntimeMatchmakerOverrideFunction, RuntimeTournamentEndFunction, RuntimeTournamentResetFunction, RuntimeLeaderboardResetFunction, RuntimeShutdownFunction, RuntimePurchaseNotificationAppleFunction, RuntimeSubscriptionNotificationAppleFunction, RuntimePurchaseNotificationGoogleFunction, RuntimeSubscriptionNotificationGoogleFunction, map[string]RuntimeStorageIndexFilterFunction, runtime.FleetManager, []*RuntimeHttpHandler, *RuntimeEventFunctions, func() []string, error) { runtimeLogger := NewRuntimeGoLogger(logger) node := config.GetName() env := config.GetRuntime().Environment nk := NewRuntimeGoNakamaModule(logger, db, protojsonMarshaler, config, socialClient, leaderboardCache, leaderboardRankCache, leaderboardScheduler, sessionRegistry, sessionCache, statusRegistry, matchRegistry, tracker, metrics, streamManager, router, storageIndex) - match := make(map[string]func(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule) (runtime.Match, error), 0) + match := make(map[string]func(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule) (runtime.Match, error)) matchLock := &sync.RWMutex{} matchNamesListFn := func() []string { @@ -2767,17 +2861,19 @@ func NewRuntimeProviderGo(ctx context.Context, logger, startupLogger *zap.Logger env: env, nk: nk, - rpc: make(map[string]RuntimeRpcFunction, 0), + rpc: make(map[string]RuntimeRpcFunction), - beforeRt: make(map[string]RuntimeBeforeRtFunction, 0), - afterRt: make(map[string]RuntimeAfterRtFunction, 0), + beforeRt: make(map[string]RuntimeBeforeRtFunction), + afterRt: make(map[string]RuntimeAfterRtFunction), beforeReq: &RuntimeBeforeReqFunctions{}, afterReq: &RuntimeAfterReqFunctions{}, - storageIndexFunctions: make(map[string]RuntimeStorageIndexFilterFunction, 0), + storageIndexFunctions: make(map[string]RuntimeStorageIndexFilterFunction), storageIndex: storageIndex, + httpHandlers: make([]*RuntimeHttpHandler, 0), + eventFunctions: make([]RuntimeEventFunction, 0), sessionStartFunctions: make([]RuntimeEventFunction, 0), sessionEndFunctions: make([]RuntimeEventFunction, 0), @@ -2804,13 +2900,13 @@ func NewRuntimeProviderGo(ctx context.Context, logger, startupLogger *zap.Logger relPath, name, fn, err := openGoModule(startupLogger, rootPath, path) if err != nil { // Errors are already logged in the function above. - return nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, err + return nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, err } // Run the initialisation. if err = fn(ctx, runtimeLogger, db, nk, initializer); err != nil { startupLogger.Fatal("Error returned by InitModule function in Go module", zap.String("name", name), zap.Error(err)) - return nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, errors.New("error returned by InitModule function in Go module") + return nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, errors.New("error returned by InitModule function in Go module") } modulePaths = append(modulePaths, relPath) } @@ -2858,7 +2954,7 @@ func NewRuntimeProviderGo(ctx context.Context, logger, startupLogger *zap.Logger } } - return modulePaths, initializer.rpc, initializer.beforeRt, initializer.afterRt, initializer.beforeReq, initializer.afterReq, initializer.matchmakerMatched, initializer.matchmakerOverride, initializer.tournamentEnd, initializer.tournamentReset, initializer.leaderboardReset, initializer.shutdownFunction, initializer.purchaseNotificationApple, initializer.subscriptionNotificationApple, initializer.purchaseNotificationGoogle, initializer.subscriptionNotificationGoogle, initializer.storageIndexFunctions, initializer.fleetManager, events, matchNamesListFn, nil + return modulePaths, initializer.rpc, initializer.beforeRt, initializer.afterRt, initializer.beforeReq, initializer.afterReq, initializer.matchmakerMatched, initializer.matchmakerOverride, initializer.tournamentEnd, initializer.tournamentReset, initializer.leaderboardReset, initializer.shutdownFunction, initializer.purchaseNotificationApple, initializer.subscriptionNotificationApple, initializer.purchaseNotificationGoogle, initializer.subscriptionNotificationGoogle, initializer.storageIndexFunctions, initializer.fleetManager, initializer.httpHandlers, events, matchNamesListFn, nil } func CheckRuntimeProviderGo(logger *zap.Logger, rootPath string, paths []string) error { diff --git a/server/runtime_test.go b/server/runtime_test.go index e0a3ba79ff..d19767015d 100644 --- a/server/runtime_test.go +++ b/server/runtime_test.go @@ -391,7 +391,7 @@ nakama.register_rpc(test.printWorld, "helloworld")`, payload := "\"Hello World\"" client := &http.Client{} - request, _ := http.NewRequest("POST", "http://localhost:7350/v2/rpc/helloworld?http_key=defaulthttpkey", strings.NewReader(payload)) + request, _ := http.NewRequest(http.MethodPost, "http://localhost:7350/v2/rpc/helloworld?http_key=defaulthttpkey", strings.NewReader(payload)) request.Header.Add("Content-Type", "Application/JSON") res, err := client.Do(request) if err != nil { diff --git a/vendor/github.com/heroiclabs/nakama-common/runtime/runtime.go b/vendor/github.com/heroiclabs/nakama-common/runtime/runtime.go index c9664bb9cf..90a269f268 100644 --- a/vendor/github.com/heroiclabs/nakama-common/runtime/runtime.go +++ b/vendor/github.com/heroiclabs/nakama-common/runtime/runtime.go @@ -90,6 +90,7 @@ import ( "database/sql" "errors" "fmt" + "net/http" "os" "time" @@ -859,10 +860,10 @@ type Initializer interface { // RegisterEventSessionStart can be used to define functions triggered when client sessions start. RegisterEventSessionStart(fn func(ctx context.Context, logger Logger, evt *api.Event)) error - // RegisterEventSessionStart can be used to define functions triggered when client sessions end. + // RegisterEventSessionEnd can be used to define functions triggered when client sessions end. RegisterEventSessionEnd(fn func(ctx context.Context, logger Logger, evt *api.Event)) error - // Register a new storage index. + // RegisterStorageIndex creates a new storage index definition and triggers an indexing process if needed. RegisterStorageIndex(name, collection, key string, fields []string, sortableFields []string, maxEntries int, indexOnly bool) error // RegisterStorageIndexFilter can be used to define a filtering function for a given storage index. @@ -874,6 +875,9 @@ type Initializer interface { // RegisterShutdown can be used to register a function that is executed once the server receives a termination signal. // This function only fires if shutdown_grace_sec > 0 and will be terminated early if its execution takes longer than the configured grace seconds. RegisterShutdown(fn func(ctx context.Context, logger Logger, db *sql.DB, nk NakamaModule)) error + + // RegisterHttp attaches a new HTTP handler to a specified path on the main client API server endpoint. + RegisterHttp(pathPattern string, handler func(http.ResponseWriter, *http.Request), methods ...string) error } type PresenceReason uint8 diff --git a/vendor/github.com/heroiclabs/sql-migrate/test-migrations/1_initial.sql b/vendor/github.com/heroiclabs/sql-migrate/test-migrations/1_initial.sql deleted file mode 100644 index cd896fbd7b..0000000000 --- a/vendor/github.com/heroiclabs/sql-migrate/test-migrations/1_initial.sql +++ /dev/null @@ -1,8 +0,0 @@ --- +migrate Up --- SQL in section 'Up' is executed when this migration is applied -CREATE TABLE people (id int); - - --- +migrate Down --- SQL section 'Down' is executed when this migration is rolled back -DROP TABLE people; diff --git a/vendor/github.com/heroiclabs/sql-migrate/test-migrations/2_record.sql b/vendor/github.com/heroiclabs/sql-migrate/test-migrations/2_record.sql deleted file mode 100644 index c76d7691bf..0000000000 --- a/vendor/github.com/heroiclabs/sql-migrate/test-migrations/2_record.sql +++ /dev/null @@ -1,5 +0,0 @@ --- +migrate Up -INSERT INTO people (id) VALUES (1); - --- +migrate Down -DELETE FROM people WHERE id=1; diff --git a/vendor/modules.txt b/vendor/modules.txt index 36320bf634..04c3a880c4 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -139,7 +139,7 @@ github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopena github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options github.com/grpc-ecosystem/grpc-gateway/v2/runtime github.com/grpc-ecosystem/grpc-gateway/v2/utilities -# github.com/heroiclabs/nakama-common v1.33.1-0.20241021170115-c7b5486ef0aa +# github.com/heroiclabs/nakama-common v1.34.0 ## explicit; go 1.19 github.com/heroiclabs/nakama-common/api github.com/heroiclabs/nakama-common/rtapi