RegisterEventSessionEnd with full functionality

Hi,

From our previous discussions, I understand that you have provided a light weight function that may be called when user disconnects, which may be registered with RegisterEventSessionEnd. We also discussed that the function is on purpose kept ‘light’ since the function may need to be called for a graceful shutdown and thus it should not include any heavy db queries that may interrupt with shutdown.

Is it possible to have a full functionality version (i.e. which has access to db and NakamaModule) and a light version (like the one that we have) to coexist? Only the light version may be called in case of emergency / distress, while the full functionality version may be used for general purposes.

My use case is this: I would like to reward the user based on the length of the session in the game. The easiest way that I could think of, is to record the times at connect and disconnect. But since I don’t have db / nk in RegisterEventSessionEnd, I am not able to record the session disconnect time.

Is there a better way to achieve this?

@gupta-vaibhav You remember our design discussions well :slight_smile:

it should not include any heavy db queries that may interrupt with shutdown.

Yes exactly. The API for event signals is intentionally kept separate from access to the NakamaModule and database connection pool in its API signature to prevent misuse where developers might add logic which is not rate limited to session connect or disconnect events that cause an IO storm after server reboots, etc.

While the API is designed to prevent this kind of misuse in reality its still not hard to cheat the design to do what you need to do. You’d use a function closure to wrap a reference to the database connection handle and NakamaModule like so:

func InitModule(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, initializer runtime.Initializer) error {
    eventSessionEndFn := func(ctx2 context.Context, logger2 runtime.Logger, evt *api.Event) {
        // Take a reference to the *sql.DB pool.
        logger2.Info("%+v", db)
    }
    if err := initializer.RegisterEventSessionEnd(eventSessionEndFn); err != nil {
        return err
    }
    return nil
}

Please use the database connection logic with great care and attention in these cases. Also have a look at a library like ratelimit from Uber to help prevent overload scenarios in your code:

https://github.com/uber-go/ratelimit

Hope this helps.

1 Like

Thank you. Very helpful indeed.

1 Like