Upgrading nakama-runtime

How should one go about upgrading the nakama-runtime used in a project?
before I start the upgrade, I have a working dev environment using the gist @novabyte provided.
here is my dockerfile:

FROM heroiclabs/nakama-pluginbuilder:2.11.1 AS builder

ENV GO111MODULE on
ENV CGO_ENABLED 1

WORKDIR /backend
COPY . .

RUN go build --trimpath --mod=vendor --buildmode=plugin -o ./backend.so

FROM heroiclabs/nakama:2.11.1

COPY --from=builder /backend/backend.so /nakama/data/modules

here is my go.mod file:

module gitlab.com/Mahdad-Baghani/davaa

go 1.14

require github.com/heroiclabs/nakama-common v1.4.0

modules.txt

# github.com/golang/protobuf v1.3.5
github.com/golang/protobuf/proto
github.com/golang/protobuf/ptypes/timestamp
github.com/golang/protobuf/ptypes/wrappers
# github.com/heroiclabs/nakama-common v1.4.0
## explicit
github.com/heroiclabs/nakama-common/api
github.com/heroiclabs/nakama-common/rtapi
github.com/heroiclabs/nakama-common/runtime

I wanted to do an upgrade by getting the latest version of the nakama-runtime (1.8.0 at the time) using the github documentation > Using this Go package > step 3:

go get -u "github.com/heroiclabs/nakama-common/runtime"
go mod vendor

here are my files after running these commands:
go.mod:

module gitlab.com/Mahdad-Baghani/davaa

go 1.14

require (
	github.com/golang/protobuf v1.4.3 // indirect
	github.com/heroiclabs/nakama-common v1.8.0
	google.golang.org/grpc v1.27.1 // indirect
)

modules.txt:

# github.com/golang/protobuf v1.4.3
## explicit
github.com/golang/protobuf/proto
github.com/golang/protobuf/ptypes/timestamp
github.com/golang/protobuf/ptypes/wrappers
# github.com/heroiclabs/nakama-common v1.8.0
## explicit
github.com/heroiclabs/nakama-common/api
github.com/heroiclabs/nakama-common/rtapi
github.com/heroiclabs/nakama-common/runtime
# google.golang.org/grpc v1.27.1
## explicit
# google.golang.org/protobuf v1.25.0
google.golang.org/protobuf/encoding/prototext
google.golang.org/protobuf/encoding/protowire
google.golang.org/protobuf/internal/descfmt
google.golang.org/protobuf/internal/descopts
google.golang.org/protobuf/internal/detrand
google.golang.org/protobuf/internal/encoding/defval
google.golang.org/protobuf/internal/encoding/messageset
google.golang.org/protobuf/internal/encoding/tag
google.golang.org/protobuf/internal/encoding/text
google.golang.org/protobuf/internal/errors
google.golang.org/protobuf/internal/fieldsort
google.golang.org/protobuf/internal/filedesc
google.golang.org/protobuf/internal/filetype
google.golang.org/protobuf/internal/flags
google.golang.org/protobuf/internal/genid
google.golang.org/protobuf/internal/impl
google.golang.org/protobuf/internal/mapsort
google.golang.org/protobuf/internal/pragma
google.golang.org/protobuf/internal/set
google.golang.org/protobuf/internal/strs
google.golang.org/protobuf/internal/version
google.golang.org/protobuf/proto
google.golang.org/protobuf/reflect/protoreflect
google.golang.org/protobuf/reflect/protoregistry
google.golang.org/protobuf/runtime/protoiface
google.golang.org/protobuf/runtime/protoimpl
google.golang.org/protobuf/types/known/timestamppb
google.golang.org/protobuf/types/known/wrapperspb

but I get the following error on recompiling:
"msg":"Could not open Go module","path":"/nakama/data/modules/backend.so","error":"plugin.Open(\"/nakama/data/modules/backend\"): plugin was built with a different version of package github.com/golang/protobuf/proto","stacktrace":"github.com/heroiclabs/nakama/v2/server.openGoModule\n\tgithub.com/heroiclabs/nakama/v2/server/runtime_go.go:2057\ngithub.com/heroiclabs/nakama/v2/server.NewRuntimeProviderGo\n\tgithub.com/heroiclabs/nakama/v2/server/runtime_go.go:1971\ngithub.com/heroiclabs/nakama/v2/server.NewRuntime\n\tgithub.com/heroiclabs/nakama/v2/server/runtime.go:465\nmain.main\n\tmain.go:130\nruntime.main\n\truntime/proc.go:203"}

I have used the following commands from this issue which changes go.mod but has no effect on solving the problem:

env GO111MODULE=on go clean -modcache
env GO111MODULE=on go mod tidy

go.mod:

module gitlab.com/Mahdad-Baghani/davaa

go 1.14

require (
	github.com/golang/protobuf v1.4.3 // indirect
	github.com/heroiclabs/nakama-common v1.8.0
)

What should I be doing?

@Mahdad-Baghani That’s a lot of good detail. Nice post!

When you want to update to newer releases of Nakama you should have a look at the release notes which describes which release requires an updated version of the nakama-common package. In the case of the nakama-common 1.8.0 release you should update to Nakama 2.14.0 server:

https://github.com/heroiclabs/nakama/releases/v2.14.0

In your code examples above your Dockerfile should be updated to use the 2.14.0 pluginbuilder and the 2.14.0 base image for the game server:

FROM heroiclabs/nakama-pluginbuilder:2.14.0 AS builder

ENV GO111MODULE on
ENV CGO_ENABLED 1

WORKDIR /backend
COPY . .

RUN go build --trimpath --mod=vendor --buildmode=plugin -o ./backend.so

FROM heroiclabs/nakama:2.14.0

COPY --from=builder /backend/backend.so /nakama/data/modules

To update the rest you can run these commands with the Go toolchain:

go get "github.com/heroiclabs/nakama-common/runtime@v1.8.0"
go mod clean
go mod vendor

Also take another look at the gist I wrote because its already been updated to the 2.14.0 release:

https://gist.github.com/novabyte/cc6d57022e2d3baa40e98d8fc91dc4c8


It does surprise me that your modfile shows an indirect dependency on “github.com/golang/protobuf” at v1.4.3 because the game server uses the v1.4.2 version:

https://github.com/heroiclabs/nakama/blob/v2.14.0/go.mod#L26

Do you have an additional dependency somewhere which specifies the protobuf runtime?

Hope this helps.

2 Likes

Yep, this solved my problem. Thank you very much.

That is the part I did not understand. But even after I successfully updated to 1.8.0, I found out that the way to reproduce the situation I described is to run the go get -u "github.com/heroiclabs/nakama-common/runtime", which reports the following

go: found github.com/heroiclabs/nakama-common/runtime in github.com/heroiclabs/nakama-common v1.8.0
go: google.golang.org/protobuf upgrade => v1.25.0
go: github.com/golang/protobuf upgrade => v1.4.3
go: downloading github.com/golang/protobuf v1.4.3

but go get "github.com/heroiclabs/nakama-common/runtime" without the param -u says:

go: found github.com/heroiclabs/nakama-common/runtime in github.com/heroiclabs/nakama-common v1.8.0

I dont know, but it could have happend when I tried to use protobuf in my backend, and I was following google’s doc, and when I issued the commands

go get -u google.golang.org/protobuf/cmd/protoc-gen-go

Of course now that I have updated to 1.8.0, I get
go: found google.golang.org/protobuf/cmd/protoc-gen-go in google.golang.org/protobuf v1.25.0,

but previously on 1.4.0, it would change my project’s dependencies.

1 Like

@Mahdad-Baghani I’m glad you’ve solved the upgrade workflow. :+1:

I found out that the way to reproduce the situation I described is to run the go get -u "github.com/heroiclabs/nakama-common/runtime" , which reports the following

When you use the -u option with the go get command it will look to apply minimal version selection to upgrade transitive dependencies to their latest versions as well. This is not what you want with your plugin code because the dependencies must match exactly to be binary compatible at runtime when loaded by the game server. I’ll update the docs to make this clearer.

I dont know, but it could have happend when I tried to use protobuf in my backend, and I was following google’s doc, and when I issued the commands

The Protobuf runtime is going through a bit of changes in the Go community. You’ll be able to use it with all of your code (as we do in the game server already) with the v1.4.2 release (which internally depends on the new “google.golang.org/protobuf” dependency). You can read more about the changes introduced by Google on this blog post:

https://blog.golang.org/protobuf-apiv2

1 Like

I actually managed to use protobuf, and I can tell you, it was not easy :slight_smile:. However, I came across somethings that are new to me regarding the new runtime (probably).

First of all, I cannot see my logs anymore. https://github.com/heroiclabs/nakama-common indicates to use--logger.level DEBUG, but that is too much. --logger.level INFO is the default apparently, but using that does not give me the logs of logger.Info("some") throughout my code.

Secondly, I get this error when the matchmaking is done
{"level":"error","ts":"2020-11-04T14:07:26.552Z","caller":"server/pipeline_matchmaker.go:85","msg":"Error running Matchmaker Matched hook.","error":"error creating match: cannot encode params","errorVerbose":"error creating match: cannot encode params\ngithub.com/heroiclabs/nakama/v2/server.init\n\tgithub.com/heroiclabs/nakama/v2/server/match_registry.go:52\nruntime.doInit\n\truntime/proc.go:5625\nruntime.doInit\n\truntime/proc.go:5620\nruntime.doInit\n\truntime/proc.go:5620\nruntime.main\n\truntime/proc.go:191\nruntime.goexit\n\truntime/asm_amd64.s:1374"}
Here is how I handle matchmaking (nothing fancy, just the boilerplate I copied from samples):
inside InitModule:

if err := initializer.RegisterMatchmakerMatched(doMatchmaking); err != nil {

        return err
    }
unc doMatchmaking(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, entries []runtime.MatchmakerEntry) (string, error) {

    for _, e := range entries {

        logger.Info("Matched user '%s' named '%s'", e.GetPresence().GetUserId(), e.GetPresence().GetUsername())

        for k, v := range e.GetProperties() {

            logger.Info("Matched on '%s' value '%v'", k, v)

        }

    }

    matchId, err := nk.MatchCreate(ctx, fmt.Sprintf("%s-%s", serviceName, CreateMatchFuncName), map[string]interface{}{"joins": entries, "debug": true, "debug-verbose": false})

    if err != nil {

        return "", err

    }

    return matchId, nil

}

This looks like something that was resolved in the Nakama 2.14.1 release. Check you’re running this version and try it again - if you still have an issue we can dig into it further. :+1:

1 Like

Yep, that was it. It turns out that my match-loop logs didn’t appear in the console because somehow my authoritative match was not created because of the matchmaking error. However, I never thought that was the reason since messages were being relayed between players of the match similar to how it was before the bug was there. Is that possible that the authoritative match was not created, but players were joined in a relayed manner?

Yes, that’s exactly what happened. If a matchmaker hook does not return an authoritative match ID then a relayed join token is supplied by default. In this case it was because of your match create error.

If you want to prevent this behaviour ensure your client only joins matches using a match ID, never a match join token, when receiving a matchmaker result.

1 Like

Really solid point. Thanks.