From 724034855db747d456110156758cb4b8cad26cc1 Mon Sep 17 00:00:00 2001 From: Kamil Kisiela Date: Fri, 3 Nov 2023 08:51:41 +0100 Subject: [PATCH] Support graphql-jit (#2465) --- .changeset/tidy-masks-reply.md | 5 + package.json | 1 + .../graphql-modules/src/module/resolvers.ts | 6 +- .../tests/execution-context.spec.ts | 164 ++++++++++++++++++ yarn.lock | 92 +++++++++- 5 files changed, 264 insertions(+), 4 deletions(-) create mode 100644 .changeset/tidy-masks-reply.md diff --git a/.changeset/tidy-masks-reply.md b/.changeset/tidy-masks-reply.md new file mode 100644 index 0000000000..74fc9e01c9 --- /dev/null +++ b/.changeset/tidy-masks-reply.md @@ -0,0 +1,5 @@ +--- +'graphql-modules': minor +--- + +Support graphql-jit diff --git a/package.json b/package.json index cbf76041aa..1fd561e589 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "@graphql-tools/merge": "9.0.0", "@graphql-yoga/node": "3.9.1", "@types/benchmark": "2.1.4", + "graphql-jit": "0.8.4", "@types/express": "4.17.20", "@types/jest": "27.5.2", "@types/node": "18.18.7", diff --git a/packages/graphql-modules/src/module/resolvers.ts b/packages/graphql-modules/src/module/resolvers.ts index cd9cc218f5..f74bebcc99 100644 --- a/packages/graphql-modules/src/module/resolvers.ts +++ b/packages/graphql-modules/src/module/resolvers.ts @@ -142,7 +142,11 @@ function wrapResolver({ ) => { const ctx = { root, - context: context.ɵgetModuleContext(config.id, context), + context: isReferenceResolver + ? context.ɵgetModuleContext(config.id, context) + : // We mark the context object as possibly undefined, + // because graphql-jit for some reason doesn't pass it for isTypeOf or resolveType methods + context?.ɵgetModuleContext(config.id, context), info, }; diff --git a/packages/graphql-modules/tests/execution-context.spec.ts b/packages/graphql-modules/tests/execution-context.spec.ts index 7bf4e9fef5..a41ac30bb8 100644 --- a/packages/graphql-modules/tests/execution-context.spec.ts +++ b/packages/graphql-modules/tests/execution-context.spec.ts @@ -11,6 +11,7 @@ import { CONTEXT, Inject, } from '../src'; +import { compileQuery, isCompiledQuery } from 'graphql-jit'; const posts = ['Foo', 'Bar']; @@ -634,3 +635,166 @@ test('accessing a singleton provider with execution context in another singleton }); } }); + +test('accessing a singleton provider with execution context in another singleton provider (parallel requests and graphql-jit)', async () => { + const spies = { + foo: jest.fn(), + bar: jest.fn(), + baz: jest.fn(), + }; + + const Name = new InjectionToken>('name'); + + @Injectable({ + scope: Scope.Singleton, + }) + class Foo { + @ExecutionContext() + public context!: ExecutionContext; + + constructor() { + spies.foo(); + } + + async getName() { + return this.context.injector.get(Name); + } + } + + @Injectable({ + scope: Scope.Singleton, + }) + class Bar { + constructor(private foo: Foo) { + spies.bar(); + } + + async getName() { + return this.foo.getName(); + } + } + + @Injectable({ + scope: Scope.Operation, + }) + class Baz { + constructor( + @Inject(Name) + private name: Promise + ) { + spies.baz(); + } + + async getName() { + return this.name; + } + } + + const mod = createModule({ + id: 'mod', + providers: [Foo, Bar, Baz], + typeDefs: gql` + type Query { + name: Name + } + + type Name { + getName: String + getDependencyName: String + getNameFromContext: String + } + `, + resolvers: { + Query: { + name: () => ({}), + }, + Name: { + // make sure that __isTypeOf works with JIT + __isTypeOf: () => true, + getName: async (_a: {}, _b: {}, { injector }: GraphQLModules.Context) => + injector.get(Foo).getName(), + getDependencyName: async ( + _a: {}, + _b: {}, + { injector }: GraphQLModules.Context + ) => injector.get(Bar).getName(), + getNameFromContext: async ( + _a: {}, + _b: {}, + { injector }: GraphQLModules.Context + ) => injector.get(Baz).getName(), + }, + }, + }); + + const app = createApplication({ + modules: [mod], + providers: [ + { + provide: Name, + scope: Scope.Operation, + useFactory(ctx) { + return new Promise((resolve) => { + setTimeout(() => { + resolve(`request-${ctx.requestId}`); + }, Math.random() * 200); + }); + }, + deps: [CONTEXT], + }, + ], + }); + + const requests = new Array({ length: 5 }).map((_, i) => i); + + const query = gql` + { + name { + getName + getDependencyName + getNameFromContext + } + } + `; + const compiledQuery = compileQuery(app.schema, query, undefined); + + if (!isCompiledQuery(compiledQuery)) { + throw new Error('Failed to to compile a query'); + } + + const results = await Promise.all( + requests.map(async (i) => { + const controller = app.createOperationController({ + context: { + requestId: i, + }, + autoDestroy: false, + }); + return Promise.resolve( + compiledQuery.query( + {}, // root + controller.context, // context + {} // variables + ) + ).finally(() => { + controller.destroy(); + }); + }) + ); + + expect(spies.bar).toHaveBeenCalledTimes(results.length); + expect(spies.foo).toHaveBeenCalledTimes(results.length); + + for (let i = 0; i < results.length; i++) { + const result = results[i]; + const expectedName = `request-${i}`; + expect(result.errors).not.toBeDefined(); + expect(result.data).toEqual({ + name: { + getName: expectedName, + getDependencyName: expectedName, + getNameFromContext: expectedName, + }, + }); + } +}); diff --git a/yarn.lock b/yarn.lock index 5913de8755..776370b043 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1605,6 +1605,11 @@ resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.52.0.tgz#78fe5f117840f69dc4a353adf9b9cd926353378c" integrity sha512-mjZVbpaeMZludF2fsWLD0Z9gCref1Tk4i9+wddjRvpUNqqcndPkBD09N/Mapey0b3jaXbLm2kICwFv2E64QinA== +"@fastify/deepmerge@^1.0.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@fastify/deepmerge/-/deepmerge-1.3.0.tgz#8116858108f0c7d9fd460d05a7d637a13fe3239a" + integrity sha512-J8TOSBq3SoZbDhM9+R/u77hP93gz/rajSA+K2kGyijPpORPWUXHUpTaleoj+92As0S9uPRP7Oi8IqMf0u+ro6A== + "@giscus/react@2.3.0": version "2.3.0" resolved "https://registry.yarnpkg.com/@giscus/react/-/react-2.3.0.tgz#1c13f2f96bb67684d4f5288dc1ed3155ff307ce4" @@ -1755,7 +1760,7 @@ tslib "^2.4.0" value-or-promise "^1.0.12" -"@graphql-typed-document-node/core@3.2.0", "@graphql-typed-document-node/core@^3.1.0", "@graphql-typed-document-node/core@^3.1.1": +"@graphql-typed-document-node/core@3.2.0", "@graphql-typed-document-node/core@^3.1.0", "@graphql-typed-document-node/core@^3.1.1", "@graphql-typed-document-node/core@^3.2.0": version "3.2.0" resolved "https://registry.yarnpkg.com/@graphql-typed-document-node/core/-/core-3.2.0.tgz#5f3d96ec6b2354ad6d8a28bf216a1d97b5426861" integrity sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ== @@ -3339,6 +3344,13 @@ agentkeepalive@^4.1.4: dependencies: humanize-ms "^1.2.1" +ajv-formats@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" + integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA== + dependencies: + ajv "^8.0.0" + ajv-keywords@^3.5.2: version "3.5.2" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" @@ -3354,6 +3366,16 @@ ajv@^6.12.4: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +ajv@^8.0.0, ajv@^8.10.0: + version "8.12.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" + integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + algoliasearch@4.19.1, algoliasearch@^4.14.3: version "4.19.1" resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-4.19.1.tgz#18111fb422eaf841737adb92d5ab12133d244218" @@ -6210,6 +6232,19 @@ fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0, fast-json-sta resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== +fast-json-stringify@^5.7.0: + version "5.9.0" + resolved "https://registry.yarnpkg.com/fast-json-stringify/-/fast-json-stringify-5.9.0.tgz#fdf029f72e2548a55aca87ed8b238364a8619f59" + integrity sha512-hXu5mchOrV7r1wzY2na0VEJZbb2gUAv5Mrlnq1QvdhZHt8k3pYnwZ6YEVbasbvPc1Ki+FyeTRJW8yDN9jN40yQ== + dependencies: + "@fastify/deepmerge" "^1.0.0" + ajv "^8.10.0" + ajv-formats "^2.1.1" + fast-deep-equal "^3.1.3" + fast-uri "^2.1.0" + json-schema-ref-resolver "^1.0.1" + rfdc "^1.2.0" + fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" @@ -6222,6 +6257,11 @@ fast-querystring@^1.1.1: dependencies: fast-decode-uri-component "^1.0.1" +fast-uri@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-2.3.0.tgz#bdae493942483d299e7285dcb4627767d42e2793" + integrity sha512-eel5UKGn369gGEWOqBShmFJWfq/xSJvsgDzgLYC845GneayWvXBf0lJCBn5qTABfewy1ZDPoaR5OZCP+kssfuw== + fast-url-parser@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/fast-url-parser/-/fast-url-parser-1.1.3.tgz#f4af3ea9f34d8a271cf58ad2b3759f431f0b318d" @@ -6472,6 +6512,13 @@ fuzzy@^0.1.3: resolved "https://registry.yarnpkg.com/fuzzy/-/fuzzy-0.1.3.tgz#4c76ec2ff0ac1a36a9dccf9a00df8623078d4ed8" integrity sha512-/gZffu4ykarLrCiP3Ygsa86UAo1E5vEVlvTrpkKywXSbP9Xhln3oSp9QSV57gEq3JFFpGJ4GZ+5zdEp3FcUh4w== +generate-function@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.3.1.tgz#f069617690c10c868e73b8465746764f97c3479f" + integrity sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ== + dependencies: + is-property "^1.0.2" + gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" @@ -6676,6 +6723,18 @@ graphemer@^1.4.0: resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== +graphql-jit@0.8.4: + version "0.8.4" + resolved "https://registry.yarnpkg.com/graphql-jit/-/graphql-jit-0.8.4.tgz#53c2e43b90ec98ea0942f4062516de910fbff709" + integrity sha512-4KRrJ1ROy3Usgbl3eAoUMfdfZCRjkcw9cCGT7QwTUIHm9dPGaSaldxzGUttyjErU0rsYEb6WWyb6mMh5r6lEoQ== + dependencies: + "@graphql-typed-document-node/core" "^3.2.0" + fast-json-stringify "^5.7.0" + generate-function "^2.3.1" + lodash.memoize "^4.1.2" + lodash.merge "4.6.2" + lodash.mergewith "4.6.2" + graphql-subscriptions@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/graphql-subscriptions/-/graphql-subscriptions-2.0.0.tgz#11ec181d475852d8aec879183e8e1eb94f2eb79a" @@ -7464,6 +7523,11 @@ is-potential-custom-element-name@^1.0.1: resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== +is-property@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" + integrity sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g== + is-redirect@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24" @@ -8184,11 +8248,23 @@ json-parse-even-better-errors@^2.3.0: resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== +json-schema-ref-resolver@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-schema-ref-resolver/-/json-schema-ref-resolver-1.0.1.tgz#6586f483b76254784fc1d2120f717bdc9f0a99bf" + integrity sha512-EJAj1pgHc1hxF6vo2Z3s69fMjO1INq6eGHXZ8Z6wCQeldCuwxGK9Sxf4/cScGn3FZubCVUehfWtcDM/PLteCQw== + dependencies: + fast-deep-equal "^3.1.3" + json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" @@ -8453,11 +8529,16 @@ lodash.memoize@4.x, lodash.memoize@^4.1.2: resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== -lodash.merge@^4.6.2: +lodash.merge@4.6.2, lodash.merge@^4.6.2: version "4.6.2" resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== +lodash.mergewith@4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz#617121f89ac55f59047c7aec1ccd6654c6590f55" + integrity sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ== + lodash.sortby@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" @@ -11165,6 +11246,11 @@ require-directory@^2.1.1: resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + require-main-filename@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" @@ -11251,7 +11337,7 @@ reusify@^1.0.4: resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== -rfdc@^1.3.0: +rfdc@^1.2.0, rfdc@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b" integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==