From 144131f87387e55c5a53ee9b00d03c6c2025713d Mon Sep 17 00:00:00 2001 From: Edoardo Marangoni Date: Wed, 3 Jul 2024 18:41:33 +0200 Subject: [PATCH 1/7] fix(wasmer-api): Resolve compilation issues when targeting wasm32 --- Cargo.lock | 27 +++++++++++- lib/backend-api/Cargo.toml | 9 ++++ lib/backend-api/schema.graphql | 78 +++++++++++++++++++++++++++++++--- lib/backend-api/src/client.rs | 11 ++++- lib/backend-api/src/query.rs | 35 ++++++++------- lib/backend-api/src/types.rs | 2 +- 6 files changed, 135 insertions(+), 27 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ba3b39304ec..3d3973f9885 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2970,6 +2970,16 @@ dependencies = [ "autocfg", ] +[[package]] +name = "merge-streams" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f84f6452969abd246e7ac1fe4fe75906c76e8ec88d898df9aef37e0f3b6a7c2" +dependencies = [ + "futures-core", + "pin-project", +] + [[package]] name = "mime" version = "0.3.17" @@ -4495,6 +4505,17 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "serde-wasm-bindgen" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8302e169f0eddcc139c70f139d19d6467353af16f9fce27e8c30158036a1e16b" +dependencies = [ + "js-sys", + "serde", + "wasm-bindgen", +] + [[package]] name = "serde_bytes" version = "0.11.14" @@ -6357,7 +6378,7 @@ dependencies = [ "rustc-demangle", "rusty_jsc", "serde", - "serde-wasm-bindgen", + "serde-wasm-bindgen 0.4.5", "shared-buffer", "target-lexicon 0.12.14", "tempfile", @@ -6386,10 +6407,13 @@ dependencies = [ "cynic", "edge-schema 0.1.0", "futures 0.3.30", + "getrandom", "harsh", + "merge-streams", "pin-project-lite", "reqwest", "serde", + "serde-wasm-bindgen 0.6.5", "serde_json", "serde_path_to_error", "time 0.3.36", @@ -6397,6 +6421,7 @@ dependencies = [ "tracing", "url", "uuid", + "wasm-bindgen", "wasmer-config 0.4.0", "webc", ] diff --git a/lib/backend-api/Cargo.toml b/lib/backend-api/Cargo.toml index e3c3999ad00..f1cfc544c8d 100644 --- a/lib/backend-api/Cargo.toml +++ b/lib/backend-api/Cargo.toml @@ -13,6 +13,8 @@ repository.workspace = true rust-version.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[features] +derive-wasm-bindgen = ["dep:serde-wasm-bindgen"] [dependencies] # Wasmer dependencies. @@ -34,6 +36,13 @@ pin-project-lite = "0.2.10" serde_path_to_error = "0.1.14" harsh = "0.2.2" reqwest = { version = "0.11.13", default-features = false, features = ["json"] } +merge-streams = "0.1.2" +wasm-bindgen = "0.2.92" +serde-wasm-bindgen = { version = "0.6", optional = true } + +[target.'cfg(target_family = "wasm")'.dependencies.getrandom] +version = "0.2.14" +features = ["js"] [dev-dependencies] base64 = "0.13.1" diff --git a/lib/backend-api/schema.graphql b/lib/backend-api/schema.graphql index a43d1b64fff..a0b1840ca08 100644 --- a/lib/backend-api/schema.graphql +++ b/lib/backend-api/schema.graphql @@ -193,7 +193,6 @@ type Namespace implements Node & PackageOwner & Owner { name: String! displayName: String description: String! - avatar: String! avatarUpdatedAt: DateTime twitterHandle: String githubHandle: String @@ -205,6 +204,7 @@ type Namespace implements Node & PackageOwner & Owner { userSet(offset: Int, before: String, after: String, first: Int, last: Int): UserConnection! globalName: String! globalId: ID! + avatar: String! packages(offset: Int, before: String, after: String, first: Int, last: Int): PackageConnection! apps(sortBy: DeployAppsSortBy, offset: Int, before: String, after: String, first: Int, last: Int): DeployAppConnection! packageVersions(offset: Int, before: String, after: String, first: Int, last: Int): PackageVersionConnection! @@ -939,6 +939,8 @@ type BindingsGeneratorEdge { type BindingsGenerator implements Node { """The ID of the object""" id: ID! + createdAt: DateTime! + updatedAt: DateTime! packageVersion: PackageVersion! active: Boolean! commandName: String! @@ -1235,11 +1237,13 @@ type AppTemplate implements Node { updatedAt: DateTime! readme: String! useCases: JSONString! - framework: String! - language: String! repoLicense: String! usingPackage: Package defaultImage: String + framework: String! + templateFramework: TemplateFramework + language: String! + templateLanguage: TemplateLanguage } type AppTemplateCategory implements Node { @@ -1253,6 +1257,24 @@ type AppTemplateCategory implements Node { appTemplates(offset: Int, before: String, after: String, first: Int, last: Int): AppTemplateConnection! } +type TemplateFramework implements Node { + """The ID of the object""" + id: ID! + createdAt: DateTime! + updatedAt: DateTime! + name: String! + slug: String! +} + +type TemplateLanguage implements Node { + """The ID of the object""" + id: ID! + createdAt: DateTime! + updatedAt: DateTime! + name: String! + slug: String! +} + type Collection { slug: String! displayName: String! @@ -1540,14 +1562,14 @@ type DNSDomainEdge { } type DNSDomain implements Node { + createdAt: DateTime! + updatedAt: DateTime! + deletedAt: DateTime name: String! """This zone will be accessible at /dns/{slug}/.""" slug: String! zoneFile: String! - createdAt: DateTime! - updatedAt: DateTime! - deletedAt: DateTime """The ID of the object""" id: ID! @@ -2258,7 +2280,9 @@ type Query { getAppByGlobalAlias(alias: String!): DeployApp getDeployApps(sortBy: DeployAppsSortBy, updatedAfter: DateTime, offset: Int, before: String, after: String, first: Int, last: Int): DeployAppConnection! getAppVersions(sortBy: DeployAppVersionsSortBy, updatedAfter: DateTime, offset: Int, before: String, after: String, first: Int, last: Int): DeployAppVersionConnection! - getAppTemplates(categorySlug: String, sortBy: AppTemplatesSortBy, offset: Int, before: String, after: String, first: Int, last: Int): AppTemplateConnection + getTemplateFrameworks(offset: Int, before: String, after: String, first: Int, last: Int): TemplateFrameworkConnection + getTemplateLanguages(offset: Int, before: String, after: String, first: Int, last: Int): TemplateLanguageConnection + getAppTemplates(categorySlug: String, frameworkSlug: String, languageSlug: String, sortBy: AppTemplatesSortBy, offset: Int, before: String, after: String, first: Int, last: Int): AppTemplateConnection getAppTemplate(slug: String!): AppTemplate getAppTemplateCategories(offset: Int, before: String, after: String, first: Int, last: Int): AppTemplateCategoryConnection viewer: User @@ -2357,6 +2381,46 @@ enum DNSRecordsSortBy { OLDEST } +type TemplateFrameworkConnection { + """Pagination data for this connection.""" + pageInfo: PageInfo! + + """Contains the nodes in this connection.""" + edges: [TemplateFrameworkEdge]! + + """Total number of items in the connection.""" + totalCount: Int +} + +"""A Relay edge containing a `TemplateFramework` and its cursor.""" +type TemplateFrameworkEdge { + """The item at the end of the edge""" + node: TemplateFramework + + """A cursor for use in pagination""" + cursor: String! +} + +type TemplateLanguageConnection { + """Pagination data for this connection.""" + pageInfo: PageInfo! + + """Contains the nodes in this connection.""" + edges: [TemplateLanguageEdge]! + + """Total number of items in the connection.""" + totalCount: Int +} + +"""A Relay edge containing a `TemplateLanguage` and its cursor.""" +type TemplateLanguageEdge { + """The item at the end of the edge""" + node: TemplateLanguage + + """A cursor for use in pagination""" + cursor: String! +} + enum AppTemplatesSortBy { NEWEST OLDEST diff --git a/lib/backend-api/src/client.rs b/lib/backend-api/src/client.rs index 66270ed9a98..9487a074186 100644 --- a/lib/backend-api/src/client.rs +++ b/lib/backend-api/src/client.rs @@ -1,11 +1,11 @@ +#[cfg(not(target_family = "wasm"))] use std::time::Duration; +use crate::GraphQLApiFailure; use anyhow::{bail, Context as _}; use cynic::{http::CynicReqwestError, GraphQlResponse, Operation}; use url::Url; -use crate::GraphQLApiFailure; - /// API client for the Wasmer API. /// /// Use the queries in [`crate::queries`] to interact with the API. @@ -53,11 +53,18 @@ impl WasmerClient { } pub fn new(graphql_endpoint: Url, user_agent: &str) -> Result { + #[cfg(target_family = "wasm")] + let client = reqwest::Client::builder() + .build() + .context("could not construct http client")?; + + #[cfg(not(target_family = "wasm"))] let client = reqwest::Client::builder() .connect_timeout(Duration::from_secs(10)) .timeout(Duration::from_secs(90)) .build() .context("could not construct http client")?; + Self::new_with_client(client, graphql_endpoint, user_agent) } diff --git a/lib/backend-api/src/query.rs b/lib/backend-api/src/query.rs index 341761e184b..806a5b9b63e 100644 --- a/lib/backend-api/src/query.rs +++ b/lib/backend-api/src/query.rs @@ -1,9 +1,10 @@ -use std::{collections::HashSet, pin::Pin, time::Duration}; +use std::{collections::HashSet, time::Duration}; use anyhow::{bail, Context}; use cynic::{MutationBuilder, QueryBuilder}; use edge_schema::schema::NetworkTokenV1; -use futures::{Stream, StreamExt}; +use futures::StreamExt; +use merge_streams::MergeStreams; use time::OffsetDateTime; use tracing::Instrument; use url::Url; @@ -606,8 +607,7 @@ pub async fn user_accessible_apps( impl futures::Stream, anyhow::Error>> + '_, anyhow::Error, > { - let apps: Pin, anyhow::Error>> + Send + Sync>> = - Box::pin(user_apps(client).await); + let user_apps = user_apps(client).await; // Get all aps in user-accessible namespaces. let namespace_res = client @@ -627,17 +627,13 @@ pub async fn user_accessible_apps( .map(|node| node.name.clone()) .collect::>(); - let mut all_apps = vec![apps]; + let mut ns_apps = vec![]; for ns in namespace_names { - let apps: Pin, anyhow::Error>> + Send + Sync>> = - Box::pin(namespace_apps(client, ns).await); - - all_apps.push(apps); + let apps = namespace_apps(client, ns).await; + ns_apps.push(apps); } - let apps = futures::stream::select_all(all_apps); - - Ok(apps) + Ok((user_apps, ns_apps.merge()).merge()) } /// Get apps for a specific namespace. @@ -998,11 +994,18 @@ fn get_app_logs( if page.is_empty() { if watch { - /* - TODO: the resolution of watch should be configurable - TODO: should this be async? - */ + /* + * [TODO]: The resolution here should be configurable. + */ + + // No tokio::time::sleep on wasm32 as of now. + // Probably not ideal? + #[cfg(target_family = "wasm32")] + std::thread::sleep(Duration::from_secs(1)); + + #[cfg(not(target_family = "wasm32"))] tokio::time::sleep(Duration::from_secs(1)).await; + continue; } diff --git a/lib/backend-api/src/types.rs b/lib/backend-api/src/types.rs index e4ac2c38b75..16e772de14a 100644 --- a/lib/backend-api/src/types.rs +++ b/lib/backend-api/src/types.rs @@ -58,7 +58,7 @@ mod queries { pub viewer: Option, } - #[derive(cynic::QueryFragment, Debug)] + #[derive(cynic::QueryFragment, Debug, serde::Serialize)] pub struct User { pub id: cynic::Id, pub username: String, From ea3b707a049475db89ecbd43ceed389e0b76240d Mon Sep 17 00:00:00 2001 From: Edoardo Marangoni Date: Wed, 3 Jul 2024 18:46:19 +0200 Subject: [PATCH 2/7] chore(backend-api): Make linter happy --- lib/backend-api/src/query.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/backend-api/src/query.rs b/lib/backend-api/src/query.rs index 7aa7598dfa0..766fac995c0 100644 --- a/lib/backend-api/src/query.rs +++ b/lib/backend-api/src/query.rs @@ -1346,12 +1346,12 @@ fn get_app_logs( if page.is_empty() { if watch { - /* - * [TODO]: The resolution here should be configurable. + /* + * [TODO]: The resolution here should be configurable. */ - // No tokio::time::sleep on wasm32 as of now. - // Probably not ideal? + // No tokio::time::sleep on wasm32 as of now. + // Probably not ideal? #[cfg(target_family = "wasm32")] std::thread::sleep(Duration::from_secs(1)); From 9d458fabda6e2e3608297eda2267bdf53994b93a Mon Sep 17 00:00:00 2001 From: Edoardo Marangoni Date: Thu, 4 Jul 2024 17:57:27 +0200 Subject: [PATCH 3/7] fix(backend-api): Remove unused `serde-wasm-bindgen` dependency --- lib/backend-api/Cargo.toml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/backend-api/Cargo.toml b/lib/backend-api/Cargo.toml index f1cfc544c8d..72915b04ce3 100644 --- a/lib/backend-api/Cargo.toml +++ b/lib/backend-api/Cargo.toml @@ -13,9 +13,6 @@ repository.workspace = true rust-version.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html -[features] -derive-wasm-bindgen = ["dep:serde-wasm-bindgen"] - [dependencies] # Wasmer dependencies. edge-schema.workspace = true @@ -38,7 +35,6 @@ harsh = "0.2.2" reqwest = { version = "0.11.13", default-features = false, features = ["json"] } merge-streams = "0.1.2" wasm-bindgen = "0.2.92" -serde-wasm-bindgen = { version = "0.6", optional = true } [target.'cfg(target_family = "wasm")'.dependencies.getrandom] version = "0.2.14" From bbd9e3ffc8962cde42ad769ee1edb090c829e407 Mon Sep 17 00:00:00 2001 From: Edoardo Marangoni Date: Mon, 8 Jul 2024 12:52:14 +0200 Subject: [PATCH 4/7] chore: Remove serde-wasm-bindgen from cargo.lock --- Cargo.lock | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3d3973f9885..d5813d94a22 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4505,17 +4505,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "serde-wasm-bindgen" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8302e169f0eddcc139c70f139d19d6467353af16f9fce27e8c30158036a1e16b" -dependencies = [ - "js-sys", - "serde", - "wasm-bindgen", -] - [[package]] name = "serde_bytes" version = "0.11.14" @@ -6378,7 +6367,7 @@ dependencies = [ "rustc-demangle", "rusty_jsc", "serde", - "serde-wasm-bindgen 0.4.5", + "serde-wasm-bindgen", "shared-buffer", "target-lexicon 0.12.14", "tempfile", @@ -6413,7 +6402,6 @@ dependencies = [ "pin-project-lite", "reqwest", "serde", - "serde-wasm-bindgen 0.6.5", "serde_json", "serde_path_to_error", "time 0.3.36", From 3c88d238e56f64665edde02997a703aa21fae7c6 Mon Sep 17 00:00:00 2001 From: Edoardo Marangoni Date: Mon, 8 Jul 2024 12:59:41 +0200 Subject: [PATCH 5/7] fix(backend-api): Remove unneeded dependency and fix typo in `target_family` cfg --- Cargo.lock | 1 - lib/backend-api/Cargo.toml | 1 - lib/backend-api/src/query.rs | 4 ++-- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d5813d94a22..5d9834f2d84 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6409,7 +6409,6 @@ dependencies = [ "tracing", "url", "uuid", - "wasm-bindgen", "wasmer-config 0.4.0", "webc", ] diff --git a/lib/backend-api/Cargo.toml b/lib/backend-api/Cargo.toml index 72915b04ce3..f49a6980f37 100644 --- a/lib/backend-api/Cargo.toml +++ b/lib/backend-api/Cargo.toml @@ -34,7 +34,6 @@ serde_path_to_error = "0.1.14" harsh = "0.2.2" reqwest = { version = "0.11.13", default-features = false, features = ["json"] } merge-streams = "0.1.2" -wasm-bindgen = "0.2.92" [target.'cfg(target_family = "wasm")'.dependencies.getrandom] version = "0.2.14" diff --git a/lib/backend-api/src/query.rs b/lib/backend-api/src/query.rs index 766fac995c0..f8692c8f49b 100644 --- a/lib/backend-api/src/query.rs +++ b/lib/backend-api/src/query.rs @@ -1352,10 +1352,10 @@ fn get_app_logs( // No tokio::time::sleep on wasm32 as of now. // Probably not ideal? - #[cfg(target_family = "wasm32")] + #[cfg(target_family = "wasm")] std::thread::sleep(Duration::from_secs(1)); - #[cfg(not(target_family = "wasm32"))] + #[cfg(not(target_family = "wasm"))] tokio::time::sleep(Duration::from_secs(1)).await; continue; From 5dcc9f8229a53b065ff1a440ccb382fecbc90bb3 Mon Sep 17 00:00:00 2001 From: Edoardo Marangoni Date: Wed, 10 Jul 2024 10:52:06 +0200 Subject: [PATCH 6/7] feat(backend-api): Take into account `wasm32-wasmer-wasi` targets --- lib/backend-api/src/client.rs | 4 ++-- lib/backend-api/src/query.rs | 7 ++----- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/lib/backend-api/src/client.rs b/lib/backend-api/src/client.rs index 9487a074186..f827f6909a1 100644 --- a/lib/backend-api/src/client.rs +++ b/lib/backend-api/src/client.rs @@ -53,12 +53,12 @@ impl WasmerClient { } pub fn new(graphql_endpoint: Url, user_agent: &str) -> Result { - #[cfg(target_family = "wasm")] + #[cfg(all(target_family = "wasm", not(target = "wasm32-wasmer-wasi")))] let client = reqwest::Client::builder() .build() .context("could not construct http client")?; - #[cfg(not(target_family = "wasm"))] + #[cfg(any(not(target_family = "wasm"), target = "wasm32-wasmer-wasi"))] let client = reqwest::Client::builder() .connect_timeout(Duration::from_secs(10)) .timeout(Duration::from_secs(90)) diff --git a/lib/backend-api/src/query.rs b/lib/backend-api/src/query.rs index f8692c8f49b..721999b7eb4 100644 --- a/lib/backend-api/src/query.rs +++ b/lib/backend-api/src/query.rs @@ -1350,12 +1350,9 @@ fn get_app_logs( * [TODO]: The resolution here should be configurable. */ - // No tokio::time::sleep on wasm32 as of now. - // Probably not ideal? - #[cfg(target_family = "wasm")] + #[cfg(all(target_family = "wasm", not(target = "wasm32-wasmer-wasi")))] std::thread::sleep(Duration::from_secs(1)); - - #[cfg(not(target_family = "wasm"))] + #[cfg(any(not(target_family = "wasm"), target = "wasm32-wasmer-wasi"))] tokio::time::sleep(Duration::from_secs(1)).await; continue; From 17b77586782c657610e2cc329b1c4b6ae0924bed Mon Sep 17 00:00:00 2001 From: Edoardo Marangoni Date: Thu, 11 Jul 2024 11:03:20 +0200 Subject: [PATCH 7/7] fix(backend-api): Use "wasm32-unknown-unknown" in #cfgs --- lib/backend-api/src/client.rs | 4 ++-- lib/backend-api/src/query.rs | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/backend-api/src/client.rs b/lib/backend-api/src/client.rs index f827f6909a1..092a09fb4d6 100644 --- a/lib/backend-api/src/client.rs +++ b/lib/backend-api/src/client.rs @@ -53,12 +53,12 @@ impl WasmerClient { } pub fn new(graphql_endpoint: Url, user_agent: &str) -> Result { - #[cfg(all(target_family = "wasm", not(target = "wasm32-wasmer-wasi")))] + #[cfg(all(target_arch = "wasm32", target_os = "unknown"))] let client = reqwest::Client::builder() .build() .context("could not construct http client")?; - #[cfg(any(not(target_family = "wasm"), target = "wasm32-wasmer-wasi"))] + #[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))] let client = reqwest::Client::builder() .connect_timeout(Duration::from_secs(10)) .timeout(Duration::from_secs(90)) diff --git a/lib/backend-api/src/query.rs b/lib/backend-api/src/query.rs index 721999b7eb4..e3120c2796f 100644 --- a/lib/backend-api/src/query.rs +++ b/lib/backend-api/src/query.rs @@ -1350,9 +1350,10 @@ fn get_app_logs( * [TODO]: The resolution here should be configurable. */ - #[cfg(all(target_family = "wasm", not(target = "wasm32-wasmer-wasi")))] + #[cfg(all(target_arch = "wasm32", target_os = "unknown"))] std::thread::sleep(Duration::from_secs(1)); - #[cfg(any(not(target_family = "wasm"), target = "wasm32-wasmer-wasi"))] + + #[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))] tokio::time::sleep(Duration::from_secs(1)).await; continue;