Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

0.15 fix async/await and code quality #540

Open
wants to merge 11 commits into
base: 0.15
Choose a base branch
from

Conversation

vitalyrotari
Copy link

@vitalyrotari vitalyrotari commented Sep 30, 2022

Hi, @endel

Our project is working more than 1 year on amazing Colyseus, now we made some new feature, and I found many issues with async/await inside of core and other minor things.

I'm not sure if this PR will be merged completely, but they contains many fixes and improvements.

  • Fix code style based according tslint config from project.
  • Fix unresolved async/await
  • Unify Presence interface methods
  • Unify MatchMakerDriver interface methods
  • Add ClientRef interface and missing onLeave method
  • Fix unresolved async _reserveSeat from Room.allowReconnection, so method _reserveSeat got some changes.

Some example of modified allowReconnection method

Allow reconnection with timeout

  try {
    await this.allowReconnection(client, 30);
  } catch (e) {
    // ...
  }

Allow reconnection with manual cancelation

  const controller = new AbortController();
  
  setTimeout(() => {
    controller.abort();
  }, 5000);

  try {
    await this.allowReconnection(client, 'manual', controller);
  } catch (e) {
    // ...
  }

@github-actions
Copy link

This PR is stale because it has been open 45 days with no activity. Remove stale label or comment or this will be closed in 10 days.

@github-actions github-actions bot added the Stale label Nov 20, 2022
@endel endel removed the Stale label Nov 21, 2022
@endel endel added this to the 0.15 milestone Nov 21, 2022
Copy link
Contributor

@hunkydoryrepair hunkydoryrepair left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a lot here that will break or slow down existing apps.
Some beneficial changes, too, but I think a smaller PR with more isolated changes would be better.

@@ -65,7 +65,7 @@ export async function setup(
/**
* Subscribe to remote `handleCreateRoom` calls.
*/
subscribeIPC(presence, processId, getProcessChannel(), (_, args) => {
await subscribeIPC(presence, processId, getProcessChannel(), (_, args) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is the point of awaiting this? Is there any reason to delay the other calls?

@@ -165,8 +165,8 @@ export async function joinById(roomId: string, clientOptions: ClientOptions = {}
/**
* Perform a query for all cached rooms
*/
export async function query(conditions: Partial<IRoomListingData> = {}) {
return await driver.find(conditions);
export function query(conditions: Partial<IRoomListingData> = {}) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a good improvement to make. The implementation is much better without extra layers of promises

@@ -195,7 +195,7 @@ export async function findOneRoomAvailable(roomName: string, clientOptions: Clie
roomQuery.sort(handler.sortOptions);
}

return await roomQuery;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if the function is awaited by the caller, then makes more sense to just remove the async and not await here

@@ -245,17 +245,17 @@ export function defineRoomType<T extends Type<Room>>(
handlers[name] = registeredHandler;

if (!isDevMode) {
cleanupStaleRooms(name);
await cleanupStaleRooms(name);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be breaking. Inserting asynchronous code into what is currently a syncrhonous call could break some apps, and changing to async changes the return type, so it is definitely app breaking.

delete handlers[name];

if (!isDevMode) {
cleanupStaleRooms(name);
await cleanupStaleRooms(name);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems unnecessary. Cleaning up stale rooms should be handled asynchronously.
I think using .catch might be useful, but why wait?

@@ -421,15 +424,15 @@ export async function gracefullyShutdown(): Promise<any> {
}

// remove processId from room count key
presence.hdel(getRoomCountKey(), processId);
await presence.hdel(getRoomCountKey(), processId);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gracefullyShutdown is called as a result of unhandled exceptions. As soon as you await when processing an unhandled exception, the application will exit, thus, this will leave redis full and won't even call disconnect. This would be a pretty big problem when we want a chance to save data during unhandled exception.

@@ -563,7 +565,7 @@ async function disposeRoom(roomName: string, room: Room) {

// decrease amount of rooms this process is handling
if (!isGracefullyShuttingDown) {
presence.hincrby(getRoomCountKey(), processId, -1);
await presence.hincrby(getRoomCountKey(), processId, -1);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

awaiting while shutting down should be avoided


// unsubscribe from remote connections
presence.unsubscribe(getRoomChannel(room.roomId));
await presence.unsubscribe(getRoomChannel(room.roomId));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these seem unnecessary.

this._reconnectingSessionId.delete(sessionId);
};

reconnection
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've never been able to get the reconnection aspect to work well with colyseus so I'm not sure of the impact here, but it should still RETURN something. This has been change to have no return value, so the call cannot be awaited anymore

@@ -796,7 +811,7 @@ export abstract class Room<State extends object= any, Metadata= any> {
return await (userReturnData || Promise.resolve());
}

private _onMessage(client: Client, bytes: number[]) {
private async _onMessage(client: Client, bytes: number[]) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

onMessage should not be awaited

@endel endel modified the milestones: 0.15, 1.0 May 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants