Initiating Asynchronous Workloads in Match Loop (TS/JS)

Hi!

I am building a card game which requires requesting card data from a separate microservice with http requests.

When a client attempts to draw a new card, I have to request that data and it can take over 5 seconds if the data is new.

Right now I am using sendMatchState to initiate those actions from the client so I am processing the results in the match loop on the Nakam server. Right now the http request just freezes the match loop, sometimes even timing it out if it takes too long.

What I’d like to do is essentially have that pending http request sitting in a background coroutine and once it’s finished have it queue up for processing in the next match loop. It’s not important that the new card is inserted immediately, but I don’t want the entire match the freeze or break just because people are drawing a few cards! I’m still new to Nakama so I’m not really sure how I can do this.

I was thinking I could initiate an RPC call that writes to a queue in the nakama storage, but this seems like a gross solution. I get the impression that storage is for persistent data. Even with this idea, I’m not sure how to call an RPC from the server without just using another httpRequest that would suffer from the same problem!

Any help much appreciated!

Client code example:

nakamaSocket.sendMatchState(match_id, 2, {}) // Draw a card

Server code example:

export function matchLoop(ctx: nkruntime.Context, logger: nkruntime.Logger, nk: nkruntime.Nakama, dispatcher: nkruntime.MatchDispatcher, tick: number, state: nkruntime.MatchState, messages: nkruntime.MatchMessage[]): { state: nkruntime.MatchState } | null {
	// Process incoming messages
	messages.forEach(message => {
		switch (message.opCode) {
			case 2: // Draw card
				const card_id = "test_card"; // Example card ID
				const response = nk.httpRequest(`${ASSET_SERVER_URL}/cards/${card_id}/stats`, 'get');
				const new_card_data = JSON.parse(response.body) as Card;

				state.team1.cards.push(new_card_data);

				break;
			default:
				logger.error('Unknown opcode type: %d', message.opCode);
				break;
		}
	});

	// Returning game state
	return {
		state
	};
}

TL;DR How can I initiate and consume asynchronous tasks in the match loop without freezing it?