diff --git a/Cargo.lock b/Cargo.lock index 35eff530999a..573e31eababd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -326,6 +326,7 @@ dependencies = [ "query-engine-metrics", "query-engine-tests", "query-tests-setup", + "regex", "reqwest", "serde_json", "tokio", @@ -2396,9 +2397,9 @@ dependencies = [ [[package]] name = "mobc" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bdeff49b387edef305eccfe166af3e1483bb57902dbf369dddc42dc824df23b" +checksum = "90eb49dc5d193287ff80e72a86f34cfb27aae562299d22fea215e06ea1059dd3" dependencies = [ "async-trait", "futures-channel", diff --git a/Makefile b/Makefile index e00c122e2713..614f72e5bd23 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ CONFIG_PATH = ./query-engine/connector-test-kit-rs/test-configs CONFIG_FILE = .test_config SCHEMA_EXAMPLES_PATH = ./query-engine/example_schemas DEV_SCHEMA_FILE = dev_datamodel.prisma -DRIVER_ADAPTERS_BRANCH ?= main +DRIVER_ADAPTERS_BRANCH ?= revert-esm LIBRARY_EXT := $(shell \ case "$$(uname -s)" in \ diff --git a/query-engine/black-box-tests/Cargo.toml b/query-engine/black-box-tests/Cargo.toml index 056ee2bcdb43..cc9e99b8ca3c 100644 --- a/query-engine/black-box-tests/Cargo.toml +++ b/query-engine/black-box-tests/Cargo.toml @@ -15,3 +15,4 @@ user-facing-errors.workspace = true insta = "1.7.1" enumflags2 = "0.7" query-engine-metrics = {path = "../metrics"} +regex = "1.9.3" diff --git a/query-engine/black-box-tests/tests/metrics/smoke_tests.rs b/query-engine/black-box-tests/tests/metrics/smoke_tests.rs index 3397de75af99..5ff7ec8ad9ba 100644 --- a/query-engine/black-box-tests/tests/metrics/smoke_tests.rs +++ b/query-engine/black-box-tests/tests/metrics/smoke_tests.rs @@ -4,6 +4,7 @@ use query_engine_tests::*; /// Asserts common basics for composite type writes. #[test_suite(schema(schema))] mod smoke_tests { + use regex::Regex; fn schema() -> String { let schema = indoc! { r#"model Person { @@ -14,6 +15,24 @@ mod smoke_tests { schema.to_owned() } + fn assert_value_in_range(metrics: &str, metric: &str, low: f64, high: f64) { + let regex = Regex::new(format!(r"{metric}\s+([+-]?\d+(\.\d+)?)").as_str()).unwrap(); + match regex.captures(&metrics) { + Some(capture) => { + let value = capture.get(1).unwrap().as_str().parse::().unwrap(); + assert!( + value >= low && value <= high, + "expected {} value of {} to be between {} and {}", + metric, + value, + low, + high + ); + } + None => panic!("Metric {} not found in metrics text", metric), + } + } + #[connector_test] #[rustfmt::skip] async fn expected_metrics_rendered(r: Runner) -> TestResult<()> { @@ -62,6 +81,8 @@ mod smoke_tests { // counters assert_eq!(metrics.matches("# HELP prisma_client_queries_total The total number of Prisma Client queries executed").count(), 1); assert_eq!(metrics.matches("# TYPE prisma_client_queries_total counter").count(), 1); + assert_eq!(metrics.matches("prisma_client_queries_total 1").count(), 1); + assert_eq!(metrics.matches("# HELP prisma_datasource_queries_total The total number of datasource queries executed").count(), 1); assert_eq!(metrics.matches("# TYPE prisma_datasource_queries_total counter").count(), 1); @@ -81,13 +102,15 @@ mod smoke_tests { assert_eq!(metrics.matches("# HELP prisma_pool_connections_busy The number of pool connections currently executing datasource queries").count(), 1); assert_eq!(metrics.matches("# TYPE prisma_pool_connections_busy gauge").count(), 1); + assert_value_in_range(&metrics, "prisma_pool_connections_busy", 0f64, 1f64); assert_eq!(metrics.matches("# HELP prisma_pool_connections_idle The number of pool connections that are not busy running a query").count(), 1); assert_eq!(metrics.matches("# TYPE prisma_pool_connections_idle gauge").count(), 1); assert_eq!(metrics.matches("# HELP prisma_pool_connections_open The number of pool connections currently open").count(), 1); assert_eq!(metrics.matches("# TYPE prisma_pool_connections_open gauge").count(), 1); - + assert_value_in_range(&metrics, "prisma_pool_connections_open", 0f64, 1f64); + // histograms assert_eq!(metrics.matches("# HELP prisma_client_queries_duration_histogram_ms The distribution of the time Prisma Client queries took to run end to end").count(), 1); assert_eq!(metrics.matches("# TYPE prisma_client_queries_duration_histogram_ms histogram").count(), 1); diff --git a/query-engine/driver-adapters/src/proxy.rs b/query-engine/driver-adapters/src/proxy.rs index 62086a245199..a708d75c0e32 100644 --- a/query-engine/driver-adapters/src/proxy.rs +++ b/query-engine/driver-adapters/src/proxy.rs @@ -249,6 +249,12 @@ fn js_value_to_quaint( column_type: ColumnType, column_name: &str, ) -> quaint::Result> { + let parse_number_as_i64 = |n: &serde_json::Number| { + n.as_i64().ok_or(conversion_error!( + "number must be an integer in column '{column_name}', got '{n}'" + )) + }; + // Note for the future: it may be worth revisiting how much bloat so many panics with different static // strings add to the compiled artefact, and in case we should come up with a restricted set of panic // messages, or even find a way of removing them altogether. @@ -256,8 +262,7 @@ fn js_value_to_quaint( ColumnType::Int32 => match json_value { serde_json::Value::Number(n) => { // n.as_i32() is not implemented, so we need to downcast from i64 instead - n.as_i64() - .ok_or(conversion_error!("number must be an integer in column '{column_name}'")) + parse_number_as_i64(&n) .and_then(|n| -> quaint::Result { n.try_into() .map_err(|e| conversion_error!("cannot convert {n} to i32 in column '{column_name}': {e}")) @@ -273,9 +278,7 @@ fn js_value_to_quaint( )), }, ColumnType::Int64 => match json_value { - serde_json::Value::Number(n) => n.as_i64().map(QuaintValue::int64).ok_or(conversion_error!( - "number must be an i64 in column '{column_name}', got {n}" - )), + serde_json::Value::Number(n) => parse_number_as_i64(&n).map(QuaintValue::int64), serde_json::Value::String(s) => s.parse::().map(QuaintValue::int64).map_err(|e| { conversion_error!("string-encoded number must be an i64 in column '{column_name}', got {s}: {e}") }),