diff --git a/linera-sdk/tests/fixtures/Cargo.lock b/linera-sdk/tests/fixtures/Cargo.lock index 418bc2d6a80..d0632e94e8f 100644 --- a/linera-sdk/tests/fixtures/Cargo.lock +++ b/linera-sdk/tests/fixtures/Cargo.lock @@ -1577,6 +1577,16 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" +[[package]] +name = "graph-ql-queries" +version = "0.1.0" +dependencies = [ + "async-graphql", + "linera-sdk", + "serde", + "tokio", +] + [[package]] name = "group" version = "0.13.0" diff --git a/linera-sdk/tests/fixtures/Cargo.toml b/linera-sdk/tests/fixtures/Cargo.toml index 0d487f8f6e6..2f735d897b4 100644 --- a/linera-sdk/tests/fixtures/Cargo.toml +++ b/linera-sdk/tests/fixtures/Cargo.toml @@ -3,6 +3,7 @@ resolver = "2" members = [ "contract-call", "create-and-call", + "graph-ql-queries", "meta-counter", "publish-read-data-blob", "time-expiry", @@ -20,6 +21,7 @@ contract-call = { path = "./create-and-call" } counter = { path = "../../../examples/counter" } counter-no-graphql = { path = "../../../examples/counter-no-graphql" } create-and-call = { path = "./create-and-call" } +graph-ql-queries = { path = "./graph-ql-queries" } meta-counter = { path = "./meta-counter" } publish-read-data-blob = { path = "./publish-read-data-blob" } time-expiry = { path = "./time-expiry" } diff --git a/linera-sdk/tests/fixtures/graph-ql-queries/Cargo.toml b/linera-sdk/tests/fixtures/graph-ql-queries/Cargo.toml new file mode 100644 index 00000000000..199f0756d64 --- /dev/null +++ b/linera-sdk/tests/fixtures/graph-ql-queries/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "graph-ql-queries" +version = "0.1.0" +authors = ["Linera "] +edition = "2021" + +[dependencies] +async-graphql.workspace = true +linera-sdk.workspace = true +serde.workspace = true + +[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] +linera-sdk = { workspace = true, features = ["test", "wasmer"] } +tokio = { workspace = true, features = ["rt", "sync"] } + +[dev-dependencies] +linera-sdk = { workspace = true, features = ["test"] } + +[[bin]] +name = "graph_ql_queries_contract" +path = "src/contract.rs" + +[[bin]] +name = "graph_ql_queries_service" +path = "src/service.rs" diff --git a/linera-sdk/tests/fixtures/graph-ql-queries/src/contract.rs b/linera-sdk/tests/fixtures/graph-ql-queries/src/contract.rs new file mode 100644 index 00000000000..55142e16843 --- /dev/null +++ b/linera-sdk/tests/fixtures/graph-ql-queries/src/contract.rs @@ -0,0 +1,68 @@ +// Copyright (c) Zefchain Labs, Inc. +// SPDX-License-Identifier: Apache-2.0 + +#![cfg_attr(target_arch = "wasm32", no_main)] + +mod state; + +use graph_ql_queries::{GraphQlQueriesAbi, GraphQlQueriesOperation, GraphQlQueriesOperation::*}; +use linera_sdk::{ + linera_base_types::WithContractAbi, + views::{RootView, View}, + Contract, ContractRuntime, +}; + +use self::state::GraphQlQueriesState; + +pub struct GraphQlQueriesContract { + state: GraphQlQueriesState, +} + +linera_sdk::contract!(GraphQlQueriesContract); + +impl WithContractAbi for GraphQlQueriesContract { + type Abi = GraphQlQueriesAbi; +} + +impl Contract for GraphQlQueriesContract { + type Message = (); + type InstantiationArgument = (); + type Parameters = (); + type EventValue = (); + + async fn load(runtime: ContractRuntime) -> Self { + let state = GraphQlQueriesState::load(runtime.root_view_storage_context()) + .await + .expect("Failed to load state"); + GraphQlQueriesContract { state } + } + + async fn instantiate(&mut self, _value: ()) {} + + async fn execute_operation(&mut self, operation: GraphQlQueriesOperation) { + match operation { + SetRegister { value } => { + self.state.reg.set(value); + } + InsertMapString { key, value } => { + self.state.map_s.insert(&key, value).unwrap(); + } + InsertCollString { key, value } => { + let subview = self.state.coll_s.load_entry_mut(&key).await.unwrap(); + subview.set(value); + } + InsertCollMap { key1, key2, value } => { + let subview = self.state.coll_map.load_entry_mut(&key1).await.unwrap(); + subview.insert(&key2, value).unwrap(); + } + } + } + + async fn execute_message(&mut self, _message: ()) { + panic!("Counter application doesn't support any cross-chain messages"); + } + + async fn store(mut self) { + self.state.save().await.expect("Failed to save state"); + } +} diff --git a/linera-sdk/tests/fixtures/graph-ql-queries/src/lib.rs b/linera-sdk/tests/fixtures/graph-ql-queries/src/lib.rs new file mode 100644 index 00000000000..dffe4ffd083 --- /dev/null +++ b/linera-sdk/tests/fixtures/graph-ql-queries/src/lib.rs @@ -0,0 +1,39 @@ +// Copyright (c) Zefchain Labs, Inc. +// SPDX-License-Identifier: Apache-2.0 + +/*! ABI of the Counter Example Application */ + +use async_graphql::{Request, Response}; +use linera_sdk::{ + graphql::GraphQLMutationRoot, + linera_base_types::{ContractAbi, ServiceAbi}, +}; +use serde::{Deserialize, Serialize}; + +pub struct GraphQlQueriesAbi; + +#[derive(Debug, Deserialize, Serialize, GraphQLMutationRoot)] +pub enum GraphQlQueriesOperation { + /// Set the register + SetRegister { value: u64 }, + /// Insert in MapView + InsertMapString { key: String, value: u8 }, + /// Insert in CollectionView + InsertCollString { key: String, value: u8 }, + /// Insertion in the CollectionView / MapView + InsertCollMap { + key1: String, + key2: String, + value: u64, + }, +} + +impl ContractAbi for GraphQlQueriesAbi { + type Operation = GraphQlQueriesOperation; + type Response = (); +} + +impl ServiceAbi for GraphQlQueriesAbi { + type Query = Request; + type QueryResponse = Response; +} diff --git a/linera-sdk/tests/fixtures/graph-ql-queries/src/service.rs b/linera-sdk/tests/fixtures/graph-ql-queries/src/service.rs new file mode 100644 index 00000000000..c0d97eeb359 --- /dev/null +++ b/linera-sdk/tests/fixtures/graph-ql-queries/src/service.rs @@ -0,0 +1,52 @@ +// Copyright (c) Zefchain Labs, Inc. +// SPDX-License-Identifier: Apache-2.0 + +#![cfg_attr(target_arch = "wasm32", no_main)] + +mod state; + +use std::sync::Arc; + +use async_graphql::{EmptySubscription, Request, Response, Schema}; +use graph_ql_queries::{GraphQlQueriesAbi, GraphQlQueriesOperation}; +use linera_sdk::{ + graphql::GraphQLMutationRoot as _, linera_base_types::WithServiceAbi, views::View, Service, + ServiceRuntime, +}; + +use self::state::GraphQlQueriesState; + +pub struct GraphQlQueriesService { + state: Arc, + runtime: Arc>, +} + +linera_sdk::service!(GraphQlQueriesService); + +impl WithServiceAbi for GraphQlQueriesService { + type Abi = GraphQlQueriesAbi; +} + +impl Service for GraphQlQueriesService { + type Parameters = (); + + async fn new(runtime: ServiceRuntime) -> Self { + let state = GraphQlQueriesState::load(runtime.root_view_storage_context()) + .await + .expect("Failed to load state"); + GraphQlQueriesService { + state: Arc::new(state), + runtime: Arc::new(runtime), + } + } + + async fn handle_query(&self, request: Request) -> Response { + let schema = Schema::build( + self.state.clone(), + GraphQlQueriesOperation::mutation_root(self.runtime.clone()), + EmptySubscription, + ) + .finish(); + schema.execute(request).await + } +} diff --git a/linera-sdk/tests/fixtures/graph-ql-queries/src/state.rs b/linera-sdk/tests/fixtures/graph-ql-queries/src/state.rs new file mode 100644 index 00000000000..ff7dbb0eeff --- /dev/null +++ b/linera-sdk/tests/fixtures/graph-ql-queries/src/state.rs @@ -0,0 +1,16 @@ +// Copyright (c) Zefchain Labs, Inc. +// SPDX-License-Identifier: Apache-2.0 + +use linera_sdk::views::{ + linera_views, CollectionView, MapView, RegisterView, RootView, ViewStorageContext, +}; + +/// The application state. +#[derive(RootView, async_graphql::SimpleObject)] +#[view(context = ViewStorageContext)] +pub struct GraphQlQueriesState { + pub reg: RegisterView, + pub map_s: MapView, + pub coll_s: CollectionView>, + pub coll_map: CollectionView>, +} diff --git a/linera-sdk/tests/fixtures/graph-ql-queries/tests/graph_ql_operation.rs b/linera-sdk/tests/fixtures/graph-ql-queries/tests/graph_ql_operation.rs new file mode 100644 index 00000000000..2c9f7ff97e9 --- /dev/null +++ b/linera-sdk/tests/fixtures/graph-ql-queries/tests/graph_ql_operation.rs @@ -0,0 +1,95 @@ +// Copyright (c) Zefchain Labs, Inc. +// SPDX-License-Identifier: Apache-2.0 + +//! Integration tests for the Matching Engine application + +#![cfg(not(target_arch = "wasm32"))] + +use graph_ql_queries::{GraphQlQueriesAbi, GraphQlQueriesOperation}; +use linera_sdk::test::{QueryOutcome, TestValidator}; + +#[tokio::test] +async fn test_queries() { + let (validator, module_id) = + TestValidator::with_current_module::().await; + + let mut chain = validator.new_chain().await; + + let application_id = chain.create_application(module_id, (), (), vec![]).await; + + let operation1 = GraphQlQueriesOperation::SetRegister { value: 124 }; + let operation2 = GraphQlQueriesOperation::InsertMapString { + key: "a".into(), + value: 91, + }; + let operation3 = GraphQlQueriesOperation::InsertCollString { + key: "a".into(), + value: 91, + }; + let operation4 = GraphQlQueriesOperation::InsertCollMap { + key1: "A".into(), + key2: "X".into(), + value: 49, + }; + + chain + .add_block(|block| { + block + .with_operation(application_id, operation1) + .with_operation(application_id, operation2) + .with_operation(application_id, operation3) + .with_operation(application_id, operation4); + }) + .await; + + // READ1 + + for (query, expected_response) in [ + ("reg", "{\"reg\":124}"), + ("mapS { keys }", "{\"mapS\":{\"keys\":[\"a\"]}}"), + ("mapS { entry(key: \"a\") { key, value } }", "{\"mapS\":{\"entry\":{\"key\":\"a\",\"value\":91}}}"), + ("mapS { entries { key, value } }", "{\"mapS\":{\"entries\":[{\"key\":\"a\",\"value\":91}]}}"), + ("mapS { entries(input: {}) { key, value } }", "{\"mapS\":{\"entries\":[{\"key\":\"a\",\"value\":91}]}}"), + ("mapS { entries(input: { filters: {} }) { key, value } }", "{\"mapS\":{\"entries\":[{\"key\":\"a\",\"value\":91}]}}"), + ("mapS { entries(input: { filters: { keys: [\"a\"]} }) { key, value } }", "{\"mapS\":{\"entries\":[{\"key\":\"a\",\"value\":91}]}}"), + ("mapS { entries(input: { filters: { keys: [\"b\"]} }) { key, value } }", "{\"mapS\":{\"entries\":[{\"key\":\"b\",\"value\":null}]}}"), + ("mapS { count }", "{\"mapS\":{\"count\":1}}"), + ("collS { keys }", "{\"collS\":{\"keys\":[\"a\"]}}"), + ("collS { entry(key: \"a\") { key, value } }", "{\"collS\":{\"entry\":{\"key\":\"a\",\"value\":91}}}"), + ("collS { entries { key, value } }", "{\"collS\":{\"entries\":[{\"key\":\"a\",\"value\":91}]}}"), + ("collS { entries(input: {}) { key, value } }", "{\"collS\":{\"entries\":[{\"key\":\"a\",\"value\":91}]}}"), + ("collS { entries(input: { filters: {} }) { key, value } }", "{\"collS\":{\"entries\":[{\"key\":\"a\",\"value\":91}]}}"), + ("collS { entries(input: { filters: { keys: [\"a\"]} }) { key, value } }", "{\"collS\":{\"entries\":[{\"key\":\"a\",\"value\":91}]}}"), + ("collS { entries(input: { filters: { keys: [\"b\"]} }) { key, value } }", "{\"collS\":{\"entries\":[{\"key\":\"b\",\"value\":null}]}}"), + ("collS { count }", "{\"collS\":{\"count\":1}}"), + ("collMap { keys }", "{\"collMap\":{\"keys\":[\"A\"]}}"), + ("collMap { entries { key, value { count } } }", "{\"collMap\":{\"entries\":[{\"key\":\"A\",\"value\":{\"count\":1}}]}}"), + ("collMap { count }", "{\"collMap\":{\"count\":1}}"), + ("collMap { entry(key: \"A\") { key, value { count } } }", "{\"collMap\":{\"entry\":{\"key\":\"A\",\"value\":{\"count\":1}}}}"), + ("collMap { entry(key: \"B\") { key, value { count } } }", "{\"collMap\":{\"entry\":{\"key\":\"B\",\"value\":null}}}"), + ("collMap { entry(key: \"A\") { key, value { entries(input: {}) { key, value } } } }", + "{\"collMap\":{\"entry\":{\"key\":\"A\",\"value\":{\"entries\":[{\"key\":\"X\",\"value\":49}]}}}}"), + ("collMap { entries(input: {}) { key, value { count } } }", + "{\"collMap\":{\"entries\":[{\"key\":\"A\",\"value\":{\"count\":1}}]}}"), + ("collMap { entries(input: {}) { key, value { entries(input: {}) { key, value } } } }", + "{\"collMap\":{\"entries\":[{\"key\":\"A\",\"value\":{\"entries\":[{\"key\":\"X\",\"value\":49}]}}]}}"), + ("collMap { entries { key, value { keys } } }", + "{\"collMap\":{\"entries\":[{\"key\":\"A\",\"value\":{\"keys\":[\"X\"]}}]}}"), + ("collMap { entries(input: {}) { key, value { keys } } }", + "{\"collMap\":{\"entries\":[{\"key\":\"A\",\"value\":{\"keys\":[\"X\"]}}]}}"), + ("collMap { entries(input: { filters: {} }) { key, value { keys } } }", + "{\"collMap\":{\"entries\":[{\"key\":\"A\",\"value\":{\"keys\":[\"X\"]}}]}}"), + ("collMap { entries(input: { filters: { keys: [\"A\"] } }) { key, value { keys } } }", + "{\"collMap\":{\"entries\":[{\"key\":\"A\",\"value\":{\"keys\":[\"X\"]}}]}}"), + ("collMap { entries(input: { filters: { keys: [\"B\"] } }) { key, value { keys } } }", + "{\"collMap\":{\"entries\":[{\"key\":\"B\",\"value\":null}]}}"), + ] { + println!("query={}", query); + let new_query = format!("query {{ {} }}", query); + let QueryOutcome { response, .. } = chain.graphql_query(application_id, new_query).await; + println!("expected_response={expected_response}"); + println!("response={response}"); + assert_eq!(format!("{response}"), expected_response); + println!(); + } +} diff --git a/linera-service-graphql-client/gql/service_schema.graphql b/linera-service-graphql-client/gql/service_schema.graphql index a6f6ba95af0..ec003098736 100644 --- a/linera-service-graphql-client/gql/service_schema.graphql +++ b/linera-service-graphql-client/gql/service_schema.graphql @@ -479,7 +479,7 @@ type Cursor { """ A GraphQL-visible map item, complete with key. """ -type Entry_AccountOwner_Amount_aaf96548 { +type Entry_AccountOwner_Amount_11ef1379 { key: AccountOwner! value: Amount } @@ -489,13 +489,13 @@ A GraphQL-visible map item, complete with key. """ type Entry_AccountOwner_PendingBlobsView_5d91edcf { key: AccountOwner! - value: PendingBlobsView! + value: PendingBlobsView } """ A GraphQL-visible map item, complete with key. """ -type Entry_BlobId_Blob_50b95aa1 { +type Entry_BlobId_Blob_3711e760 { key: BlobId! value: Blob } @@ -511,7 +511,7 @@ type Entry_BlobId_Blob_9f0b41f3 { """ A GraphQL-visible map item, complete with key. """ -type Entry_BlockHeight_CryptoHash_74e16b71 { +type Entry_BlockHeight_CryptoHash_1bae6d76 { key: BlockHeight! value: CryptoHash } @@ -519,7 +519,7 @@ type Entry_BlockHeight_CryptoHash_74e16b71 { """ A GraphQL-visible map item, complete with key. """ -type Entry_ChainId_BlockHeight_2fe78645 { +type Entry_ChainId_BlockHeight_f2e56e12 { key: ChainId! value: BlockHeight } @@ -529,7 +529,7 @@ A GraphQL-visible map item, complete with key. """ type Entry_ChainId_InboxStateView_a9e4d828 { key: ChainId! - value: InboxStateView! + value: InboxStateView } """ @@ -537,13 +537,13 @@ A GraphQL-visible map item, complete with key. """ type Entry_ChainId_OutboxStateView_855dcf53 { key: ChainId! - value: OutboxStateView! + value: OutboxStateView } """ A GraphQL-visible map item, complete with key. """ -type Entry_StreamId_BlockHeight_50cd702e { +type Entry_StreamId_BlockHeight_e6657ad9 { key: StreamId! value: BlockHeight } @@ -551,7 +551,7 @@ type Entry_StreamId_BlockHeight_50cd702e { """ A GraphQL-visible map item, complete with key. """ -type Entry_StreamId_Int_459c4ec3 { +type Entry_StreamId_Int_3d7f5335 { key: StreamId! value: Int } @@ -712,50 +712,50 @@ input MapInput_StreamIdInput_b7c3909d { type MapView_AccountOwner_Amount_11ef1379 { keys(count: Int): [AccountOwner!]! count: Int! - entry(key: AccountOwner!): Entry_AccountOwner_Amount_aaf96548! - entries(input: MapInput_AccountOwner_d6668c53): [Entry_AccountOwner_Amount_aaf96548!]! + entry(key: AccountOwner!): Entry_AccountOwner_Amount_11ef1379! + entries(input: MapInput_AccountOwner_d6668c53): [Entry_AccountOwner_Amount_11ef1379!]! } type MapView_BlobId_Blob_3711e760 { keys(count: Int): [BlobId!]! count: Int! - entry(key: BlobId!): Entry_BlobId_Blob_9f0b41f3! - entries(input: MapInput_BlobId_4d2a0555): [Entry_BlobId_Blob_9f0b41f3!]! + entry(key: BlobId!): Entry_BlobId_Blob_3711e760! + entries(input: MapInput_BlobId_4d2a0555): [Entry_BlobId_Blob_3711e760!]! } type MapView_BlobId_Blob_9f0b41f3 { keys(count: Int): [BlobId!]! count: Int! - entry(key: BlobId!): Entry_BlobId_Blob_50b95aa1! - entries(input: MapInput_BlobId_4d2a0555): [Entry_BlobId_Blob_50b95aa1!]! + entry(key: BlobId!): Entry_BlobId_Blob_9f0b41f3! + entries(input: MapInput_BlobId_4d2a0555): [Entry_BlobId_Blob_9f0b41f3!]! } type MapView_BlockHeight_CryptoHash_1bae6d76 { keys(count: Int): [BlockHeight!]! count: Int! - entry(key: BlockHeight!): Entry_BlockHeight_CryptoHash_74e16b71! - entries(input: MapInput_BlockHeight_e824a938): [Entry_BlockHeight_CryptoHash_74e16b71!]! + entry(key: BlockHeight!): Entry_BlockHeight_CryptoHash_1bae6d76! + entries(input: MapInput_BlockHeight_e824a938): [Entry_BlockHeight_CryptoHash_1bae6d76!]! } type MapView_ChainId_BlockHeight_f2e56e12 { keys(count: Int): [ChainId!]! count: Int! - entry(key: ChainId!): Entry_ChainId_BlockHeight_2fe78645! - entries(input: MapInput_ChainId_37f83aa9): [Entry_ChainId_BlockHeight_2fe78645!]! + entry(key: ChainId!): Entry_ChainId_BlockHeight_f2e56e12! + entries(input: MapInput_ChainId_37f83aa9): [Entry_ChainId_BlockHeight_f2e56e12!]! } type MapView_StreamId_BlockHeight_e6657ad9 { keys(count: Int): [StreamId!]! count: Int! - entry(key: StreamIdInput!): Entry_StreamId_BlockHeight_50cd702e! - entries(input: MapInput_StreamIdInput_b7c3909d): [Entry_StreamId_BlockHeight_50cd702e!]! + entry(key: StreamIdInput!): Entry_StreamId_BlockHeight_e6657ad9! + entries(input: MapInput_StreamIdInput_b7c3909d): [Entry_StreamId_BlockHeight_e6657ad9!]! } type MapView_StreamId_Int_3d7f5335 { keys(count: Int): [StreamId!]! count: Int! - entry(key: StreamIdInput!): Entry_StreamId_Int_459c4ec3! - entries(input: MapInput_StreamIdInput_b7c3909d): [Entry_StreamId_Int_459c4ec3!]! + entry(key: StreamIdInput!): Entry_StreamId_Int_3d7f5335! + entries(input: MapInput_StreamIdInput_b7c3909d): [Entry_StreamId_Int_3d7f5335!]! } """ diff --git a/linera-views/src/graphql.rs b/linera-views/src/graphql.rs index 038bc3b8156..2f0ea3a1513 100644 --- a/linera-views/src/graphql.rs +++ b/linera-views/src/graphql.rs @@ -36,7 +36,7 @@ pub struct Entry< V: async_graphql::OutputType + Send + Sync, > { pub key: K, - pub value: V, + pub value: Option, } impl async_graphql::TypeName @@ -218,11 +218,3 @@ impl async_graphql::InputType for MapInput { Some(self) } } - -pub(crate) fn missing_key_error(key: &impl std::fmt::Debug) -> async_graphql::Error { - async_graphql::Error { - message: format!("The key={:?} is missing in collection", key), - source: None, - extensions: None, - } -} diff --git a/linera-views/src/views/collection_view.rs b/linera-views/src/views/collection_view.rs index 6f45be99ff8..3d740168c16 100644 --- a/linera-views/src/views/collection_view.rs +++ b/linera-views/src/views/collection_view.rs @@ -1570,7 +1570,7 @@ mod graphql { use super::{CollectionView, CustomCollectionView, ReadGuardedView}; use crate::{ - graphql::{hash_name, mangle, missing_key_error, Entry, MapInput}, + graphql::{hash_name, mangle, Entry, MapInput}, views::View, }; @@ -1629,10 +1629,7 @@ mod graphql { &self, key: K, ) -> Result>, async_graphql::Error> { - let value = self - .try_load_entry(&key) - .await? - .ok_or_else(|| missing_key_error(&key))?; + let value = self.try_load_entry(&key).await?; Ok(Entry { value, key }) } @@ -1653,7 +1650,7 @@ mod graphql { Ok(values .into_iter() .zip(keys) - .filter_map(|(value, key)| value.map(|value| Entry { value, key })) + .map(|(value, key)| Entry { value, key }) .collect()) } } @@ -1694,10 +1691,7 @@ mod graphql { &self, key: K, ) -> Result>, async_graphql::Error> { - let value = self - .try_load_entry(&key) - .await? - .ok_or_else(|| missing_key_error(&key))?; + let value = self.try_load_entry(&key).await?; Ok(Entry { value, key }) } @@ -1718,7 +1712,7 @@ mod graphql { Ok(values .into_iter() .zip(keys) - .filter_map(|(value, key)| value.map(|value| Entry { value, key })) + .map(|(value, key)| Entry { value, key }) .collect()) } } diff --git a/linera-views/src/views/map_view.rs b/linera-views/src/views/map_view.rs index e23c66817e1..0472fe32a54 100644 --- a/linera-views/src/views/map_view.rs +++ b/linera-views/src/views/map_view.rs @@ -2075,10 +2075,7 @@ mod graphql { }) } - async fn entry( - &self, - key: Vec, - ) -> Result, Option>, async_graphql::Error> { + async fn entry(&self, key: Vec) -> Result, V>, async_graphql::Error> { Ok(Entry { value: self.get(&key).await?, key, @@ -2088,7 +2085,7 @@ mod graphql { async fn entries( &self, input: Option>>, - ) -> Result, Option>>, async_graphql::Error> { + ) -> Result, V>>, async_graphql::Error> { let keys = input .and_then(|input| input.filters) .and_then(|filters| filters.keys); @@ -2160,7 +2157,7 @@ mod graphql { Ok(self.count().await? as u32) } - async fn entry(&self, key: I) -> Result>, async_graphql::Error> { + async fn entry(&self, key: I) -> Result, async_graphql::Error> { Ok(Entry { value: self.get(&key).await?, key, @@ -2170,7 +2167,7 @@ mod graphql { async fn entries( &self, input: Option>, - ) -> Result>>, async_graphql::Error> { + ) -> Result>, async_graphql::Error> { let keys = input .and_then(|input| input.filters) .and_then(|filters| filters.keys); @@ -2233,7 +2230,7 @@ mod graphql { }) } - async fn entry(&self, key: I) -> Result>, async_graphql::Error> { + async fn entry(&self, key: I) -> Result, async_graphql::Error> { Ok(Entry { value: self.get(&key).await?, key, @@ -2243,7 +2240,7 @@ mod graphql { async fn entries( &self, input: Option>, - ) -> Result>>, async_graphql::Error> { + ) -> Result>, async_graphql::Error> { let keys = input .and_then(|input| input.filters) .and_then(|filters| filters.keys); diff --git a/linera-views/src/views/reentrant_collection_view.rs b/linera-views/src/views/reentrant_collection_view.rs index c40e4922bf6..abd199b4a19 100644 --- a/linera-views/src/views/reentrant_collection_view.rs +++ b/linera-views/src/views/reentrant_collection_view.rs @@ -2073,7 +2073,7 @@ mod graphql { use super::{ReadGuardedView, ReentrantCollectionView}; use crate::{ - graphql::{hash_name, mangle, missing_key_error, Entry, MapInput}, + graphql::{hash_name, mangle, Entry, MapInput}, views::View, }; @@ -2132,10 +2132,7 @@ mod graphql { &self, key: K, ) -> Result>, async_graphql::Error> { - let value = self - .try_load_entry(&key) - .await? - .ok_or_else(|| missing_key_error(&key))?; + let value = self.try_load_entry(&key).await?; Ok(Entry { value, key }) } @@ -2156,7 +2153,7 @@ mod graphql { Ok(values .into_iter() .zip(keys) - .filter_map(|(value, key)| value.map(|value| Entry { value, key })) + .map(|(value, key)| Entry { value, key }) .collect()) } } @@ -2193,10 +2190,7 @@ mod graphql { &self, key: K, ) -> Result>, async_graphql::Error> { - let value = self - .try_load_entry(&key) - .await? - .ok_or_else(|| missing_key_error(&key))?; + let value = self.try_load_entry(&key).await?; Ok(Entry { value, key }) } @@ -2217,7 +2211,7 @@ mod graphql { Ok(values .into_iter() .zip(keys) - .filter_map(|(value, key)| value.map(|value| Entry { value, key })) + .map(|(value, key)| Entry { value, key }) .collect()) } }