boardgame.io icon indicating copy to clipboard operation
boardgame.io copied to clipboard

server-side side-effects for room state changes

Open jabza opened this issue 4 years ago • 5 comments

The current lobby and server are somewhat of a black box when it comes to accessing the room state.

It would be nice to allow server to listen to state change events, perhaps the redux store directly, to trigger side-effects when rooms are created, modified and ended. One example being updating user statistics upon game completion.

Right now, server-side, the only option is events hooked up with the various game callbacks, such as onEnd(G, ctx). But these are understandably intended for modifying G only. (and do not provide roomId or player metadata)

I'm not sure what the solution is here, but maybe something like the redux enhancer for client side could exist in server-side as an effective way of triggering side-effects as games progress?

Ideally we'd have access to the RoomId that changed, what changed in it, and the player metadata of those currently involved.

jabza avatar May 10 '20 23:05 jabza

Thanks for laying out the details @jabza.

There are two different states to listen for changes in: metadata (players joining/leaving, room created etc.) and the actual game state.

Game State

For game state, we would probably need to add a hook/callback in the game master. For example, we currently do this to check if the game is over and if we should update the metadata:

https://github.com/boardgameio/boardgame.io/blob/b2d6b067d6d737406484a648b6697c8d1443570e/src/master/master.ts#L293-L303

Room ID, action, old & new state are all available here. It wouldn’t offer fine-grained game events, but it would permit the basic functionality you’re looking for I think.

Metadata

For metadata changes, we might hook something into the REST API code, that could be called for each successful request.


Is this something you’d be interested in working on? I’d be happy to provide pointers and answer any questions you might have.

delucis avatar May 10 '20 23:05 delucis

Hey @delucis

Thanks for the reply.

In haste, I ended up taking a more low-level approach. I created a new StorageAPI.Async db class that includes EventEmitter, effectively acting as a 'man-in-the-middle'. This is great for me, but I've no idea if this a solution wanted for master.

Ideally having StorageAPI.Async inherit EventEmitter would be cleaner, but I'm using composition for now.

Cheers

jabza avatar May 12 '20 08:05 jabza

Nice! I actually thought about something like that too — glad it’s working for you for now.

delucis avatar May 12 '20 15:05 delucis

@jabza I am also interested in this functionality. Could you share your implementation? Maybe we could create a package that would be used as middleware (like the cache storage adapter)?

janKir avatar Jun 27 '20 09:06 janKir

For reference, if anyone’s looking for a quick solution, here’s an example of extending a database implementation to do some extra work when the game ends: https://gist.github.com/delucis/53803fedb036f778e8a991bb9e07b388

A similar approach would cover many use cases — extend the createMatch method for game start events, setMetadata for match metadata changes, setState for all other types of state changes.

delucis avatar Sep 14 '21 09:09 delucis