From ebb702b740d9a49b9d5c1ce78fa735d48576fdcb Mon Sep 17 00:00:00 2001 From: Alberto Schiabel Date: Mon, 20 Nov 2023 04:20:52 +0100 Subject: [PATCH] feat(driver-adapters): enable Wasm on `query-core` (#4445) * feat(quaint): allow wasm32-unknown-unknown compilation; currently fails on native * feat(quaint): split postgres connector into native and wasm submodules * feat(quaint): split mysql connector into native and wasm submodules * feat(quaint): recover wasm error for mysql * feat(quaint): split mssql connector into native and wasm submodules * feat(quaint): split sqlite connector into native and wasm submodules * chore(quaint): fix clippy when compiling natively * chore(quaint): fix clippy when compiling to wasm32-unknown-unknown * chore(quaint): update README * chore(quaint): rename "*-connector" feature flag to "*-native" * feat(quaint): enable pure Wasm SqliteError * feat(query-connect): allow wasm32-unknown-unknown compilation * feat(sql-query-connector): allow wasm32-unknown-unknown compilation * chore(query-engine-wasm): add currently unused local crates to test wasm32-unknown-unknown compilation * chore: update Cargo.lock * chore: remove leftover comments * feat(query-core): allow wasm32-unknown-unknown compilation * chore(sql-query-connector): fix clipppy on wasm32 * chore: remove leftover comment * WIP: refactor mysql module to flatten its structure * feat(quaint): flatten mssql connector module * feat(quaint): flatten postgres connector module * feat(quaint): flatten sqlite connector module * chore(quaint): export all public definitions in connector "url" modules * chore(quaint): refactor tests for connectors, addressing feedback * chore: add comment on MysqlAsyncError * chore: add comment on ffi.rs for sqlite * chore: replace awkward "super::super::" with "crate::..." * chore: add comments around "query_core::executor::task" * chore: move "task" module into its own file * fix(driver-adapters): ci for "request-handlers" --------- Co-authored-by: Miguel Fernandez --- Cargo.lock | 3 + .../query-tests-setup/Cargo.toml | 2 +- query-engine/core-tests/Cargo.toml | 2 +- query-engine/core/Cargo.toml | 13 +- .../core/src/executor/execute_operation.rs | 11 ++ query-engine/core/src/executor/mod.rs | 1 + query-engine/core/src/executor/task.rs | 59 ++++++++ .../interactive_transactions/actor_manager.rs | 2 +- .../src/interactive_transactions/actors.rs | 15 +- query-engine/core/src/lib.rs | 7 +- query-engine/query-engine-node-api/Cargo.toml | 2 +- query-engine/query-engine-wasm/Cargo.toml | 1 + query-engine/query-engine-wasm/pnpm-lock.yaml | 130 ++++++++++++++++++ query-engine/query-engine/Cargo.toml | 2 +- query-engine/request-handlers/Cargo.toml | 2 +- 15 files changed, 238 insertions(+), 14 deletions(-) create mode 100644 query-engine/core/src/executor/task.rs create mode 100644 query-engine/query-engine-wasm/pnpm-lock.yaml diff --git a/Cargo.lock b/Cargo.lock index 646e5f46d709..d788c5f344c6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3680,6 +3680,7 @@ dependencies = [ "once_cell", "opentelemetry", "petgraph 0.4.13", + "pin-project", "prisma-models", "psl", "query-connector", @@ -3695,6 +3696,7 @@ dependencies = [ "tracing-subscriber", "user-facing-errors", "uuid", + "wasm-bindgen-futures", ] [[package]] @@ -3824,6 +3826,7 @@ dependencies = [ "psl", "quaint", "query-connector", + "query-core", "serde", "serde-wasm-bindgen", "serde_json", diff --git a/query-engine/connector-test-kit-rs/query-tests-setup/Cargo.toml b/query-engine/connector-test-kit-rs/query-tests-setup/Cargo.toml index 088a0d4b2d34..f257d9e52162 100644 --- a/query-engine/connector-test-kit-rs/query-tests-setup/Cargo.toml +++ b/query-engine/connector-test-kit-rs/query-tests-setup/Cargo.toml @@ -10,7 +10,7 @@ once_cell = "1" qe-setup = { path = "../qe-setup" } request-handlers = { path = "../../request-handlers" } tokio.workspace = true -query-core = { path = "../../core" } +query-core = { path = "../../core", features = ["metrics"] } sql-query-connector = { path = "../../connectors/sql-query-connector" } query-engine = { path = "../../query-engine"} psl.workspace = true diff --git a/query-engine/core-tests/Cargo.toml b/query-engine/core-tests/Cargo.toml index 9a2c3f5686eb..bac9219c3522 100644 --- a/query-engine/core-tests/Cargo.toml +++ b/query-engine/core-tests/Cargo.toml @@ -9,7 +9,7 @@ edition = "2021" dissimilar = "1.0.4" user-facing-errors = { path = "../../libs/user-facing-errors" } request-handlers = { path = "../request-handlers" } -query-core = { path = "../core" } +query-core = { path = "../core", features = ["metrics"] } schema = { path = "../schema" } psl.workspace = true serde_json.workspace = true diff --git a/query-engine/core/Cargo.toml b/query-engine/core/Cargo.toml index caadf6cdba00..9e0f03517cb5 100644 --- a/query-engine/core/Cargo.toml +++ b/query-engine/core/Cargo.toml @@ -3,6 +3,9 @@ edition = "2021" name = "query-core" version = "0.1.0" +[features] +metrics = ["query-engine-metrics"] + [dependencies] async-trait = "0.1" bigdecimal = "0.3" @@ -18,11 +21,11 @@ once_cell = "1" petgraph = "0.4" prisma-models = { path = "../prisma-models", features = ["default_generators"] } opentelemetry = { version = "0.17.0", features = ["rt-tokio", "serialize"] } -query-engine-metrics = {path = "../metrics"} +query-engine-metrics = { path = "../metrics", optional = true } serde.workspace = true serde_json.workspace = true thiserror = "1.0" -tokio.workspace = true +tokio = { version = "1.0", features = ["macros", "time"] } tracing = { version = "0.1", features = ["attributes"] } tracing-futures = "0.2" tracing-subscriber = { version = "0.3", features = ["env-filter"] } @@ -34,3 +37,9 @@ schema = { path = "../schema" } lru = "0.7.7" enumflags2 = "0.7" +pin-project = "1" +wasm-bindgen-futures = "0.4" + +[target.'cfg(target_arch = "wasm32")'.dependencies] +pin-project = "1" +wasm-bindgen-futures = "0.4" diff --git a/query-engine/core/src/executor/execute_operation.rs b/query-engine/core/src/executor/execute_operation.rs index 06452fcdd865..6ba21d37f9ff 100644 --- a/query-engine/core/src/executor/execute_operation.rs +++ b/query-engine/core/src/executor/execute_operation.rs @@ -1,3 +1,5 @@ +#![cfg_attr(target_arch = "wasm32", allow(unused_variables))] + use super::pipeline::QueryPipeline; use crate::{ executor::request_context, protocol::EngineProtocol, CoreError, IrSerializer, Operation, QueryGraph, @@ -5,9 +7,12 @@ use crate::{ }; use connector::{Connection, ConnectionLike, Connector}; use futures::future; + +#[cfg(feature = "metrics")] use query_engine_metrics::{ histogram, increment_counter, metrics, PRISMA_CLIENT_QUERIES_DURATION_HISTOGRAM_MS, PRISMA_CLIENT_QUERIES_TOTAL, }; + use schema::{QuerySchema, QuerySchemaRef}; use std::time::{Duration, Instant}; use tracing::Instrument; @@ -24,6 +29,7 @@ pub async fn execute_single_operation( let (graph, serializer) = build_graph(&query_schema, operation.clone())?; let result = execute_on(conn, graph, serializer, query_schema.as_ref(), trace_id).await; + #[cfg(feature = "metrics")] histogram!(PRISMA_CLIENT_QUERIES_DURATION_HISTOGRAM_MS, operation_timer.elapsed()); result @@ -45,6 +51,8 @@ pub async fn execute_many_operations( for (i, (graph, serializer)) in queries.into_iter().enumerate() { let operation_timer = Instant::now(); let result = execute_on(conn, graph, serializer, query_schema.as_ref(), trace_id.clone()).await; + + #[cfg(feature = "metrics")] histogram!(PRISMA_CLIENT_QUERIES_DURATION_HISTOGRAM_MS, operation_timer.elapsed()); match result { @@ -98,6 +106,7 @@ pub async fn execute_many_self_contained( let dispatcher = crate::get_current_dispatcher(); for op in operations { + #[cfg(feature = "metrics")] increment_counter!(PRISMA_CLIENT_QUERIES_TOTAL); let conn_span = info_span!( @@ -158,6 +167,7 @@ async fn execute_self_contained( execute_self_contained_without_retry(conn, graph, serializer, force_transactions, &query_schema, trace_id).await }; + #[cfg(feature = "metrics")] histogram!(PRISMA_CLIENT_QUERIES_DURATION_HISTOGRAM_MS, operation_timer.elapsed()); result @@ -259,6 +269,7 @@ async fn execute_on<'a>( query_schema: &'a QuerySchema, trace_id: Option, ) -> crate::Result { + #[cfg(feature = "metrics")] increment_counter!(PRISMA_CLIENT_QUERIES_TOTAL); let interpreter = QueryInterpreter::new(conn); diff --git a/query-engine/core/src/executor/mod.rs b/query-engine/core/src/executor/mod.rs index ddbb7dfc8429..ba2784d3c71a 100644 --- a/query-engine/core/src/executor/mod.rs +++ b/query-engine/core/src/executor/mod.rs @@ -10,6 +10,7 @@ mod execute_operation; mod interpreting_executor; mod pipeline; mod request_context; +pub(crate) mod task; pub use self::{execute_operation::*, interpreting_executor::InterpretingExecutor}; diff --git a/query-engine/core/src/executor/task.rs b/query-engine/core/src/executor/task.rs new file mode 100644 index 000000000000..8d1c39bbcd06 --- /dev/null +++ b/query-engine/core/src/executor/task.rs @@ -0,0 +1,59 @@ +//! This module provides a unified interface for spawning asynchronous tasks, regardless of the target platform. + +pub use arch::{spawn, JoinHandle}; +use futures::Future; + +// On native targets, `tokio::spawn` spawns a new asynchronous task. +#[cfg(not(target_arch = "wasm32"))] +mod arch { + use super::*; + + pub type JoinHandle = tokio::task::JoinHandle; + + pub fn spawn(future: T) -> JoinHandle + where + T: Future + Send + 'static, + T::Output: Send + 'static, + { + tokio::spawn(future) + } +} + +// On Wasm targets, `wasm_bindgen_futures::spawn_local` spawns a new asynchronous task. +#[cfg(target_arch = "wasm32")] +mod arch { + use super::*; + use tokio::sync::oneshot::{self}; + + // Wasm-compatible alternative to `tokio::task::JoinHandle`. + // `pin_project` enables pin-projection and a `Pin`-compatible implementation of the `Future` trait. + pub struct JoinHandle(oneshot::Receiver); + + impl Future for JoinHandle { + type Output = Result; + + fn poll(mut self: std::pin::Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> std::task::Poll { + // the `self.project()` method is provided by the `pin_project` macro + core::pin::Pin::new(&mut self.0).poll(cx) + } + } + + impl JoinHandle { + pub fn abort(&mut self) { + // abort is noop on Wasm targets + } + } + + pub fn spawn(future: T) -> JoinHandle + where + T: Future + Send + 'static, + T::Output: Send + 'static, + { + let (sender, receiver) = oneshot::channel(); + wasm_bindgen_futures::spawn_local(async move { + let result = future.await; + sender.send(result).ok(); + }); + JoinHandle(receiver) + } +} diff --git a/query-engine/core/src/interactive_transactions/actor_manager.rs b/query-engine/core/src/interactive_transactions/actor_manager.rs index 98208343d28a..105733be4166 100644 --- a/query-engine/core/src/interactive_transactions/actor_manager.rs +++ b/query-engine/core/src/interactive_transactions/actor_manager.rs @@ -1,3 +1,4 @@ +use crate::executor::task::JoinHandle; use crate::{protocol::EngineProtocol, ClosedTx, Operation, ResponseData}; use connector::Connection; use lru::LruCache; @@ -9,7 +10,6 @@ use tokio::{ mpsc::{channel, Sender}, RwLock, }, - task::JoinHandle, time::Duration, }; diff --git a/query-engine/core/src/interactive_transactions/actors.rs b/query-engine/core/src/interactive_transactions/actors.rs index 88402d86fedd..104ffc26812f 100644 --- a/query-engine/core/src/interactive_transactions/actors.rs +++ b/query-engine/core/src/interactive_transactions/actors.rs @@ -1,7 +1,8 @@ use super::{CachedTx, TransactionError, TxOpRequest, TxOpRequestMsg, TxOpResponse}; +use crate::executor::task::{spawn, JoinHandle}; use crate::{ - execute_many_operations, execute_single_operation, protocol::EngineProtocol, - telemetry::helpers::set_span_link_from_traceparent, ClosedTx, Operation, ResponseData, TxId, + execute_many_operations, execute_single_operation, protocol::EngineProtocol, ClosedTx, Operation, ResponseData, + TxId, }; use connector::Connection; use schema::QuerySchemaRef; @@ -11,13 +12,15 @@ use tokio::{ mpsc::{channel, Receiver, Sender}, oneshot, RwLock, }, - task::JoinHandle, time::{self, Duration, Instant}, }; use tracing::Span; use tracing_futures::Instrument; use tracing_futures::WithSubscriber; +#[cfg(feature = "metrics")] +use crate::telemetry::helpers::set_span_link_from_traceparent; + #[derive(PartialEq)] enum RunState { Continue, @@ -81,6 +84,8 @@ impl<'a> ITXServer<'a> { traceparent: Option, ) -> crate::Result { let span = info_span!("prisma:engine:itx_query_builder", user_facing = true); + + #[cfg(feature = "metrics")] set_span_link_from_traceparent(&span, traceparent.clone()); let conn = self.cached_tx.as_open()?; @@ -267,7 +272,7 @@ pub(crate) async fn spawn_itx_actor( }; let (open_transaction_send, open_transaction_rcv) = oneshot::channel(); - tokio::task::spawn( + spawn( crate::executor::with_request_context(engine_protocol, async move { // We match on the result in order to send the error to the parent task and abort this // task, on error. This is a separate task (actor), not a function where we can just bubble up the @@ -380,7 +385,7 @@ pub(crate) fn spawn_client_list_clear_actor( closed_txs: Arc>>>, mut rx: Receiver<(TxId, Option)>, ) -> JoinHandle<()> { - tokio::task::spawn(async move { + spawn(async move { loop { if let Some((id, closed_tx)) = rx.recv().await { trace!("removing {} from client list", id); diff --git a/query-engine/core/src/lib.rs b/query-engine/core/src/lib.rs index 7970c96139b7..38f39e9fb5d9 100644 --- a/query-engine/core/src/lib.rs +++ b/query-engine/core/src/lib.rs @@ -9,6 +9,8 @@ pub mod protocol; pub mod query_document; pub mod query_graph_builder; pub mod response_ir; + +#[cfg(feature = "metrics")] pub mod telemetry; pub use self::{ @@ -16,8 +18,11 @@ pub use self::{ executor::{QueryExecutor, TransactionOptions}, interactive_transactions::{ExtendedTransactionUserFacingError, TransactionError, TxId}, query_document::*, - telemetry::*, }; + +#[cfg(feature = "metrics")] +pub use self::telemetry::*; + pub use connector::{ error::{ConnectorError, ErrorKind as ConnectorErrorKind}, Connector, diff --git a/query-engine/query-engine-node-api/Cargo.toml b/query-engine/query-engine-node-api/Cargo.toml index 74f9686189fc..0eaed9eff7ce 100644 --- a/query-engine/query-engine-node-api/Cargo.toml +++ b/query-engine/query-engine-node-api/Cargo.toml @@ -16,7 +16,7 @@ driver-adapters = ["request-handlers/driver-adapters", "sql-connector/driver-ada [dependencies] anyhow = "1" async-trait = "0.1" -query-core = { path = "../core" } +query-core = { path = "../core", features = ["metrics"] } request-handlers = { path = "../request-handlers" } query-connector = { path = "../connectors/query-connector" } user-facing-errors = { path = "../../libs/user-facing-errors" } diff --git a/query-engine/query-engine-wasm/Cargo.toml b/query-engine/query-engine-wasm/Cargo.toml index 34ef69df467d..b8c12dc91f5c 100644 --- a/query-engine/query-engine-wasm/Cargo.toml +++ b/query-engine/query-engine-wasm/Cargo.toml @@ -17,6 +17,7 @@ prisma-models = { path = "../prisma-models" } quaint = { path = "../../quaint" } connector = { path = "../connectors/query-connector", package = "query-connector" } sql-query-connector = { path = "../connectors/sql-query-connector" } +query-core = { path = "../core" } thiserror = "1" connection-string.workspace = true diff --git a/query-engine/query-engine-wasm/pnpm-lock.yaml b/query-engine/query-engine-wasm/pnpm-lock.yaml new file mode 100644 index 000000000000..89591aef9869 --- /dev/null +++ b/query-engine/query-engine-wasm/pnpm-lock.yaml @@ -0,0 +1,130 @@ +lockfileVersion: '6.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +dependencies: + '@neondatabase/serverless': + specifier: 0.6.0 + version: 0.6.0 + '@prisma/adapter-neon': + specifier: 5.6.0 + version: 5.6.0(@neondatabase/serverless@0.6.0) + '@prisma/driver-adapter-utils': + specifier: 5.6.0 + version: 5.6.0 + +packages: + + /@neondatabase/serverless@0.6.0: + resolution: {integrity: sha512-qXxBRYN0m2v8kVQBfMxbzNGn2xFAhTXFibzQlE++NfJ56Shz3m7+MyBBtXDlEH+3Wfa6lToDXf1MElocY4sJ3w==} + dependencies: + '@types/pg': 8.6.6 + dev: false + + /@prisma/adapter-neon@5.6.0(@neondatabase/serverless@0.6.0): + resolution: {integrity: sha512-IUkIE5NKyP2wCXMMAByM78fizfaJl7YeWDEajvyqQafXgRwmxl+2HhxsevvHly8jT4RlELdhjK6IP1eciGvXVA==} + peerDependencies: + '@neondatabase/serverless': ^0.6.0 + dependencies: + '@neondatabase/serverless': 0.6.0 + '@prisma/driver-adapter-utils': 5.6.0 + postgres-array: 3.0.2 + transitivePeerDependencies: + - supports-color + dev: false + + /@prisma/driver-adapter-utils@5.6.0: + resolution: {integrity: sha512-/TSrfCGLAQghNf+bwg5/e8iKAgecCYU/gMN0IyNra3183/VTQJneLFgbacuSK9bBXiIRUmpbuUIrJ6dhENzfjA==} + dependencies: + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: false + + /@types/node@20.9.1: + resolution: {integrity: sha512-HhmzZh5LSJNS5O8jQKpJ/3ZcrrlG6L70hpGqMIAoM9YVD0YBRNWYsfwcXq8VnSjlNpCpgLzMXdiPo+dxcvSmiA==} + dependencies: + undici-types: 5.26.5 + dev: false + + /@types/pg@8.6.6: + resolution: {integrity: sha512-O2xNmXebtwVekJDD+02udOncjVcMZQuTEQEMpKJ0ZRf5E7/9JJX3izhKUcUifBkyKpljyUM6BTgy2trmviKlpw==} + dependencies: + '@types/node': 20.9.1 + pg-protocol: 1.6.0 + pg-types: 2.2.0 + dev: false + + /debug@4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + dev: false + + /ms@2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + dev: false + + /pg-int8@1.0.1: + resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==} + engines: {node: '>=4.0.0'} + dev: false + + /pg-protocol@1.6.0: + resolution: {integrity: sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==} + dev: false + + /pg-types@2.2.0: + resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==} + engines: {node: '>=4'} + dependencies: + pg-int8: 1.0.1 + postgres-array: 2.0.0 + postgres-bytea: 1.0.0 + postgres-date: 1.0.7 + postgres-interval: 1.2.0 + dev: false + + /postgres-array@2.0.0: + resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==} + engines: {node: '>=4'} + dev: false + + /postgres-array@3.0.2: + resolution: {integrity: sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog==} + engines: {node: '>=12'} + dev: false + + /postgres-bytea@1.0.0: + resolution: {integrity: sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==} + engines: {node: '>=0.10.0'} + dev: false + + /postgres-date@1.0.7: + resolution: {integrity: sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==} + engines: {node: '>=0.10.0'} + dev: false + + /postgres-interval@1.2.0: + resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==} + engines: {node: '>=0.10.0'} + dependencies: + xtend: 4.0.2 + dev: false + + /undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + dev: false + + /xtend@4.0.2: + resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} + engines: {node: '>=0.4'} + dev: false diff --git a/query-engine/query-engine/Cargo.toml b/query-engine/query-engine/Cargo.toml index be36e4f842dc..c70d8590d0ff 100644 --- a/query-engine/query-engine/Cargo.toml +++ b/query-engine/query-engine/Cargo.toml @@ -20,7 +20,7 @@ enumflags2 = { version = "0.7"} psl.workspace = true graphql-parser = { git = "https://github.com/prisma/graphql-parser" } mongodb-connector = { path = "../connectors/mongodb-query-connector", optional = true, package = "mongodb-query-connector" } -query-core = { path = "../core" } +query-core = { path = "../core", features = ["metrics"] } request-handlers = { path = "../request-handlers" } serde.workspace = true serde_json.workspace = true diff --git a/query-engine/request-handlers/Cargo.toml b/query-engine/request-handlers/Cargo.toml index f5fb433b13ba..e6545eda2234 100644 --- a/query-engine/request-handlers/Cargo.toml +++ b/query-engine/request-handlers/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] prisma-models = { path = "../prisma-models" } -query-core = { path = "../core" } +query-core = { path = "../core", features = ["metrics"] } user-facing-errors = { path = "../../libs/user-facing-errors" } psl.workspace = true dmmf_crate = { path = "../dmmf", package = "dmmf" }