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

Initialise pusher before rendering children #54188

Merged
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions src/libs/Pusher/pusher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,10 @@ let pusherSocketID = '';
const socketEventCallbacks: SocketEventCallback[] = [];
let customAuthorizer: ChannelAuthorizerGenerator;

let initPromise: Promise<void>;
let resolveInitPromise: (value?: unknown) => void;
let initPromise = new Promise((resolve) => {
resolveInitPromise = resolve;
});

const eventsBoundToChannels = new Map<Channel, Set<PusherEventName>>();

Expand All @@ -90,8 +93,9 @@ function callSocketEventCallbacks(eventName: SocketEventName, data?: EventCallba
* @returns resolves when Pusher has connected
*/
function init(args: Args, params?: unknown): Promise<void> {
initPromise = new Promise((resolve) => {
return new Promise((resolve) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this strategy of preserving the original promise work fine if the user does this:

  • Log in with Account A
  • Log out
  • Log in with Account B

?

I imagine that before a new promise would be created, now we reuse the same. Could that cause a bug?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good catch! It could lead to this sequence and crash:

  1. User A logs in
  2. initPromise is resolved
  3. User A logs out
  4. socket is reassigned to null
  5. User B logs in
  6. initPromise is resolved but socket is not created yet
  7. App crashes here
    throw new Error(`[Pusher] instance not found. Pusher.subscribe()
    most likely has been called before Pusher.init()`);

Copy link
Contributor Author

Choose a reason for hiding this comment

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

But we can avoid this by creating new Promise in disconnect function like that:

/**
 * Disconnect from Pusher
 */
function disconnect() {
    if (!socket) {
        Log.info('[Pusher] Attempting to disconnect from Pusher before initialisation has occurred, ignoring.');
        return;
    }

    socket.disconnect();
    socket = null;
    pusherSocketID = '';
    initPromise = new Promise((resolve) => {
        resolveInitPromise = resolve;
    });
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Good catch! That would cause a bug as now if you call pusher.subscribe() it will fail with [Pusher] instance not found, socket is cleared on logout and not created again since the promise is already resolved.

Actually the bug already exists on main too as we can always call subscribe before init

Copy link
Contributor

Choose a reason for hiding this comment

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

Github comments are not loading up in time 😅

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@s77rt yeah, github lags sometimes but it seems that we all agree to the solution :D

if (socket) {
resolveInitPromise();
resolve();
return;
}
Expand Down Expand Up @@ -131,6 +135,7 @@ function init(args: Args, params?: unknown): Promise<void> {
socket?.connection.bind('connected', () => {
pusherSocketID = socket?.connection.socket_id ?? '';
callSocketEventCallbacks('connected');
resolveInitPromise();
resolve();
});

Expand All @@ -142,8 +147,6 @@ function init(args: Args, params?: unknown): Promise<void> {
callSocketEventCallbacks('state_change', states);
});
});

return initPromise;
}

/**
Expand Down Expand Up @@ -394,6 +397,9 @@ function disconnect() {
socket.disconnect();
socket = null;
pusherSocketID = '';
initPromise = new Promise((resolve) => {
resolveInitPromise = resolve;
});
}

/**
Expand Down
Loading