Skip to content

Commit

Permalink
fix: subscription switching by maintaining reference
Browse files Browse the repository at this point in the history
  • Loading branch information
yashim-deriv committed Aug 5, 2024
1 parent 4d4a36c commit d810de3
Show file tree
Hide file tree
Showing 9 changed files with 29 additions and 26 deletions.
2 changes: 1 addition & 1 deletion src/api/mutation/use-authorize.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export const useAuthorize = ({ ...options }: Omit<AugmentedMutationOptions<'auth
const { derivAPIClient } = useAPI();

return useReactQueryMutation({
mutationFn: payload => derivAPIClient.send({ name: 'authorize', payload }),
mutationFn: payload => derivAPIClient.getActiveClient().send({ name: 'authorize', payload }),
...options,
});
};
2 changes: 1 addition & 1 deletion src/api/mutation/use-logout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export const useLogout = ({ ...options }: Omit<AugmentedMutationOptions<'logout'
const { derivAPIClient } = useAPI();

return useReactQueryMutation({
mutationFn: () => derivAPIClient.send({ name: 'logout' }),
mutationFn: () => derivAPIClient.getActiveClient().send({ name: 'logout' }),
...options,
});
};
2 changes: 1 addition & 1 deletion src/api/mutation/use-new-account-virtual.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const useNewAccountVirtual = ({
const { derivAPIClient } = useAPI();

return useReactQueryMutation({
mutationFn: payload => derivAPIClient.send({ name: 'new_account_virtual', payload }),
mutationFn: payload => derivAPIClient.getActiveClient().send({ name: 'new_account_virtual', payload }),
...options,
});
};
2 changes: 1 addition & 1 deletion src/base/use-infinite-query.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const useInfiniteQuery = <T extends TSocketPaginateableEndpointNames>({
limit,
offset: Number(pageParam) * limit + initialOffset,
} as TSocketRequestPayload<T>;
return derivAPIClient.send({ name, payload: requestPayload });
return derivAPIClient.getActiveClient().send({ name, payload: requestPayload });
},
...options,
initialPageParam: options?.initialPageParam ? options.initialPageParam : 0,
Expand Down
2 changes: 1 addition & 1 deletion src/base/use-mutation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export const useMutation = <T extends TSocketEndpointNames>({
const { derivAPIClient } = useAPI();

const { mutate, mutateAsync, ...props } = useReactQueryMutation({
mutationFn: payload => derivAPIClient.send({ name, payload }),
mutationFn: payload => derivAPIClient.getActiveClient().send({ name, payload }),
...options,
});

Expand Down
2 changes: 1 addition & 1 deletion src/base/use-query.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export const useQuery = <T extends TSocketEndpointNames>({

return _useQuery<TSocketResponseData<T>, TSocketError<T>['error']>({
queryKey: [name, ...(queryKey ?? [])],
queryFn: () => derivAPIClient.send({ name, payload }),
queryFn: () => derivAPIClient.getActiveClient().send({ name, payload }),
...rest,
});
};
4 changes: 2 additions & 2 deletions src/base/use-subscribe.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export const useSubscribe = <T extends TSocketSubscribableEndpointNames>(name: T
if (internalId.current) return;
if (internalHash.current) return;

const { id, hash } = await derivAPIClient.subscribe({
const { id, hash } = await derivAPIClient.getActiveClient().subscribe({
name,
payload,
onData: (data: TSocketSubscribeResponseData<TSocketSubscribableEndpointNames>) => {
Expand All @@ -65,7 +65,7 @@ export const useSubscribe = <T extends TSocketSubscribableEndpointNames>(name: T

const unsubscribe = async () => {
if (internalId.current && internalHash.current) {
await derivAPIClient.unsubscribe({ id: internalId.current, hash: internalHash.current });
await derivAPIClient.getActiveClient().unsubscribe({ id: internalId.current, hash: internalHash.current });
clearTimeout(timeoutRef.current);
setStatus('loading');
internalId.current = null;
Expand Down
6 changes: 6 additions & 0 deletions src/client-library/deriv-api-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,12 @@ export class DerivAPIClient {
}
}

async unsubscribeAll() {
for (const subs of this.subscribeHandler.values()) {
await this.send({ name: 'forget', payload: { forget: subs.subscription_id } });
}
}

isSocketClosingOrClosed() {
return ![2, 3].includes(this.websocket.readyState);
}
Expand Down
33 changes: 15 additions & 18 deletions src/client-library/deriv-api-manager.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,4 @@
import { TSocketEndpointNames, TSocketSubscribableEndpointNames } from '../types/api.types';
import {
DerivAPIClient,
DerivAPIClientOptions,
SendFunctionArgs,
SubscribeFunctionArgs,
UnsubscribeHandlerArgs,
} from './deriv-api-client';
import { DerivAPIClient, DerivAPIClientOptions } from './deriv-api-client';

export class DerivAPIManager {
options?: DerivAPIClientOptions;
Expand All @@ -19,26 +12,30 @@ export class DerivAPIManager {
this.options = options;
}

async send<T extends TSocketEndpointNames>(args: SendFunctionArgs<T>) {
return this.activeClient.send(args);
}

async subscribe<T extends TSocketSubscribableEndpointNames>(args: SubscribeFunctionArgs<T>) {
return this.activeClient.subscribe(args);
}

async unsubscribe(args: UnsubscribeHandlerArgs) {
return this.activeClient.unsubscribe(args);
getActiveClient() {
return this.activeClient;
}

async switchConnection(endpoint: string) {
const matchingInstance = this.clientList.get(endpoint);
if (matchingInstance) {
if (this.activeClient.websocket.url !== matchingInstance.websocket.url) {
// If does not match means we have to reinit and forget same like how we are doing with the new instances
await this.activeClient.unsubscribeAll();
await matchingInstance.reinitializeSubscriptions(
this.activeClient.subscribeHandler,
this.activeClient.authorizePayload
);
}
this.activeClient = matchingInstance;

return;
}
const subscribeHandlers = this.activeClient.subscribeHandler;
const newInstance = new DerivAPIClient(endpoint, this.options);
// We will call forget on all subscriptions in the old subscription list but maintain the onData reference of the subscription list
await this.activeClient.unsubscribeAll();
// Pass the reference to the new connection. Here we will re-subscribe and attach it to the handlers of the new one
await newInstance.reinitializeSubscriptions(subscribeHandlers, this.activeClient.authorizePayload);
this.clientList.set(endpoint, newInstance);
this.activeClient = newInstance;
Expand Down

0 comments on commit d810de3

Please sign in to comment.