Skip to content

Commit bd03b52

Browse files
committed
feat(sdk): eager DDPSDK connect, drop Meteor fallback from sdk.call/publish/stream
DDPSDK's Connection buffers outgoing messages until the WebSocket handshake completes, so downstream call sites don't actually need an isDdpSdkReady gate. Open the socket as soon as getDdpSdk() runs and drop the Meteor fallback from sdk.call / sdk.publish / the stream factory. Pre-authentication, anonymous methods / streams still work (the SDK queues them and flushes on 'connected'); authenticated methods will surface a server auth error the same way an unauthenticated Meteor call would. userIdStore continues to drive loginWithToken so the SDK becomes authenticated as soon as either session resume or a fresh login sets a uid. createNewMeteorStream stays in the file for now (no longer reachable) — removing it and the Meteor._stream('message') listener is left for the cleanup pass once Meteor.connection is fully neutralised.
1 parent 78a4bf9 commit bd03b52

2 files changed

Lines changed: 20 additions & 25 deletions

File tree

apps/meteor/app/utils/client/lib/SDKClient.ts

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -268,9 +268,7 @@ const createStreamManager = () => {
268268

269269
const stream =
270270
streams.get(eventLiteral) ||
271-
(isDdpSdkReady()
272-
? createNewDdpSdkStream(streamProxy, name as StreamNames, key as StreamKeys<StreamNames>, args)
273-
: createNewMeteorStream(name as StreamNames, key as StreamKeys<StreamNames>, args));
271+
createNewDdpSdkStream(streamProxy, name as StreamNames, key as StreamKeys<StreamNames>, args);
274272

275273
const stop = (): void => {
276274
streamProxy.off(eventLiteral, proxyCallback);
@@ -322,27 +320,17 @@ const createStreamManager = () => {
322320
return { stream, stopAll };
323321
};
324322

325-
const isDdpSdkReady = (): boolean => {
326-
const sdk = getDdpSdk();
327-
return sdk.connection.status === 'connected' && Boolean(sdk.account.uid);
328-
};
329-
330323
export const createSDK = (rest: RestClientInterface) => {
331324
const { stream, stopAll } = createStreamManager();
332325

333326
const publish = (name: string, args: unknown[]) => {
334-
if (isDdpSdkReady()) {
335-
void getDdpSdk().client.callAsync(`stream-${name}`, ...args);
336-
return;
337-
}
338-
Meteor.call(`stream-${name}`, ...args);
327+
// DDPSDK queues writes until the WS handshake completes and reconnects
328+
// automatically, so there's no longer a Meteor fallback path here.
329+
void getDdpSdk().client.callAsync(`stream-${name}`, ...args);
339330
};
340331

341332
const call = <T extends keyof ServerMethods>(method: T, ...args: Parameters<ServerMethods[T]>): Promise<ReturnType<ServerMethods[T]>> => {
342-
if (isDdpSdkReady()) {
343-
return getDdpSdk().client.callAsync(method, ...args) as Promise<ReturnType<ServerMethods[T]>>;
344-
}
345-
return Meteor.callAsync(method, ...args);
333+
return getDdpSdk().client.callAsync(method, ...args) as Promise<ReturnType<ServerMethods[T]>>;
346334
};
347335

348336
const disconnect = () => {

apps/meteor/client/lib/sdk/ddpSdk.ts

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ import EJSON from 'ejson';
44
import { userIdStore } from '../user';
55

66
/**
7-
* Phase 2 scaffolding for migrating the frontend off Meteor.connection onto
8-
* @rocket.chat/ddp-client.
7+
* Primary DDP transport for the frontend, replacing Meteor.connection.
98
*
10-
* The instance is constructed lazily pointing at the current origin. A
11-
* Zustand subscription on userIdStore keeps the SDK connected +
12-
* authenticated whenever a user is logged in (covering both session
13-
* resume and fresh logins) and tears it down on logout. Failures are
14-
* logged but non-fatal — the Meteor transport remains authoritative
15-
* while this runs in parallel.
9+
* The lazy getter constructs the SDK on first use and eagerly opens the
10+
* WebSocket. DDPSDK internally queues outgoing messages until the WS
11+
* handshake completes, so sdk.call / sdk.stream / sdk.publish work the
12+
* instant the module loads — no `isReady` gate needed at the call sites.
13+
*
14+
* A userIdStore subscription drives loginWithToken on login (session
15+
* resume and fresh logins) and tears the connection down on logout.
1616
*/
1717

1818
const stripTrailingSlash = (value: string): string => (value.endsWith('/') ? value.slice(0, -1) : value);
@@ -47,6 +47,13 @@ export const getDdpSdk = (): DDPSDK => {
4747
if (!instance) {
4848
instance = DDPSDK.create(computeDdpUrl());
4949
applyEjsonEncoding(instance);
50+
// Open the socket immediately. DDPSDK queues everything written before
51+
// the WS is open and flushes on 'connected', so downstream call sites
52+
// don't have to care about timing.
53+
void instance.connection.connect().catch((error) => {
54+
// eslint-disable-next-line no-console
55+
console.warn('[ddpSdk] initial connect failed', error);
56+
});
5057
}
5158
return instance;
5259
};

0 commit comments

Comments
 (0)