Skip to content

Commit

Permalink
C ABI target (prisma#4793)
Browse files Browse the repository at this point in the history
* Add C ABI target with support for iOS and Android

* Start undoing merge problems

* Undo merge frocks

* Undo merge frocks

* Undo merge frocks

* Various fixes

* Update query-engine/query-engine-c-abi/README.md

Co-authored-by: Jan Piotrowski <[email protected]>

* Update README

* Lint

* Safety comments

* Shellcheck

* PR changes

* Update query-engine/query-engine-c-abi/README.md

Co-authored-by: Flavian Desverne <[email protected]>

* PR comments

* Get rid of functions file

* Remove comments

* Replace all custom errors with the common ApiError

* Remove hanging TODO

* Remove unnecessary from serde error

* Add failed at field to migrations table and throw on failed migration

* Update query-engine/query-engine-c-abi/src/engine.rs

Co-authored-by: Flavian Desverne <[email protected]>

* Update react native tests to take real emulator url

* Return null adapter on RN case and handle null case

* Fix tests

* Fix mssql & cockroach

* Pass raw error pointer to C context and resign de allocation to calling function

* Serialize API errors on start, commit and rollback transaction

* Re introduce dispatcher and spans

* Add metrics feature to query-engine-common

* change base path missing message to tracing

* Fix copy xcframework script

* Store URL in the query engine instance

* Fix non cloned url error and linting

* Add ReactNative preview feature

* Modify make scripts and add e2e workflow for RN

* Tweak CI

* Tweak CI

* Tweak CI

* Tweak CI

* Tweak CI

* Tweak CI

* Comment e2e test for RN

* Update query-engine/query-engine-c-abi/src/engine.rs

Co-authored-by: Alexey Orlenko <[email protected]>

* Adjust to main

* Remove non-working workflow

---------

Co-authored-by: Jan Piotrowski <[email protected]>
Co-authored-by: Flavian Desverne <[email protected]>
Co-authored-by: Sergey Tatarintsev <[email protected]>
Co-authored-by: Serhii Tatarintsev <[email protected]>
Co-authored-by: Alexey Orlenko <[email protected]>
  • Loading branch information
6 people authored Apr 12, 2024
1 parent b339b9d commit 1d60431
Show file tree
Hide file tree
Showing 38 changed files with 1,937 additions and 223 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/codspeed.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
run: cargo codspeed build -p schema --features all_connectors

- name: "Build the benchmark targets: request-handlers"
run: cargo codspeed build -p request-handlers --features native
run: cargo codspeed build -p request-handlers --features native,all

- name: Run the benchmarks
uses: CodSpeedHQ/action@v2
Expand Down
70 changes: 68 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ members = [
"query-engine/query-engine",
"query-engine/query-engine-node-api",
"query-engine/query-engine-wasm",
"query-engine/query-engine-c-abi",
"query-engine/request-handlers",
"query-engine/schema",
"libs/*",
Expand Down Expand Up @@ -86,6 +87,9 @@ strip = "symbols"
[profile.release.package.query-engine]
strip = "symbols"

[profile.release.package.query-engine-c-abi]
strip = "symbols"

[profile.release]
lto = "fat"
codegen-units = 1
Expand Down
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,9 @@ start-sqlite:
dev-sqlite:
cp $(CONFIG_PATH)/sqlite $(CONFIG_FILE)

dev-react-native:
cp $(CONFIG_PATH)/react-native $(CONFIG_FILE)

dev-libsql-js: build-qe-napi build-driver-adapters-kit
cp $(CONFIG_PATH)/libsql-js $(CONFIG_FILE)

Expand Down
9 changes: 5 additions & 4 deletions libs/query-engine-common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ name = "query-engine-common"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features]
metrics = []

[dependencies]
thiserror = "1"
Expand All @@ -20,11 +21,11 @@ tracing.workspace = true
tracing-subscriber = { version = "0.3" }
tracing-futures = "0.2"
tracing-opentelemetry = "0.17.3"
opentelemetry = { version = "0.17"}
opentelemetry = { version = "0.17" }

[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
napi.workspace = true
[target.'cfg(all(not(target_arch = "wasm32")))'.dependencies]
query-engine-metrics = { path = "../../query-engine/metrics" }
napi.workspace = true

[target.'cfg(target_arch = "wasm32")'.dependencies]
wasm-bindgen.workspace = true
Expand Down
1 change: 1 addition & 0 deletions libs/query-engine-common/src/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ pub struct EngineBuilder {
pub struct ConnectedEngineNative {
pub config_dir: PathBuf,
pub env: HashMap<String, String>,
#[cfg(feature = "metrics")]
pub metrics: Option<query_engine_metrics::MetricRegistry>,
}

Expand Down
1 change: 1 addition & 0 deletions libs/query-engine-common/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ impl From<serde_json::Error> for ApiError {
}

#[cfg(not(target_arch = "wasm32"))]
#[cfg(not(any(target_os = "android", target_os = "ios")))]
impl From<ApiError> for napi::Error {
fn from(e: ApiError) -> Self {
let user_facing = user_facing_errors::Error::from(e);
Expand Down
5 changes: 3 additions & 2 deletions psl/psl-core/src/common/preview_features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,9 @@ features!(
UncheckedScalarInputs,
Views,
RelationJoins,
ReactNative,
PrismaSchemaFolder,
OmitApi,
OmitApi
);

/// Generator preview features (alphabetically sorted)
Expand Down Expand Up @@ -131,7 +132,7 @@ pub const ALL_PREVIEW_FEATURES: FeatureMap = FeatureMap {
| TransactionApi
| UncheckedScalarInputs
}),
hidden: enumflags2::make_bitflags!(PreviewFeature::{PrismaSchemaFolder}),
hidden: enumflags2::make_bitflags!(PreviewFeature::{PrismaSchemaFolder | ReactNative}),
};

#[derive(Debug)]
Expand Down
2 changes: 1 addition & 1 deletion query-engine/connector-test-kit-rs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ To run tests through a driver adapters, you should also configure the following

* `DRIVER_ADAPTER`: tells the test executor to use a particular driver adapter. Set to `neon`, `planetscale` or any other supported adapter.
* `DRIVER_ADAPTER_CONFIG`: a json string with the configuration for the driver adapter. This is adapter specific. See the [github workflow for driver adapter tests](.github/workflows/query-engine-driver-adapters.yml) for examples on how to configure the driver adapters.
* `ENGINE`: can be used to run either `wasm` or `napi` version of the engine.
* `ENGINE`: can be used to run either `wasm` or `napi` or `c-abi` version of the engine.

Example:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use query_engine_tests::test_suite;
exclude(
Vitess("planetscale.js", "planetscale.js.wasm"),
Postgres("neon.js", "pg.js", "neon.js.wasm", "pg.js.wasm"),
Sqlite("libsql.js", "libsql.js.wasm", "cfd1")
Sqlite("libsql.js", "libsql.js.wasm", "cfd1", "react-native")
)
)]
mod metrics {
Expand Down
36 changes: 30 additions & 6 deletions query-engine/connector-test-kit-rs/query-tests-setup/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,20 @@ use std::{convert::TryFrom, env, fmt::Display, fs::File, io::Read, path::PathBuf

static TEST_CONFIG_FILE_NAME: &str = ".test_config";

#[derive(Debug, Deserialize, Default, Clone)]
#[derive(Debug, Deserialize, Default, Clone, Copy, PartialEq)]
pub enum TestExecutor {
#[default]
Napi,
Wasm,
Mobile,
}

impl Display for TestExecutor {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
TestExecutor::Napi => f.write_str("Napi"),
TestExecutor::Wasm => f.write_str("Wasm"),
TestExecutor::Mobile => f.write_str("Mobile"),
}
}
}
Expand Down Expand Up @@ -62,6 +64,11 @@ pub struct TestConfigFromSerde {
/// test executor by setting the `DRIVER_ADAPTER_CONFIG` env var when spawning the executor.
/// Correctness: if set, [`TestConfigFromSerde::driver_adapter`] must be set as well.
pub(crate) driver_adapter_config: Option<DriverAdapterConfig>,

/// For mobile tests a running device with a valid http server is required.
/// This is the URL to the mobile emulator which will execute the queries against
/// the instances of the engine running on the device.
pub(crate) mobile_emulator_url: Option<String>,
}

impl TestConfigFromSerde {
Expand Down Expand Up @@ -105,10 +112,18 @@ impl TestConfigFromSerde {
Err(err) => exit_with_message(&err.to_string()),
}

if self.external_test_executor.is_some() && self.driver_adapter.is_none() {
exit_with_message(
"When using an external test executor, the driver adapter (DRIVER_ADAPTER env var) must be set.",
);
if self.external_test_executor.is_some() {
if self.external_test_executor.unwrap() == TestExecutor::Mobile && self.mobile_emulator_url.is_none() {
exit_with_message(
"When using the mobile external test executor, the mobile emulator URL (MOBILE_EMULATOR_URL env var) must be set.",
);
}

if self.external_test_executor.unwrap() != TestExecutor::Mobile && self.driver_adapter.is_none() {
exit_with_message(
"When using an external test executor, the driver adapter (DRIVER_ADAPTER env var) must be set.",
);
}
}

if self.driver_adapter.is_some() && self.external_test_executor.is_none() {
Expand Down Expand Up @@ -154,6 +169,7 @@ pub struct TestConfig {
pub(crate) connector_version: Option<String>,
pub(crate) with_driver_adapter: Option<WithDriverAdapter>,
pub(crate) is_ci: bool,
pub(crate) mobile_emulator_url: Option<String>,
}

impl From<TestConfigFromSerde> for TestConfig {
Expand All @@ -174,6 +190,7 @@ impl From<TestConfigFromSerde> for TestConfig {
connector_version: config.connector_version,
is_ci: config.is_ci,
with_driver_adapter,
mobile_emulator_url: config.mobile_emulator_url,
}
}
}
Expand Down Expand Up @@ -213,6 +230,7 @@ And optionally, to test driver adapters
- EXTERNAL_TEST_EXECUTOR
- DRIVER_ADAPTER
- DRIVER_ADAPTER_CONFIG (optional, not required by all driver adapters)
- MOBILE_EMULATOR_URL (optional, only required by mobile external test executor)
📁 Config file
Expand Down Expand Up @@ -278,6 +296,8 @@ impl TestConfig {
.map(|config| serde_json::from_str::<DriverAdapterConfig>(config.as_str()).ok())
.unwrap_or_default();

let mobile_emulator_url = std::env::var("MOBILE_EMULATOR_URL").ok();

// Just care for a set value for now.
let is_ci = std::env::var("BUILDKITE").is_ok();

Expand All @@ -289,13 +309,13 @@ impl TestConfig {
external_test_executor,
driver_adapter,
driver_adapter_config,
mobile_emulator_url,
})
.map(Self::from)
}

fn from_file() -> Option<Self> {
let current_dir = env::current_dir().ok();

current_dir
.and_then(|path| Self::try_path(config_path(path)))
.or_else(|| Self::workspace_root().and_then(|path| Self::try_path(config_path(path))))
Expand Down Expand Up @@ -402,6 +422,10 @@ impl TestConfig {
"PRISMA_DISABLE_QUAINT_EXECUTORS".to_string(),
"1".to_string(),
),
(
"MOBILE_EMULATOR_URL".to_string(),
self.mobile_emulator_url.clone().unwrap_or_default()
),
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -196,8 +196,9 @@ fn start_rpc_thread(mut receiver: mpsc::Receiver<ReqImpl>) -> Result<()> {
.build()
.unwrap()
.block_on(async move {
let environment = CONFIG.for_external_executor();
let process = match Command::new(&path)
.envs(CONFIG.for_external_executor())
.envs(environment)
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.stderr(Stdio::inherit())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ impl ConnectorTagInterface for SqliteConnectorTag {
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum SqliteVersion {
V3,
ReactNative,
LibsqlJsNapi,
LibsqlJsWasm,
CloudflareD1,
Expand All @@ -37,6 +38,7 @@ pub enum SqliteVersion {
impl ToString for SqliteVersion {
fn to_string(&self) -> String {
match self {
SqliteVersion::ReactNative => "react-native".to_string(),
SqliteVersion::V3 => "3".to_string(),
SqliteVersion::LibsqlJsNapi => "libsql.js".to_string(),
SqliteVersion::LibsqlJsWasm => "libsql.js.wasm".to_string(),
Expand All @@ -53,6 +55,7 @@ impl TryFrom<&str> for SqliteVersion {
"3" => Self::V3,
"libsql.js" => Self::LibsqlJsNapi,
"libsql.js.wasm" => Self::LibsqlJsWasm,
"react-native" => Self::ReactNative,
"cfd1" => Self::CloudflareD1,
_ => return Err(TestError::parse_error(format!("Unknown SQLite version `{s}`"))),
};
Expand Down
6 changes: 6 additions & 0 deletions query-engine/connector-test-kit-rs/test-configs/react-native
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"connector": "sqlite",
"version": "react-native",
"external_test_executor": "Mobile",
"mobile_emulator_url": "http://localhost:3000"
}
Loading

0 comments on commit 1d60431

Please sign in to comment.