Skip to content

Commit

Permalink
updated graphql API singleton to use separate realtime providers per …
Browse files Browse the repository at this point in the history
…endpoint
  • Loading branch information
Jon Wire committed Dec 18, 2024
1 parent 7f6a612 commit e61d28d
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 11 deletions.
54 changes: 48 additions & 6 deletions packages/api-graphql/__tests__/internals/generateClient.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,14 @@ describe('generateClient', () => {
const client = generateClient<Schema>({ amplify: Amplify });

const spy = jest.fn(() => from([graphqlMessage]));
(raw.GraphQLAPI as any).appSyncRealTime = { subscribe: spy };
(raw.GraphQLAPI as any).appSyncRealTime = {
get() {
return { subscribe: spy }
},
set() {
// not needed for test mock
}
};

expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot();

Expand Down Expand Up @@ -497,7 +504,14 @@ describe('generateClient', () => {
const client = generateClient<Schema>({ amplify: Amplify });

const spy = jest.fn(() => from([graphqlMessage]));
(raw.GraphQLAPI as any).appSyncRealTime = { subscribe: spy };
(raw.GraphQLAPI as any).appSyncRealTime = {
get() {
return { subscribe: spy }
},
set() {
// not needed for test mock
}
};

client.models.Note.onCreate({
filter: graphqlVariables.filter,
Expand Down Expand Up @@ -531,7 +545,14 @@ describe('generateClient', () => {
});

const spy = jest.fn(() => from([graphqlMessage]));
(raw.GraphQLAPI as any).appSyncRealTime = { subscribe: spy };
(raw.GraphQLAPI as any).appSyncRealTime = {
get() {
return { subscribe: spy }
},
set() {
// not needed for test mock
}
};

client.models.Note.onCreate({
filter: graphqlVariables.filter,
Expand Down Expand Up @@ -561,7 +582,14 @@ describe('generateClient', () => {
const client = generateClient<Schema>({ amplify: Amplify });

const spy = jest.fn(() => from([graphqlMessage]));
(raw.GraphQLAPI as any).appSyncRealTime = { subscribe: spy };
(raw.GraphQLAPI as any).appSyncRealTime = {
get() {
return { subscribe: spy }
},
set() {
// not needed for test mock
}
};

client.models.Note.onCreate({
filter: graphqlVariables.filter,
Expand All @@ -583,7 +611,14 @@ describe('generateClient', () => {
const client = generateClient<Schema>({ amplify: Amplify });

const spy = jest.fn(() => from([graphqlMessage]));
(raw.GraphQLAPI as any).appSyncRealTime = { subscribe: spy };
(raw.GraphQLAPI as any).appSyncRealTime = {
get() {
return { subscribe: spy }
},
set() {
// not needed for test mock
}
};

client.models.Note.onCreate({
filter: graphqlVariables.filter,
Expand Down Expand Up @@ -711,7 +746,14 @@ describe('generateClient', () => {
const client = generateClient<Schema>({ amplify: Amplify });

const spy = jest.fn(() => from([graphqlMessage]));
(raw.GraphQLAPI as any).appSyncRealTime = { subscribe: spy };
(raw.GraphQLAPI as any).appSyncRealTime = {
get() {
return { subscribe: spy }
},
set() {
// not needed for test mock
}
};

client.models.Note.onCreate({
filter: graphqlVariables.filter,
Expand Down
20 changes: 17 additions & 3 deletions packages/api-graphql/src/internals/InternalGraphQLAPI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export class InternalGraphQLAPIClass {
/**
* @private
*/
private appSyncRealTime = new AWSAppSyncRealTimeProvider();
private appSyncRealTime = new Map<string, AWSAppSyncRealTimeProvider>();

private _api = {
post,
Expand Down Expand Up @@ -384,12 +384,26 @@ export class InternalGraphQLAPIClass {
*/
const { headers: libraryConfigHeaders } = resolveLibraryOptions(amplify);

return this.appSyncRealTime
const appSyncGraphqlEndpoint = endpoint ?? config?.endpoint;

if (!appSyncGraphqlEndpoint) {
throw new Error(
'Endpoint missing from subscription query. An endpoint must either be configured or provided at the call site.',
);
}

const realtimeProvider =
this.appSyncRealTime.get(appSyncGraphqlEndpoint!) ??
new AWSAppSyncRealTimeProvider();

this.appSyncRealTime.set(appSyncGraphqlEndpoint, realtimeProvider);

return realtimeProvider
.subscribe(
{
query: print(query as DocumentNode),
variables,
appSyncGraphqlEndpoint: endpoint ?? config?.endpoint,
appSyncGraphqlEndpoint,
region: config?.region,
authenticationType: authMode,
apiKey: apiKeyOverride ?? config?.apiKey,
Expand Down
18 changes: 16 additions & 2 deletions packages/api/__tests__/API.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,20 @@ const DEFAULT_AUTH_TOKEN =
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjE3MTAyOTMxMzB9.YzDpgJsrB3z-ZU1XxMcXSQsMbgCzwH_e-_76rnfehh0';

const _postSpy = jest.spyOn((GraphQLAPI as any)._api, 'post');
const _subspy = jest.spyOn((GraphQLAPI as any).appSyncRealTime, 'subscribe');
const _subspy = jest.fn();

/**
* Should be called on every subscription, ensuring that realtime provider instances
* are re-used for each distinct endpoint.
*/
const _setProviderSpy = jest.fn();

(GraphQLAPI as any).appSyncRealTime = {
get() {
return { subscribe: _subspy }
},
set: _setProviderSpy
};

/**
* Validates that a specific "post" occurred (against `_postSpy`).
Expand Down Expand Up @@ -116,6 +129,7 @@ function expectSubscription({
}),
expect.anything(),
);
expect(_setProviderSpy).toHaveBeenCalledWith(endpoint, expect.anything());
}

/**
Expand Down Expand Up @@ -204,7 +218,7 @@ describe('generateClient (web)', () => {
});

afterEach(() => {
jest.resetAllMocks();
jest.clearAllMocks();
});

for (const op of ['query', 'subscription'] as const) {
Expand Down

0 comments on commit e61d28d

Please sign in to comment.