diff --git a/benches/import_functions.rs b/benches/import_functions.rs index 834ca0061d9..2f1d4f758bb 100644 --- a/benches/import_functions.rs +++ b/benches/import_functions.rs @@ -56,6 +56,7 @@ pub fn run_import_inner(store: &mut Store, n_fn: u32, compiler_name: &str, c: &m } fn run_import_functions_benchmarks_small(_c: &mut Criterion) { + #[allow(unused_variables)] let size = 10; #[cfg(feature = "llvm")] @@ -78,6 +79,7 @@ fn run_import_functions_benchmarks_small(_c: &mut Criterion) { } fn run_import_functions_benchmarks_medium(_c: &mut Criterion) { + #[allow(unused_variables)] let size = 100; #[cfg(feature = "llvm")] @@ -100,6 +102,7 @@ fn run_import_functions_benchmarks_medium(_c: &mut Criterion) { } fn run_import_functions_benchmarks_large(_c: &mut Criterion) { + #[allow(unused_variables)] let size = 1000; #[cfg(feature = "llvm")] { diff --git a/lib/backend-api/schema.graphql b/lib/backend-api/schema.graphql index 8c94716758f..a1d3f25d629 100644 --- a/lib/backend-api/schema.graphql +++ b/lib/backend-api/schema.graphql @@ -37,6 +37,7 @@ type User implements Node & PackageOwner & Owner { bio: String location: String websiteUrl: String + wasmerInternal: Boolean! """The ID of the object""" id: ID! @@ -199,6 +200,7 @@ type Namespace implements Node & PackageOwner & Owner { websiteUrl: String createdAt: DateTime! updatedAt: DateTime! + wasmerInternal: Boolean! maintainerInvites(offset: Int, before: String, after: String, first: Int, last: Int): NamespaceCollaboratorInviteConnection! userSet(offset: Int, before: String, after: String, first: Int, last: Int): UserConnection! globalName: String! @@ -446,6 +448,7 @@ type PackageVersion implements Node & PackageReleaseInterface & PackageInstance bindingsState: RegistryPackageVersionBindingsStateChoices! nativeExecutablesState: RegistryPackageVersionNativeExecutablesStateChoices! deployappversionSet(offset: Int, before: String, after: String, first: Int, last: Int): DeployAppVersionConnection! + packagewebcSet(offset: Int, before: String, after: String, first: Int, last: Int): PackageWebcConnection! lastversionPackage(offset: Int, before: String, after: String, first: Int, last: Int): PackageConnection! commands: [Command!]! nativeexecutableSet(offset: Int, before: String, after: String, first: Int, last: Int): NativeExecutableConnection! @@ -504,7 +507,9 @@ scalar JSONString type WebcImage implements Node { """The ID of the object""" id: ID! - version: WebcVersion + + """The version of the webc image, defaults to v2.""" + version: WebcVersion! """""" fileSize: BigInt! @@ -835,6 +840,26 @@ type AppVersionVolumeMountPath { subpath: String! } +type PackageWebcConnection { + """Pagination data for this connection.""" + pageInfo: PageInfo! + + """Contains the nodes in this connection.""" + edges: [PackageWebcEdge]! + + """Total number of items in the connection.""" + totalCount: Int +} + +"""A Relay edge containing a `PackageWebc` and its cursor.""" +type PackageWebcEdge { + """The item at the end of the edge""" + node: PackageWebc + + """A cursor for use in pagination""" + cursor: String! +} + type Command { command: String! packageVersion: PackageVersion! @@ -1227,26 +1252,6 @@ type AppTemplateCategory implements Node { appTemplates(offset: Int, before: String, after: String, first: Int, last: Int): AppTemplateConnection! } -type PackageWebcConnection { - """Pagination data for this connection.""" - pageInfo: PageInfo! - - """Contains the nodes in this connection.""" - edges: [PackageWebcEdge]! - - """Total number of items in the connection.""" - totalCount: Int -} - -"""A Relay edge containing a `PackageWebc` and its cursor.""" -type PackageWebcEdge { - """The item at the end of the edge""" - node: PackageWebc - - """A cursor for use in pagination""" - cursor: String! -} - type Collection { slug: String! displayName: String! @@ -2088,6 +2093,9 @@ type Log { """Log stream""" stream: LogStream + + """ID of instance from which the log was generated""" + instanceId: String! } """This is for backwards compatibility with the old PackageInstance type.""" @@ -2249,7 +2257,7 @@ 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, offset: Int, before: String, after: String, first: Int, last: Int): AppTemplateConnection + getAppTemplates(categorySlug: 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 @@ -2348,6 +2356,12 @@ enum DNSRecordsSortBy { OLDEST } +enum AppTemplatesSortBy { + NEWEST + OLDEST + POPULAR +} + type AppTemplateCategoryConnection { """Pagination data for this connection.""" pageInfo: PageInfo! @@ -2788,6 +2802,9 @@ type Mutation { generateDeployConfigToken(input: GenerateDeployConfigTokenInput!): GenerateDeployConfigTokenPayload renameApp(input: RenameAppInput!): RenameAppPayload renameAppAlias(input: RenameAppAliasInput!): RenameAppAliasPayload + + """Purges all cache for this app version""" + purgeCacheForAppVersion(input: PurgeCacheForAppVersionInput!): PurgeCacheForAppVersionPayload requestAppTransfer(input: RequestAppTransferInput!): RequestAppTransferPayload acceptAppTransferRequest(input: AcceptAppTransferRequestInput!): AcceptAppTransferRequestPayload removeAppTransferRequest(input: RemoveAppTransferRequestInput!): RemoveAppTransferRequestPayload @@ -3026,6 +3043,18 @@ input RenameAppAliasInput { clientMutationId: String } +"""Purges all cache for this app version""" +type PurgeCacheForAppVersionPayload { + appVersion: DeployAppVersion! + clientMutationId: String +} + +input PurgeCacheForAppVersionInput { + """ID of the app version to purge cache for.""" + id: ID! + clientMutationId: String +} + type RequestAppTransferPayload { appTransferRequest: AppTransferRequest wasInstantlyTransferred: Boolean! @@ -3086,6 +3115,7 @@ input CreateRepoForAppTemplateInput { name: String! namespace: String! private: Boolean = false + domains: [String] = null clientMutationId: String } @@ -3606,9 +3636,9 @@ type TagPackageReleasePayload { input TagPackageReleaseInput { packageReleaseId: ID! - name: String! version: String! - manifest: String! + name: String + manifest: String namespace: String description: String license: String diff --git a/lib/backend-api/src/query.rs b/lib/backend-api/src/query.rs index 0d777b04d3a..e8774a1784c 100644 --- a/lib/backend-api/src/query.rs +++ b/lib/backend-api/src/query.rs @@ -1137,6 +1137,20 @@ pub fn get_all_dns_records_stream( ) } +pub async fn purge_cache_for_app_version( + client: &WasmerClient, + vars: types::PurgeCacheForAppVersionVars, +) -> Result<(), anyhow::Error> { + client + .run_graphql_strict(types::PurgeCacheForAppVersion::build(vars)) + .await + .map_err(anyhow::Error::from) + .map(|x| x.purge_cache_for_app_version) + .context("backend did not return data")?; + + Ok(()) +} + /// Convert a [`OffsetDateTime`] to a unix timestamp that the WAPM backend /// understands. fn unix_timestamp(ts: OffsetDateTime) -> f64 { diff --git a/lib/backend-api/src/types.rs b/lib/backend-api/src/types.rs index 1519ff67ff1..9f381c87dd9 100644 --- a/lib/backend-api/src/types.rs +++ b/lib/backend-api/src/types.rs @@ -1547,6 +1547,23 @@ mod queries { pub records: Option>>, } + #[derive(cynic::QueryVariables, Debug)] + pub struct PurgeCacheForAppVersionVars { + pub id: cynic::Id, + } + + #[derive(cynic::QueryFragment, Debug)] + pub struct PurgeCacheForAppVersionPayload { + pub app_version: DeployAppVersion, + } + + #[derive(cynic::QueryFragment, Debug)] + #[cynic(graphql_type = "Mutation", variables = "PurgeCacheForAppVersionVars")] + pub struct PurgeCacheForAppVersion { + #[arguments(input: {id: $id})] + pub purge_cache_for_app_version: Option, + } + #[derive(cynic::Scalar, Debug, Clone)] pub struct BigInt(pub i64); diff --git a/lib/cli/src/commands/app/mod.rs b/lib/cli/src/commands/app/mod.rs index e41b8eb7ab7..35c8336b4e2 100644 --- a/lib/cli/src/commands/app/mod.rs +++ b/lib/cli/src/commands/app/mod.rs @@ -7,6 +7,7 @@ pub mod get; pub mod info; pub mod list; pub mod logs; +pub mod purge_cache; pub mod version; mod util; @@ -16,15 +17,16 @@ use crate::commands::AsyncCliCommand; /// Manage Wasmer Deploy apps. #[derive(clap::Subcommand, Debug)] pub enum CmdApp { + Deploy(deploy::CmdAppDeploy), + Create(create::CmdAppCreate), Get(get::CmdAppGet), Info(info::CmdAppInfo), List(list::CmdAppList), Logs(logs::CmdAppLogs), - Create(create::CmdAppCreate), + PurgeCache(purge_cache::CmdAppPurgeCache), Delete(delete::CmdAppDelete), #[clap(subcommand)] Version(version::CmdAppVersion), - Deploy(deploy::CmdAppDeploy), } #[async_trait::async_trait] @@ -50,6 +52,7 @@ impl AsyncCliCommand for CmdApp { Self::Delete(cmd) => cmd.run_async().await, Self::Version(cmd) => cmd.run_async().await, Self::Deploy(cmd) => cmd.run_async().await, + Self::PurgeCache(cmd) => cmd.run_async().await, } } } diff --git a/lib/cli/src/commands/app/purge_cache.rs b/lib/cli/src/commands/app/purge_cache.rs new file mode 100644 index 00000000000..79a20fea57e --- /dev/null +++ b/lib/cli/src/commands/app/purge_cache.rs @@ -0,0 +1,54 @@ +//! Get information about an edge app. + +use super::util::AppIdentOpts; +use crate::{ + commands::AsyncCliCommand, + opts::{ApiOpts, ItemFormatOpts}, +}; + +/// Purge caches for applications. +/// +/// Cache scopes that can be cleared: +/// * InstaBoot startup snapshots +/// Will delete all existing snapshots. +/// New snapshots will be created automatically. +#[derive(clap::Parser, Debug)] +pub struct CmdAppPurgeCache { + #[clap(flatten)] + #[allow(missing_docs)] + pub api: ApiOpts, + #[clap(flatten)] + #[allow(missing_docs)] + pub fmt: ItemFormatOpts, + + #[clap(flatten)] + #[allow(missing_docs)] + pub ident: AppIdentOpts, +} + +#[async_trait::async_trait] +impl AsyncCliCommand for CmdAppPurgeCache { + type Output = (); + + async fn run_async(self) -> Result<(), anyhow::Error> { + let client = self.api.client()?; + let (_ident, app) = self.ident.load_app(&client).await?; + + let version_id = app.active_version.id; + + let name = format!("{} ({})", app.name, app.owner.global_name); + + println!( + "Purging caches for {}, app version {}...", + name, + version_id.inner() + ); + + let vars = wasmer_api::types::PurgeCacheForAppVersionVars { id: version_id }; + wasmer_api::query::purge_cache_for_app_version(&client, vars).await?; + + println!("🚽 swirl! All caches have been purged!"); + + Ok(()) + } +} diff --git a/lib/cli/src/commands/app/util.rs b/lib/cli/src/commands/app/util.rs index e7b6f44041b..514f0c286be 100644 --- a/lib/cli/src/commands/app/util.rs +++ b/lib/cli/src/commands/app/util.rs @@ -112,6 +112,9 @@ pub fn get_app_config_from_current_dir() -> Result<(AppConfigV1, std::path::Path /// /// Provides convenience methods for resolving an app identifier or loading it /// from a local app.yaml. +/// +/// NOTE: this is a separate struct to prevent the need for copy-pasting the +/// field docs #[derive(clap::Parser, Debug)] pub struct AppIdentOpts { /// Identifier of the application. @@ -123,7 +126,7 @@ pub struct AppIdentOpts { /// - namespace/app-name /// - app-alias /// - App ID - pub app_ident: Option, + pub app: Option, } // Allowing because this is not performance-critical at all. @@ -148,7 +151,7 @@ impl ResolvedAppIdent { impl AppIdentOpts { pub fn resolve_static(&self) -> Result { - if let Some(id) = &self.app_ident { + if let Some(id) = &self.app { return Ok(ResolvedAppIdent::Ident(id.clone())); }