diff --git a/Cargo.lock b/Cargo.lock index 2a8d514602..a7470fa9e7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1488,7 +1488,6 @@ dependencies = [ "lazy_static", "libc", "portpicker", - "protobuf", "reqwest", "rivet-api-builder", "rivet-config", @@ -3860,12 +3859,6 @@ dependencies = [ "prost", ] -[[package]] -name = "protobuf" -version = "2.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94" - [[package]] name = "quanta" version = "0.12.6" diff --git a/Cargo.toml b/Cargo.toml index dd8b093c0f..9e2a7facdc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,7 +52,6 @@ papaya = "0.2.1" pest_derive = "2.7" portpicker = "0.1" prettyplease = "0.2" -protobuf = "2.28" quote = "1.0" rand = "0.8" regex = "1.4" diff --git a/engine/artifacts/openapi.json b/engine/artifacts/openapi.json index f0ce865757..373bab96c2 100644 --- a/engine/artifacts/openapi.json +++ b/engine/artifacts/openapi.json @@ -367,6 +367,27 @@ ] } }, + "/metadata": { + "delete": { + "tags": [ + "metadata" + ], + "summary": "Returns metadata about the API including runtime and version", + "operationId": "metadata_get", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MetadataGetResponse" + } + } + } + } + } + } + }, "/namespaces": { "get": { "tags": [ @@ -1253,6 +1274,45 @@ "error" ] }, + "MetadataGetResponse": { + "type": "object", + "required": [ + "runtime", + "version", + "git_sha", + "build_timestamp", + "rustc_version", + "rustc_host", + "cargo_target", + "cargo_profile" + ], + "properties": { + "build_timestamp": { + "type": "string" + }, + "cargo_profile": { + "type": "string" + }, + "cargo_target": { + "type": "string" + }, + "git_sha": { + "type": "string" + }, + "runtime": { + "type": "string" + }, + "rustc_host": { + "type": "string" + }, + "rustc_version": { + "type": "string" + }, + "version": { + "type": "string" + } + } + }, "Namespace": { "type": "object", "required": [ diff --git a/engine/docker/engine/linux-aarch64.Dockerfile b/engine/docker/engine/linux-aarch64.Dockerfile index 54d3e8069b..42924ece09 100644 --- a/engine/docker/engine/linux-aarch64.Dockerfile +++ b/engine/docker/engine/linux-aarch64.Dockerfile @@ -13,7 +13,6 @@ RUN apt-get update && apt-get install -y \ clang-14 \ libssl-dev \ pkg-config \ - protobuf-compiler \ ca-certificates \ g++ \ git-lfs \ diff --git a/engine/docker/engine/linux-x86_64.Dockerfile b/engine/docker/engine/linux-x86_64.Dockerfile index a2c2dde596..57841a4d02 100644 --- a/engine/docker/engine/linux-x86_64.Dockerfile +++ b/engine/docker/engine/linux-x86_64.Dockerfile @@ -13,7 +13,6 @@ RUN apt-get update && apt-get install -y \ clang-14 \ libssl-dev \ pkg-config \ - protobuf-compiler \ ca-certificates \ g++ \ g++-multilib \ diff --git a/engine/docker/engine/macos-aarch64.Dockerfile b/engine/docker/engine/macos-aarch64.Dockerfile index 4b08efde00..b4ba8c6252 100644 --- a/engine/docker/engine/macos-aarch64.Dockerfile +++ b/engine/docker/engine/macos-aarch64.Dockerfile @@ -7,7 +7,6 @@ ARG VITE_APP_API_URL=__SAME__ # Install dependencies RUN apt-get update && apt-get install -y \ git-lfs \ - protobuf-compiler \ clang \ cmake \ patch \ diff --git a/engine/docker/engine/macos-x86_64.Dockerfile b/engine/docker/engine/macos-x86_64.Dockerfile index 5e38886bb2..3a803aaac2 100644 --- a/engine/docker/engine/macos-x86_64.Dockerfile +++ b/engine/docker/engine/macos-x86_64.Dockerfile @@ -7,7 +7,6 @@ ARG VITE_APP_API_URL=__SAME__ # Install dependencies RUN apt-get update && apt-get install -y \ git-lfs \ - protobuf-compiler \ clang \ cmake \ patch \ diff --git a/engine/docker/engine/windows.Dockerfile b/engine/docker/engine/windows.Dockerfile index e4650e2fc4..ff5ed7218d 100644 --- a/engine/docker/engine/windows.Dockerfile +++ b/engine/docker/engine/windows.Dockerfile @@ -10,7 +10,6 @@ RUN apt-get update && apt-get install -y \ libclang-14-dev \ clang-14 \ git-lfs \ - protobuf-compiler \ gcc-mingw-w64-x86-64 \ g++-mingw-w64-x86-64 \ binutils-mingw-w64-x86-64 \ diff --git a/engine/docker/universal/Dockerfile b/engine/docker/universal/Dockerfile index 60bcbaa777..b221a62f07 100644 --- a/engine/docker/universal/Dockerfile +++ b/engine/docker/universal/Dockerfile @@ -21,7 +21,6 @@ RUN apt-get update -y && \ libpq-dev \ libssl-dev \ pkg-config \ - protobuf-compiler \ ca-certificates \ gpg \ openssl \ diff --git a/engine/packages/api-peer/src/actors/delete.rs b/engine/packages/api-peer/src/actors/delete.rs index afb5c3486c..28961420f7 100644 --- a/engine/packages/api-peer/src/actors/delete.rs +++ b/engine/packages/api-peer/src/actors/delete.rs @@ -23,16 +23,16 @@ pub struct DeletePath { } #[utoipa::path( - delete, + delete, operation_id = "actors_delete", - path = "/actors/{actor_id}", - params( - ("actor_id" = Id, Path), - DeleteQuery, - ), - responses( - (status = 200, body = DeleteResponse), - ), + path = "/actors/{actor_id}", + params( + ("actor_id" = Id, Path), + DeleteQuery, + ), + responses( + (status = 200, body = DeleteResponse), + ), )] #[tracing::instrument(skip_all)] pub async fn delete(ctx: ApiCtx, path: DeletePath, query: DeleteQuery) -> Result { diff --git a/engine/packages/api-peer/src/actors/list.rs b/engine/packages/api-peer/src/actors/list.rs index 6291e58caf..b8f1636dba 100644 --- a/engine/packages/api-peer/src/actors/list.rs +++ b/engine/packages/api-peer/src/actors/list.rs @@ -3,13 +3,13 @@ use rivet_api_builder::ApiCtx; use rivet_api_types::{actors::list::*, pagination::Pagination}; #[utoipa::path( - get, + get, operation_id = "actors_list", - path = "/actors", - params(ListQuery), - responses( - (status = 200, body = ListResponse), - ), + path = "/actors", + params(ListQuery), + responses( + (status = 200, body = ListResponse), + ), )] #[tracing::instrument(skip_all)] pub async fn list(ctx: ApiCtx, _path: (), query: ListQuery) -> Result { diff --git a/engine/packages/api-peer/src/actors/list_names.rs b/engine/packages/api-peer/src/actors/list_names.rs index f6122278bf..d53722d27b 100644 --- a/engine/packages/api-peer/src/actors/list_names.rs +++ b/engine/packages/api-peer/src/actors/list_names.rs @@ -4,13 +4,13 @@ use rivet_api_types::{actors::list_names::*, pagination::Pagination}; use rivet_types::actors::ActorName; #[utoipa::path( - get, + get, operation_id = "actors_list_names", - path = "/actors/names", - params(ListNamesQuery), - responses( - (status = 200, body = ListNamesResponse), - ), + path = "/actors/names", + params(ListNamesQuery), + responses( + (status = 200, body = ListNamesResponse), + ), )] #[tracing::instrument(skip_all)] pub async fn list_names( diff --git a/engine/packages/api-peer/src/runners.rs b/engine/packages/api-peer/src/runners.rs index 2adbbee834..f398ecfde7 100644 --- a/engine/packages/api-peer/src/runners.rs +++ b/engine/packages/api-peer/src/runners.rs @@ -5,13 +5,13 @@ use serde::{Deserialize, Serialize}; use utoipa::{IntoParams, ToSchema}; #[utoipa::path( - get, + get, operation_id = "runners_list", - path = "/runners", - params(ListQuery), - responses( - (status = 200, body = ListResponse), - ), + path = "/runners", + params(ListQuery), + responses( + (status = 200, body = ListResponse), + ), )] #[tracing::instrument(skip_all)] pub async fn list(ctx: ApiCtx, _path: (), query: ListQuery) -> Result { diff --git a/engine/packages/api-public/src/actors/create.rs b/engine/packages/api-public/src/actors/create.rs index e7d9a9eec2..3d5c1d3103 100644 --- a/engine/packages/api-public/src/actors/create.rs +++ b/engine/packages/api-public/src/actors/create.rs @@ -35,14 +35,14 @@ pub struct CreateQuery { /// /// actor::get will always be in the same datacenter. #[utoipa::path( - post, + post, operation_id = "actors_create", - path = "/actors", - params(CreateQuery), - request_body(content = CreateRequest, content_type = "application/json"), - responses( - (status = 200, body = CreateResponse), - ), + path = "/actors", + params(CreateQuery), + request_body(content = CreateRequest, content_type = "application/json"), + responses( + (status = 200, body = CreateResponse), + ), )] pub async fn create( Extension(ctx): Extension, diff --git a/engine/packages/api-public/src/actors/delete.rs b/engine/packages/api-public/src/actors/delete.rs index 543f8ba0f9..e433a8edd2 100644 --- a/engine/packages/api-public/src/actors/delete.rs +++ b/engine/packages/api-public/src/actors/delete.rs @@ -34,16 +34,16 @@ pub struct DeleteResponse {} /// - DELETE /actors/{} /// - [api-peer] namespace::ops::resolve_for_name_global #[utoipa::path( - delete, + delete, operation_id = "actors_delete", - path = "/actors/{actor_id}", - params( - ("actor_id" = Id, Path), - DeleteQuery, - ), - responses( - (status = 200, body = DeleteResponse), - ), + path = "/actors/{actor_id}", + params( + ("actor_id" = Id, Path), + DeleteQuery, + ), + responses( + (status = 200, body = DeleteResponse), + ), security(("bearer_auth" = [])), )] #[tracing::instrument(skip_all)] diff --git a/engine/packages/api-public/src/actors/get_or_create.rs b/engine/packages/api-public/src/actors/get_or_create.rs index 3fd6071442..1c560536a4 100644 --- a/engine/packages/api-public/src/actors/get_or_create.rs +++ b/engine/packages/api-public/src/actors/get_or_create.rs @@ -63,14 +63,14 @@ pub struct GetOrCreateResponse { /// /// ## Optimized Alternative Routes #[utoipa::path( - put, + put, operation_id = "actors_get_or_create", - path = "/actors", - params(GetOrCreateQuery), - request_body(content = GetOrCreateRequest, content_type = "application/json"), - responses( - (status = 200, body = GetOrCreateResponse), - ), + path = "/actors", + params(GetOrCreateQuery), + request_body(content = GetOrCreateRequest, content_type = "application/json"), + responses( + (status = 200, body = GetOrCreateResponse), + ), )] pub async fn get_or_create( Extension(ctx): Extension, diff --git a/engine/packages/api-public/src/actors/list.rs b/engine/packages/api-public/src/actors/list.rs index 4aedf36583..34ce2cbb79 100644 --- a/engine/packages/api-public/src/actors/list.rs +++ b/engine/packages/api-public/src/actors/list.rs @@ -55,13 +55,13 @@ pub struct ListResponse { /// /// ## Optimized Alternative Routes #[utoipa::path( - get, + get, operation_id = "actors_list", - path = "/actors", - params(ListQuery), - responses( - (status = 200, body = ListResponse), - ), + path = "/actors", + params(ListQuery), + responses( + (status = 200, body = ListResponse), + ), )] pub async fn list(Extension(ctx): Extension, Query(query): Query) -> Response { match list_inner(ctx, query).await { diff --git a/engine/packages/api-public/src/actors/list_names.rs b/engine/packages/api-public/src/actors/list_names.rs index a98742be19..d68240816a 100644 --- a/engine/packages/api-public/src/actors/list_names.rs +++ b/engine/packages/api-public/src/actors/list_names.rs @@ -16,13 +16,13 @@ use crate::ctx::ApiCtx; /// - GET /actors/names (fanout) /// - [api-peer] namespace::ops::resolve_for_name_global #[utoipa::path( - get, + get, operation_id = "actors_list_names", - path = "/actors/names", - params(ListNamesQuery), - responses( - (status = 200, body = ListNamesResponse), - ), + path = "/actors/names", + params(ListNamesQuery), + responses( + (status = 200, body = ListNamesResponse), + ), security(("bearer_auth" = [])), )] #[tracing::instrument(skip_all)] diff --git a/engine/packages/api-public/src/datacenters.rs b/engine/packages/api-public/src/datacenters.rs index ea1013353b..9221c18b16 100644 --- a/engine/packages/api-public/src/datacenters.rs +++ b/engine/packages/api-public/src/datacenters.rs @@ -7,12 +7,12 @@ use rivet_types::datacenters::Datacenter; use crate::ctx::ApiCtx; #[utoipa::path( - get, + get, operation_id = "datacenters_list", - path = "/datacenters", - responses( - (status = 200, body = ListResponse), - ), + path = "/datacenters", + responses( + (status = 200, body = ListResponse), + ), security(("bearer_auth" = [])), )] #[tracing::instrument(skip_all)] diff --git a/engine/packages/api-public/src/metadata.rs b/engine/packages/api-public/src/metadata.rs index 1a06f32376..6cc0034306 100644 --- a/engine/packages/api-public/src/metadata.rs +++ b/engine/packages/api-public/src/metadata.rs @@ -1,24 +1,54 @@ -use axum::Json; -use axum::response::IntoResponse; +use anyhow::Result; +use axum::response::{IntoResponse, Json, Response}; +use rivet_api_builder::ApiError; use rivet_api_builder::extract::Extension; use rivet_util::build_meta; -use serde_json::json; +use serde::Serialize; +use utoipa::ToSchema; use crate::ctx::ApiCtx; +#[derive(Serialize, ToSchema)] +#[schema(as = MetadataGetResponse)] +pub struct GetResponse { + runtime: String, + version: String, + git_sha: String, + build_timestamp: String, + rustc_version: String, + rustc_host: String, + cargo_target: String, + cargo_profile: String, +} + /// Returns metadata about the API including runtime and version +#[utoipa::path( + delete, + operation_id = "metadata_get", + path = "/metadata", + responses( + (status = 200, body = GetResponse), + ), +)] #[tracing::instrument(skip_all)] -pub async fn get_metadata(Extension(ctx): Extension) -> impl IntoResponse { +pub async fn get(Extension(ctx): Extension) -> Response { + match get_inner(ctx).await { + Ok(response) => Json(response).into_response(), + Err(err) => ApiError::from(err).into_response(), + } +} + +pub async fn get_inner(ctx: ApiCtx) -> Result { ctx.skip_auth(); - Json(json!({ - "runtime": build_meta::RUNTIME, - "version": build_meta::VERSION, - "git_sha": build_meta::GIT_SHA, - "build_timestamp": build_meta::BUILD_TIMESTAMP, - "rustc_version": build_meta::RUSTC_VERSION, - "rustc_host": build_meta::RUSTC_HOST, - "cargo_target": build_meta::CARGO_TARGET, - "cargo_profile": build_meta::cargo_profile() - })) + Ok(GetResponse { + runtime: build_meta::RUNTIME.to_string(), + version: build_meta::VERSION.to_string(), + git_sha: build_meta::GIT_SHA.to_string(), + build_timestamp: build_meta::BUILD_TIMESTAMP.to_string(), + rustc_version: build_meta::RUSTC_VERSION.to_string(), + rustc_host: build_meta::RUSTC_HOST.to_string(), + cargo_target: build_meta::CARGO_TARGET.to_string(), + cargo_profile: build_meta::cargo_profile().to_string(), + }) } diff --git a/engine/packages/api-public/src/namespaces.rs b/engine/packages/api-public/src/namespaces.rs index a27446ad40..b17eeb098e 100644 --- a/engine/packages/api-public/src/namespaces.rs +++ b/engine/packages/api-public/src/namespaces.rs @@ -11,13 +11,13 @@ use rivet_api_util::request_remote_datacenter; use crate::ctx::ApiCtx; #[utoipa::path( - get, + get, operation_id = "namespaces_list", - path = "/namespaces", - params(ListQuery), - responses( - (status = 200, body = ListResponse), - ), + path = "/namespaces", + params(ListQuery), + responses( + (status = 200, body = ListResponse), + ), security(("bearer_auth" = [])), )] #[tracing::instrument(skip_all)] @@ -48,13 +48,13 @@ async fn list_inner(ctx: ApiCtx, query: ListQuery) -> Result { } #[utoipa::path( - post, + post, operation_id = "namespaces_create", - path = "/namespaces", + path = "/namespaces", request_body(content = CreateRequest, content_type = "application/json"), - responses( - (status = 200, body = CreateResponse), - ), + responses( + (status = 200, body = CreateResponse), + ), security(("bearer_auth" = [])), )] #[tracing::instrument(skip_all)] diff --git a/engine/packages/api-public/src/router.rs b/engine/packages/api-public/src/router.rs index 2b71b35c9b..39a13707c2 100644 --- a/engine/packages/api-public/src/router.rs +++ b/engine/packages/api-public/src/router.rs @@ -30,12 +30,13 @@ use crate::{actors, ctx, datacenters, health, metadata, namespaces, runner_confi runner_configs::refresh_metadata::refresh_metadata, datacenters::list, health::fanout, + metadata::get, ), components( schemas(rivet_types::keys::namespace::runner_config::RunnerConfigVariant) ), security( ("bearer_auth" = []) ), - modifiers(&SecurityAddon), + modifiers(&SecurityAddon), )] pub struct ApiDoc; @@ -53,7 +54,7 @@ pub async fn router( axum::routing::get(|| async { Redirect::permanent("/ui/") }), ) // MARK: Metadata - .route("/metadata", axum::routing::get(metadata::get_metadata)) + .route("/metadata", axum::routing::get(metadata::get)) // MARK: Namespaces .route("/namespaces", axum::routing::get(namespaces::list)) .route("/namespaces", axum::routing::post(namespaces::create)) diff --git a/engine/packages/api-public/src/runners.rs b/engine/packages/api-public/src/runners.rs index 63455587e2..b29533b652 100644 --- a/engine/packages/api-public/src/runners.rs +++ b/engine/packages/api-public/src/runners.rs @@ -12,13 +12,13 @@ use utoipa::{IntoParams, ToSchema}; use crate::ctx::ApiCtx; #[utoipa::path( - get, + get, operation_id = "runners_list", - path = "/runners", - params(ListQuery), - responses( - (status = 200, body = ListResponse), - ), + path = "/runners", + params(ListQuery), + responses( + (status = 200, body = ListResponse), + ), security(("bearer_auth" = [])), )] #[tracing::instrument(skip_all)] diff --git a/engine/packages/epoxy/Cargo.toml b/engine/packages/epoxy/Cargo.toml index 5acd9ecc8b..3ef3bea138 100644 --- a/engine/packages/epoxy/Cargo.toml +++ b/engine/packages/epoxy/Cargo.toml @@ -14,7 +14,6 @@ gas.workspace = true epoxy-protocol.workspace = true futures-util.workspace = true lazy_static.workspace = true -protobuf.workspace = true reqwest.workspace = true rivet-api-builder.workspace = true rivet-config.workspace = true diff --git a/engine/packages/gasoline/src/signal.rs b/engine/packages/gasoline/src/signal.rs index 215d66081a..f67b20608c 100644 --- a/engine/packages/gasoline/src/signal.rs +++ b/engine/packages/gasoline/src/signal.rs @@ -46,20 +46,20 @@ macro_rules! join_signal { join_signal!(@ $vis $join [] [] $($tt)*); }; (@ - $vis:vis $join:ident - [$({ $names:tt } { $types:tt })*] - [$({ $just_types:tt })*] + $vis:vis $join:ident + [$({ $names:tt } { $types:tt })*] + [$({ $just_types:tt })*] ) => { - $vis enum $join { + $vis enum $join { $( $names ($types) ),* } - #[async_trait::async_trait] + #[async_trait::async_trait] impl Listen for $join { #[tracing::instrument(skip_all, fields(t=std::any::type_name::()))] async fn listen(ctx: &mut gas::prelude::ListenCtx) -> gas::prelude::WorkflowResult { let row = ctx.listen_any(&[ - $(<$just_types as gas::signal::Signal>::NAME),* + $(<$just_types as gas::signal::Signal>::NAME),* ]).await?; Self::parse(&row.signal_name, &row.body) @@ -67,7 +67,7 @@ macro_rules! join_signal { fn parse(name: &str, body: &serde_json::value::RawValue) -> gas::prelude::WorkflowResult { $( - if name == <$types as gas::signal::Signal>::NAME { + if name == <$types as gas::signal::Signal>::NAME { std::result::Result::Ok( Self::$names( serde_json::from_str(body.get()) @@ -84,33 +84,33 @@ macro_rules! join_signal { } } } - }; + }; (@ - $vis:vis $join:ident - [$({ $names:tt } { $types:tt })*] - [$({ $just_types:tt })*] - $name:ident, - $($tail:tt)* + $vis:vis $join:ident + [$({ $names:tt } { $types:tt })*] + [$({ $just_types:tt })*] + $name:ident, + $($tail:tt)* ) => { join_signal!(@ - $vis $join - [$( { $names } { $types } )* { $name } { $name }] - [$( { $just_types } )* { $name }] - $($tail)* + $vis $join + [$( { $names } { $types } )* { $name } { $name }] + [$( { $just_types } )* { $name }] + $($tail)* ); }; (@ - $vis:vis $join:ident - [$({ $names:tt } { $types:tt })*] - [$({ $just_types:tt })*] - $name:ident($ty:ty), - $($tail:tt)* + $vis:vis $join:ident + [$({ $names:tt } { $types:tt })*] + [$({ $just_types:tt })*] + $name:ident($ty:ty), + $($tail:tt)* ) => { join_signal!(@ - $vis $join - [$( { $names } { $types } )* { $name } { $ty }] - [$( { $just_types } )* { $ty }] - $($tail)* + $vis $join + [$( { $names } { $types } )* { $name } { $ty }] + [$( { $just_types } )* { $ty }] + $($tail)* ); }; } diff --git a/engine/packages/universaldb/src/utils/cherry_pick.rs b/engine/packages/universaldb/src/utils/cherry_pick.rs index 51a6262fbc..96662017b3 100644 --- a/engine/packages/universaldb/src/utils/cherry_pick.rs +++ b/engine/packages/universaldb/src/utils/cherry_pick.rs @@ -21,60 +21,60 @@ pub trait CherryPick { // Implements `CherryPick` for any tuple size macro_rules! impl_tuple { - ($($args:ident),*) => { - #[async_trait::async_trait] - impl<$($args: FormalKey + for<'de> TupleUnpack<'de>),*> CherryPick for ($($args),*) - where - $($args::Value: Send),* - { - type Output = ($($args::Value),*); + ($($args:ident),*) => { + #[async_trait::async_trait] + impl<$($args: FormalKey + for<'de> TupleUnpack<'de>),*> CherryPick for ($($args),*) + where + $($args::Value: Send),* + { + type Output = ($($args::Value),*); - async fn cherry_pick( - tx: &Transaction, - subspace: S, - isolation_level: IsolationLevel, - ) -> Result { - let tx = tx.with_subspace(Subspace::new(&subspace)); + async fn cherry_pick( + tx: &Transaction, + subspace: S, + isolation_level: IsolationLevel, + ) -> Result { + let tx = tx.with_subspace(Subspace::new(&subspace)); - let mut stream = tx.read_range( - $crate::range_option::RangeOption { - mode: StreamingMode::WantAll, - ..(&Subspace::all()).into() - }, - isolation_level, - ); + let mut stream = tx.read_range( + $crate::range_option::RangeOption { + mode: StreamingMode::WantAll, + ..(&Subspace::all()).into() + }, + isolation_level, + ); - $( + $( #[allow(non_snake_case)] - let mut $args = None; - )* + let mut $args = None; + )* - loop { - let Some(entry) = stream.try_next().await? else { - break; - }; + loop { + let Some(entry) = stream.try_next().await? else { + break; + }; - $( - if let Ok(key) = tx.unpack::<$args>(entry.key()) { - ensure!($args.is_none(), "{} already picked", std::any::type_name::<$args>()); + $( + if let Ok(key) = tx.unpack::<$args>(entry.key()) { + ensure!($args.is_none(), "{} already picked", std::any::type_name::<$args>()); - let value = key.deserialize(entry.value())?; - $args = Some(value); - continue; - } - )* - } + let value = key.deserialize(entry.value())?; + $args = Some(value); + continue; + } + )* + } - Ok(( - $( - $args.with_context(|| { - format!("key not found in cherry pick: {}", std::any::type_name::<$args>()) - })?, - )* - )) - } - } - } + Ok(( + $( + $args.with_context(|| { + format!("key not found in cherry pick: {}", std::any::type_name::<$args>()) + })?, + )* + )) + } + } + } } impl_tuple!(A, B);