Skip to content

Commit

Permalink
Merge pull request #53751 from software-mansion-labs/fix-pusher-insta…
Browse files Browse the repository at this point in the history
…nce-not-found

Subscribe to Pusher only when it's initialized
  • Loading branch information
mountiny authored Dec 9, 2024
2 parents 7fed578 + f2090bf commit f5234f7
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 47 deletions.
7 changes: 2 additions & 5 deletions src/libs/Navigation/AppNavigator/AuthScreens.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,6 @@ function AuthScreens({session, lastOpenedPublicRoomID, initialLastUpdateIDApplie
const {toggleSearch} = useSearchRouterContext();

const modal = useRef<OnyxTypes.Modal>({});
const [didPusherInit, setDidPusherInit] = useState(false);
const {isOnboardingCompleted} = useOnboardingFlowRouter();
const [initialReportID] = useState(() => {
const currentURL = getCurrentUrl();
Expand Down Expand Up @@ -280,9 +279,7 @@ function AuthScreens({session, lastOpenedPublicRoomID, initialLastUpdateIDApplie
NetworkConnection.listenForReconnect();
NetworkConnection.onReconnect(handleNetworkReconnect);
PusherConnectionManager.init();
initializePusher().then(() => {
setDidPusherInit(true);
});
initializePusher();

// In Hybrid App we decide to call one of those method when booting ND and we don't want to duplicate calls
if (!NativeModules.HybridAppModule) {
Expand Down Expand Up @@ -591,7 +588,7 @@ function AuthScreens({session, lastOpenedPublicRoomID, initialLastUpdateIDApplie
<TestToolsModal />
<SearchRouterModal />
</View>
{didPusherInit && <ActiveGuidesEventListener />}
<ActiveGuidesEventListener />
</ComposeProviders>
);
}
Expand Down
89 changes: 48 additions & 41 deletions src/libs/Pusher/pusher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ let pusherSocketID = '';
const socketEventCallbacks: SocketEventCallback[] = [];
let customAuthorizer: ChannelAuthorizerGenerator;

let initPromise: Promise<void>;

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

/**
Expand All @@ -88,7 +90,7 @@ function callSocketEventCallbacks(eventName: SocketEventName, data?: EventCallba
* @returns resolves when Pusher has connected
*/
function init(args: Args, params?: unknown): Promise<void> {
return new Promise((resolve) => {
initPromise = new Promise((resolve) => {
if (socket) {
resolve();
return;
Expand Down Expand Up @@ -140,6 +142,8 @@ function init(args: Args, params?: unknown): Promise<void> {
callSocketEventCallbacks('state_change', states);
});
});

return initPromise;
}

/**
Expand Down Expand Up @@ -236,52 +240,55 @@ function subscribe<EventName extends PusherEventName>(
eventCallback: (data: EventData<EventName>) => void = () => {},
onResubscribe = () => {},
): Promise<void> {
return new Promise((resolve, reject) => {
InteractionManager.runAfterInteractions(() => {
// We cannot call subscribe() before init(). Prevent any attempt to do this on dev.
if (!socket) {
throw new Error(`[Pusher] instance not found. Pusher.subscribe()
return initPromise.then(
() =>
new Promise((resolve, reject) => {
InteractionManager.runAfterInteractions(() => {
// We cannot call subscribe() before init(). Prevent any attempt to do this on dev.
if (!socket) {
throw new Error(`[Pusher] instance not found. Pusher.subscribe()
most likely has been called before Pusher.init()`);
}

Log.info('[Pusher] Attempting to subscribe to channel', false, {channelName, eventName});
let channel = getChannel(channelName);
}

if (!channel?.subscribed) {
channel = socket.subscribe(channelName);
let isBound = false;
channel.bind('pusher:subscription_succeeded', () => {
// Check so that we do not bind another event with each reconnect attempt
if (!isBound) {
Log.info('[Pusher] Attempting to subscribe to channel', false, {channelName, eventName});
let channel = getChannel(channelName);

if (!channel?.subscribed) {
channel = socket.subscribe(channelName);
let isBound = false;
channel.bind('pusher:subscription_succeeded', () => {
// Check so that we do not bind another event with each reconnect attempt
if (!isBound) {
bindEventToChannel(channel, eventName, eventCallback);
resolve();
isBound = true;
return;
}

// When subscribing for the first time we register a success callback that can be
// called multiple times when the subscription succeeds again in the future
// e.g. as a result of Pusher disconnecting and reconnecting. This callback does
// not fire on the first subscription_succeeded event.
onResubscribe();
});

channel.bind('pusher:subscription_error', (data: PusherSubscribtionErrorData = {}) => {
const {type, error, status} = data;
Log.hmmm('[Pusher] Issue authenticating with Pusher during subscribe attempt.', {
channelName,
status,
type,
error,
});
reject(error);
});
} else {
bindEventToChannel(channel, eventName, eventCallback);
resolve();
isBound = true;
return;
}

// When subscribing for the first time we register a success callback that can be
// called multiple times when the subscription succeeds again in the future
// e.g. as a result of Pusher disconnecting and reconnecting. This callback does
// not fire on the first subscription_succeeded event.
onResubscribe();
});

channel.bind('pusher:subscription_error', (data: PusherSubscribtionErrorData = {}) => {
const {type, error, status} = data;
Log.hmmm('[Pusher] Issue authenticating with Pusher during subscribe attempt.', {
channelName,
status,
type,
error,
});
reject(error);
});
} else {
bindEventToChannel(channel, eventName, eventCallback);
resolve();
}
});
});
}),
);
}

/**
Expand Down
6 changes: 5 additions & 1 deletion tests/ui/UnreadIndicatorsTest.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,11 @@ function signInAndGetAppWithUnreadChat(): Promise<void> {
}

describe('Unread Indicators', () => {
afterEach(() => {
beforeAll(() => {
PusherHelper.setup();
});

beforeEach(() => {
jest.clearAllMocks();
Onyx.clear();

Expand Down
2 changes: 2 additions & 0 deletions tests/utils/PusherHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ function setup() {
cluster: CONFIG.PUSHER.CLUSTER,
authEndpoint: `${CONFIG.EXPENSIFY.DEFAULT_API_ROOT}api/AuthenticatePusher?`,
});

window.getPusherInstance()?.connection.emit('connected');
}

function emitOnyxUpdate(args: OnyxServerUpdate[]) {
Expand Down

0 comments on commit f5234f7

Please sign in to comment.