Skip to content

Commit 7cc280b

Browse files
committed
fix: review comments
1 parent 89af114 commit 7cc280b

4 files changed

Lines changed: 58 additions & 4 deletions

File tree

composition/src/v1/warnings/params.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,9 @@ export type InvalidRepeatedComposedDirectiveWarningParams = {
1616
directiveName: DirectiveName;
1717
printedDirective: string;
1818
};
19+
20+
export type RequestScopedSingleFieldWarningParams = {
21+
subgraphName: SubgraphName;
22+
key: string;
23+
fieldCoords: string;
24+
};

composition/src/v1/warnings/warnings.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { Warning } from '../../warnings/types';
22
import { QUOTATION_JOIN } from '../../utils/string-constants';
33
import {
44
type InvalidRepeatedComposedDirectiveWarningParams,
5+
type RequestScopedSingleFieldWarningParams,
56
type SingleFederatedInputFieldOneOfWarningParams,
67
type SingleSubgraphInputFieldOneOfWarningParams,
78
} from './params';
@@ -192,6 +193,22 @@ export function singleSubgraphInputFieldOneOfWarning({
192193
});
193194
}
194195

196+
export function requestScopedSingleFieldWarning({
197+
subgraphName,
198+
key,
199+
fieldCoords,
200+
}: RequestScopedSingleFieldWarningParams): Warning {
201+
return new Warning({
202+
message:
203+
`@openfed__requestScoped(key: "${key}") is declared on only one field ("${fieldCoords}") in this subgraph.` +
204+
` The directive is meaningless unless at least 2 fields share the same key so that the second and` +
205+
` subsequent fields can be served from the per-request L1 cache populated by the first.`,
206+
subgraph: {
207+
name: subgraphName,
208+
},
209+
});
210+
}
211+
195212
export function singleFederatedInputFieldOneOfWarning({
196213
fieldName,
197214
typeName,

composition/tests/v1/directives/request-scoped.test.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import { describe, expect, test } from 'vitest';
22
import {
3-
DIRECTIVE_DEFINITION_BY_NAME,
43
FIRST_ORDINAL,
54
invalidDirectiveError,
65
invalidRepeatedDirectiveErrorMessage,
76
OPENFED_REQUEST_SCOPED,
87
OPENFED_REQUEST_SCOPED_DEFINITION,
8+
requestScopedSingleFieldWarning,
99
ROUTER_COMPATIBILITY_VERSION_ONE,
1010
undefinedRequiredArgumentsErrorMessage,
1111
} from '../../../src';
@@ -71,6 +71,30 @@ describe('@openfed__requestScoped tests', () => {
7171
expect(config!.entityCaching!.requestScopedConfigurations![0].fieldName).toBe('currentLocale');
7272
expect(config!.entityCaching!.requestScopedConfigurations![0].l1Key).toBe('subgraph-default-a.locale');
7373
});
74+
75+
test('that a key declared on only one field still populates config but emits a warning', () => {
76+
const result = normalizeSubgraphSuccess(
77+
createSubgraphWithDefaultName(`
78+
type Query {
79+
currentUser: User @openfed__requestScoped(key: "lonely")
80+
}
81+
type User @key(fields: "id") {
82+
id: ID!
83+
}
84+
`),
85+
ROUTER_COMPATIBILITY_VERSION_ONE,
86+
);
87+
const config = result.configurationDataByTypeName.get('Query');
88+
expect(config!.entityCaching?.requestScopedConfigurations).toHaveLength(1);
89+
expect(config!.entityCaching!.requestScopedConfigurations![0].l1Key).toBe('subgraph-default-a.lonely');
90+
expect(result.warnings).toStrictEqual([
91+
requestScopedSingleFieldWarning({
92+
subgraphName: 'subgraph-default-a',
93+
key: 'lonely',
94+
fieldCoords: 'Query.currentUser',
95+
}),
96+
]);
97+
});
7498
});
7599

76100
describe('validation tests', () => {

shared/src/router-config/builder.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,9 @@ function costsToCostConfiguration(costs?: Costs): CostConfiguration | undefined
8080
* @returns The `EntityCaching` message, or `undefined` when empty so the field is omitted (like
8181
* `costsToCostConfiguration`).
8282
*/
83-
function extractEntityCachingConfiguration(dataByTypeName?: Map<TypeName, ConfigurationData>): EntityCachingConfiguration | undefined {
83+
function extractEntityCachingConfiguration(
84+
dataByTypeName?: Map<TypeName, ConfigurationData>,
85+
): EntityCachingConfiguration | undefined {
8486
if (!dataByTypeName) {
8587
return;
8688
}
@@ -134,8 +136,13 @@ function extractEntityCachingConfiguration(dataByTypeName?: Map<TypeName, Config
134136
);
135137
}
136138
}
137-
if (entityCache.length > 0 || cacheInvalidateConfigurations.length > 0 || cachePopulateConfigurations.length > 0 || requestScopedConfigurations.length > 0) {
138-
return new EntityCachingConfiguration({
139+
if (
140+
entityCache.length > 0 ||
141+
cacheInvalidateConfigurations.length > 0 ||
142+
cachePopulateConfigurations.length > 0 ||
143+
requestScopedConfigurations.length > 0
144+
) {
145+
return new EntityCachingConfiguration({
139146
entityCache,
140147
cacheInvalidateConfigurations,
141148
cachePopulateConfigurations,

0 commit comments

Comments
 (0)