diff --git a/Cargo.lock b/Cargo.lock index ba3b39304ec..5d9834f2d84 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" @@ -6386,7 +6396,9 @@ dependencies = [ "cynic", "edge-schema 0.1.0", "futures 0.3.30", + "getrandom", "harsh", + "merge-streams", "pin-project-lite", "reqwest", "serde", diff --git a/lib/backend-api/Cargo.toml b/lib/backend-api/Cargo.toml index e3c3999ad00..f49a6980f37 100644 --- a/lib/backend-api/Cargo.toml +++ b/lib/backend-api/Cargo.toml @@ -13,7 +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 - [dependencies] # Wasmer dependencies. edge-schema.workspace = true @@ -34,6 +33,11 @@ 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" + +[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 ee38b06e560..88f0945295f 100644 --- a/lib/backend-api/schema.graphql +++ b/lib/backend-api/schema.graphql @@ -197,7 +197,6 @@ type Namespace implements Node & PackageOwner & Owner { name: String! displayName: String description: String! - avatar: String! avatarUpdatedAt: DateTime twitterHandle: String githubHandle: String @@ -209,6 +208,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! diff --git a/lib/backend-api/src/client.rs b/lib/backend-api/src/client.rs index 66270ed9a98..092a09fb4d6 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(all(target_arch = "wasm32", target_os = "unknown"))] + let client = reqwest::Client::builder() + .build() + .context("could not construct http client")?; + + #[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)) .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 ba7f9189c7f..e3120c2796f 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; @@ -958,8 +959,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 @@ -979,17 +979,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. @@ -1351,10 +1347,15 @@ 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. + */ + + #[cfg(all(target_arch = "wasm32", target_os = "unknown"))] + std::thread::sleep(Duration::from_secs(1)); + + #[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))] 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 4646dff33a0..922e2f0e6ae 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,