From 99854c2fa918d5b8a61ab1b3207dc92fe594bdd7 Mon Sep 17 00:00:00 2001 From: Sandipsinh Rathod Date: Tue, 1 Oct 2024 00:53:05 -0400 Subject: [PATCH] introduce `dedupe.graphql` --- ...test__should_generate_combined_config.snap | 2 +- ...__should_generate_config_from_configs.snap | 2 +- src/core/jit/model.rs | 25 ++++++--- .../fixtures/configs/dedupe.graphql | 54 +++++++++++++++++++ .../fixtures/configs/jsonplaceholder.graphql | 2 +- 5 files changed, 74 insertions(+), 11 deletions(-) create mode 100644 tailcall-fixtures/fixtures/configs/dedupe.graphql diff --git a/src/core/generator/snapshots/tailcall__core__generator__generator__test__should_generate_combined_config.snap b/src/core/generator/snapshots/tailcall__core__generator__generator__test__should_generate_combined_config.snap index 34541a5d38..c102b794a6 100644 --- a/src/core/generator/snapshots/tailcall__core__generator__generator__test__should_generate_combined_config.snap +++ b/src/core/generator/snapshots/tailcall__core__generator__generator__test__should_generate_combined_config.snap @@ -86,7 +86,7 @@ type Query { GEN__news__NewsService__GetNews(newsId: Id!): News @grpc(body: "{{.args.newsId}}", method: "news.NewsService.GetNews") inCompatibleProperties: InCompatibleProperty @http(path: "/") post(id: Int! = 1): Post @http(path: "/posts/{{.args.id}}") - posts: [Post] @http(path: "/posts?_limit=11", dedupe: true) + posts: [Post] @http(path: "/posts?_limit=11") user(id: Int!): User @http(path: "/users/{{.args.id}}") users: [User] @http(path: "/users") } diff --git a/src/core/generator/snapshots/tailcall__core__generator__generator__test__should_generate_config_from_configs.snap b/src/core/generator/snapshots/tailcall__core__generator__generator__test__should_generate_config_from_configs.snap index 1004f287dd..ab4e5fc607 100644 --- a/src/core/generator/snapshots/tailcall__core__generator__generator__test__should_generate_config_from_configs.snap +++ b/src/core/generator/snapshots/tailcall__core__generator__generator__test__should_generate_config_from_configs.snap @@ -40,7 +40,7 @@ type Post { type Query { post(id: Int! = 1): Post @http(path: "/posts/{{.args.id}}") - posts: [Post] @http(path: "/posts?_limit=11", dedupe: true) + posts: [Post] @http(path: "/posts?_limit=11") user(id: Int!): User @http(path: "/users/{{.args.id}}") users: [User] @http(path: "/users") } diff --git a/src/core/jit/model.rs b/src/core/jit/model.rs index a045a2e091..57d4d98478 100644 --- a/src/core/jit/model.rs +++ b/src/core/jit/model.rs @@ -411,17 +411,28 @@ impl OperationPlan { .map(|f| f.into_nested(&fields)) .collect::>(); + // by default dedupe should be set to false + // then we check if there is any ir with dedupe set to true + // in that case we set is_dedupe to true let mut is_dedupe = false; + // if there is any ir with dedupe set to false + // in that case we set is_not_dedupe to true + let mut is_not_dedupe = false; for field in fields.iter() { - if let Some(val) = field.ir.as_ref() { - if let IR::IO(io) = val { - is_dedupe = is_dedupe && !io.dedupe(); + if let Some(IR::IO(io)) = field.ir.as_ref() { + if io.dedupe() { + is_dedupe = true; + } else { + is_not_dedupe = true; } } } - let dedupe = !is_dedupe; + // now we check if all the IRs have dedupe set to true + // this method is more accurate then `filter.all(...)` + // because this could handle a list with no elements + let dedupe = is_dedupe && !is_not_dedupe; Self { root_name: root_name.to_string(), @@ -715,8 +726,7 @@ mod test { #[test] fn test_operation_plan_dedupe() { let config = - include_config!("../../../tailcall-fixtures/fixtures/configs/jsonplaceholder.graphql") - .unwrap(); + include_config!("../../../tailcall-fixtures/fixtures/configs/dedupe.graphql").unwrap(); let module = ConfigModule::from(config); let bp = Blueprint::try_from(&module).unwrap(); @@ -730,8 +740,7 @@ mod test { #[test] fn test_operation_plan_dedupe_false() { let config = - include_config!("../../../tailcall-fixtures/fixtures/configs/jsonplaceholder.graphql") - .unwrap(); + include_config!("../../../tailcall-fixtures/fixtures/configs/dedupe.graphql").unwrap(); let module = ConfigModule::from(config); let bp = Blueprint::try_from(&module).unwrap(); diff --git a/tailcall-fixtures/fixtures/configs/dedupe.graphql b/tailcall-fixtures/fixtures/configs/dedupe.graphql new file mode 100644 index 0000000000..f657d4048b --- /dev/null +++ b/tailcall-fixtures/fixtures/configs/dedupe.graphql @@ -0,0 +1,54 @@ +schema + @server(port: 8000, hostname: "0.0.0.0") + @upstream(baseURL: "http://jsonplaceholder.typicode.com", httpCache: 42) { + query: Query +} + +type Query { + posts: [Post] @http(path: "/posts?_limit=11", dedupe: true) + users: [User] @http(path: "/users") + user(id: Int!): User @http(path: "/users/{{.args.id}}") + post(id: Int! = 1): Post @http(path: "/posts/{{.args.id}}") +} + +type User { + id: Int! + name: String! + username: String! + email: String! + phone: String + blog: String @expr(body: "https://test.blog/users/website/{{.value.username}}") + albums: [Album] @http(path: "/users/{{.value.id}}/albums?_limit=2") +} + +type Post { + id: Int! + userId: Int! + title: String! + body: String! + user: User @http(path: "/users/{{.value.userId}}") + users: [User] @http(path: "/users") + comments: [Comment] @http(path: "/posts/{{.value.id}}/comments") +} + +type Comment { + id: Int! + name: String! + email: String! + body: String! + title: String! @expr(body: "{{.value.email}}: {{.value.name}}") +} + +type Photo { + albumId: Int! + id: Int! + title: String! + combinedId: String! @expr(body: "Album: {{.value.albumId}}, photo: {{.value.id}}") +} + +type Album { + userId: Int! + id: Int! + title: Int + photos: [Photo] @http(path: "/albums/{{.value.id}}/photos?_limit=3") +} diff --git a/tailcall-fixtures/fixtures/configs/jsonplaceholder.graphql b/tailcall-fixtures/fixtures/configs/jsonplaceholder.graphql index f657d4048b..ae41585800 100644 --- a/tailcall-fixtures/fixtures/configs/jsonplaceholder.graphql +++ b/tailcall-fixtures/fixtures/configs/jsonplaceholder.graphql @@ -5,7 +5,7 @@ schema } type Query { - posts: [Post] @http(path: "/posts?_limit=11", dedupe: true) + posts: [Post] @http(path: "/posts?_limit=11") users: [User] @http(path: "/users") user(id: Int!): User @http(path: "/users/{{.args.id}}") post(id: Int! = 1): Post @http(path: "/posts/{{.args.id}}")