diff --git a/engine/packages/guard-core/src/response_body.rs b/engine/packages/guard-core/src/response_body.rs index 40fda95a7b..9a3e28dbc7 100644 --- a/engine/packages/guard-core/src/response_body.rs +++ b/engine/packages/guard-core/src/response_body.rs @@ -45,7 +45,8 @@ pub enum ResponseBody { } impl ResponseBody { - pub(crate) fn with_completion(self, callback: impl FnOnce() + Send + 'static) -> Self { + #[doc(hidden)] + pub fn with_completion(self, callback: impl FnOnce() + Send + 'static) -> Self { Self::WithCompletion { body: Box::new(self), completion: CompletionGuard(Some(Box::new(callback))), diff --git a/engine/packages/pegboard-gateway2/src/http_stream/handler.rs b/engine/packages/pegboard-gateway2/src/http_stream/handler.rs index 8e40965634..fccfc69ea6 100644 --- a/engine/packages/pegboard-gateway2/src/http_stream/handler.rs +++ b/engine/packages/pegboard-gateway2/src/http_stream/handler.rs @@ -1,4 +1,11 @@ -use std::{collections::HashMap, time::Duration}; +use std::{ + collections::HashMap, + sync::{ + Arc, + atomic::{AtomicU64, Ordering}, + }, + time::Duration, +}; use anyhow::{Result, anyhow}; use bytes::Bytes; @@ -11,7 +18,7 @@ use rivet_guard_core::{ errors::{ActorStoppedWhileWaiting, InvalidRequestBody}, request_context::RequestContext, }; -use tokio::sync::mpsc; +use tokio::sync::{mpsc, watch}; use tracing::Instrument; use super::{ @@ -24,7 +31,7 @@ use super::{ send_http_request_abort, }; use crate::{ - PegboardGateway2, + PegboardGateway2, metrics_task, request_metrics::{RequestKind, RequestMetrics}, shared_state::{InFlightRequestCtx, RequestProtocol, RequestStopResult}, }; @@ -42,10 +49,8 @@ impl PegboardGateway2 { B::Error: std::error::Error + Send + Sync + 'static, { let ctx = self.ctx.with_ray(req_ctx.ray_id(), req_ctx.req_id())?; - let req_body_size_hint = req.body().size_hint(); - let ingress_size_hint = req_body_size_hint - .upper() - .unwrap_or(req_body_size_hint.lower()) as usize; + let ingress_bytes = Arc::new(AtomicU64::new(0)); + let egress_bytes = Arc::new(AtomicU64::new(0)); let request_metrics = RequestMetrics::new( ctx.clone(), self.actor_id, @@ -53,19 +58,54 @@ impl PegboardGateway2 { self.envoy_key.clone(), RequestKind::Http, ); + let (metrics_abort_tx, metrics_abort_rx) = watch::channel(()); + let transfer_metrics = request_metrics.clone(); + let transfer_ingress_bytes = ingress_bytes.clone(); + let transfer_egress_bytes = egress_bytes.clone(); + tokio::spawn( + async move { + if let Err(error) = metrics_task::task( + transfer_metrics, + transfer_ingress_bytes, + transfer_egress_bytes, + metrics_abort_rx, + ) + .await + { + tracing::error!(?error, "HTTP transfer metrics task failed"); + } + } + .in_current_span(), + ); let (res, active_metrics) = tokio::join!( - self.handle_request_inner(&ctx, req, req_ctx), - request_metrics.begin(ingress_size_hint), + self.handle_request_inner( + &ctx, + req, + req_ctx, + ingress_bytes.clone(), + egress_bytes.clone(), + ), + request_metrics.begin(0), ); - let egress_size_hint = res - .as_ref() - .map(|res| res.size_hint().upper().unwrap_or(res.size_hint().lower()) as usize) - .unwrap_or_default(); - active_metrics.finish_in_background(egress_size_hint); - - res + match res { + Ok(response) => { + let (parts, body) = response.into_parts(); + Ok(Response::from_parts( + parts, + body.with_completion(move || { + let _ = metrics_abort_tx.send(()); + active_metrics.finish_in_background(0); + }), + )) + } + Err(error) => { + let _ = metrics_abort_tx.send(()); + active_metrics.finish_in_background(0); + Err(error) + } + } } async fn handle_request_inner( @@ -73,6 +113,8 @@ impl PegboardGateway2 { ctx: &StandaloneCtx, req: Request, req_ctx: &mut RequestContext, + ingress_bytes: Arc, + egress_bytes: Arc, ) -> Result> where B: Body + Unpin, @@ -119,6 +161,7 @@ impl PegboardGateway2 { None, ) }; + ingress_bytes.fetch_add(body_bytes.len() as u64, Ordering::AcqRel); let mut stopped_sub = ctx .subscribe::(("actor_id", self.actor_id)) @@ -222,6 +265,7 @@ impl PegboardGateway2 { request_id, body, max_request_body_size, + ingress_bytes, response_start_deadline, response_start_timeout, ) @@ -273,6 +317,7 @@ impl PegboardGateway2 { expected_message_index, self.actor_id, idle_timeout, + egress_bytes, ) .in_current_span(), ); @@ -280,6 +325,7 @@ impl PegboardGateway2 { response_builder.body(ResponseBody::Channel(body_rx))? } else { let body = response_start.body.unwrap_or_default(); + egress_bytes.fetch_add(body.len() as u64, Ordering::AcqRel); let response = response_builder.body(ResponseBody::Full(Full::new(Bytes::from(body))))?; diff --git a/engine/packages/pegboard-gateway2/src/http_stream/request.rs b/engine/packages/pegboard-gateway2/src/http_stream/request.rs index 74b5b2a487..d1faf2c80b 100644 --- a/engine/packages/pegboard-gateway2/src/http_stream/request.rs +++ b/engine/packages/pegboard-gateway2/src/http_stream/request.rs @@ -8,7 +8,13 @@ use rivet_guard_core::errors::{ ActorStoppedWhileWaiting, GatewayResponseStartTimeout, InvalidRequestBody, TunnelMessageTimeout, TunnelRequestAborted, TunnelResponseClosed, }; -use std::time::Duration; +use std::{ + sync::{ + Arc, + atomic::{AtomicU64, Ordering}, + }, + time::Duration, +}; use tokio::sync::{mpsc, watch}; use crate::shared_state::{InFlightRequestHandle, InFlightTunnelMessage, MsgGcReason}; @@ -64,6 +70,7 @@ async fn send_streaming_http_request_body_chunks( in_flight_req: &InFlightRequestHandle, mut body: B, max_body_size: usize, + ingress_bytes: Arc, ) -> Result<()> where B: Body + Unpin, @@ -85,7 +92,12 @@ where frame = body.frame() => frame, _ = tokio::time::sleep_until(deadline) => { if let Some(chunk) = chunker.flush() { - send_http_request_body_chunk(in_flight_req, chunk, false).await?; + send_http_request_body_chunk( + in_flight_req, + chunk, + false, + ) + .await?; } flush_deadline = None; continue; @@ -112,6 +124,7 @@ where let Ok(data) = frame.into_data() else { continue; }; + ingress_bytes.fetch_add(data.len() as u64, Ordering::AcqRel); let Some(next_body_size) = next_request_body_size(body_size, data.len(), max_body_size) else { super::send_http_request_abort( @@ -240,6 +253,7 @@ pub(super) async fn stream_http_request_and_wait_for_response( request_id: protocol::RequestId, body: B, max_body_size: usize, + ingress_bytes: Arc, response_start_deadline: tokio::time::Instant, response_start_timeout: Duration, ) -> Result<(protocol::MessageId, protocol::ToRivetResponseStart)> @@ -250,7 +264,8 @@ where // Upload ingress, cumulative byte accounting, and bounded-latency // coalescing run in one future. Response start/abort is observed // concurrently so a slow or rejected upload cannot retain the request. - let upload = send_streaming_http_request_body_chunks(in_flight_req, body, max_body_size); + let upload = + send_streaming_http_request_body_chunks(in_flight_req, body, max_body_size, ingress_bytes); tokio::pin!(upload); tokio::select! { upload_result = &mut upload => { diff --git a/engine/packages/pegboard-gateway2/src/http_stream/response.rs b/engine/packages/pegboard-gateway2/src/http_stream/response.rs index c7c90094a6..3f3af352e4 100644 --- a/engine/packages/pegboard-gateway2/src/http_stream/response.rs +++ b/engine/packages/pegboard-gateway2/src/http_stream/response.rs @@ -1,6 +1,10 @@ use bytes::Bytes; use gas::prelude::*; use rivet_envoy_protocol as protocol; +use std::sync::{ + Arc, + atomic::{AtomicU64, Ordering}, +}; use std::time::Duration; use tokio::sync::{mpsc, watch}; @@ -31,10 +35,12 @@ async fn send_http_response_body_bytes( actor_id: Id, body: Vec, detail: &'static str, + egress_bytes: &AtomicU64, ) -> bool { let body = Bytes::from(body); for offset in (0..body.len()).step_by(HTTP_BODY_CHUNK_SIZE) { let chunk = body.slice(offset..(offset + HTTP_BODY_CHUNK_SIZE).min(body.len())); + let chunk_len = chunk.len(); let delivery = tokio::select! { biased; _ = body_tx.closed() => Err((RequestStopResult::ClientDisconnect, detail.to_owned())), @@ -84,6 +90,7 @@ async fn send_http_response_body_bytes( in_flight_req.stop(stop_result).await; return false; } + egress_bytes.fetch_add(chunk_len as u64, Ordering::AcqRel); } true @@ -99,6 +106,7 @@ pub(super) async fn drain_http_response_stream( mut expected_message_index: protocol::MessageIndex, actor_id: Id, idle_timeout: Option, + egress_bytes: Arc, ) { if let Some(body) = initial_body.filter(|body| !body.is_empty()) { if !send_http_response_body_bytes( @@ -109,6 +117,7 @@ pub(super) async fn drain_http_response_stream( actor_id, body, "client dropped response before initial body was sent", + &egress_bytes, ) .await { @@ -159,6 +168,7 @@ pub(super) async fn drain_http_response_stream( actor_id, chunk.body, "client dropped streaming response body", + &egress_bytes, ).await { return; } diff --git a/engine/packages/pegboard-gateway2/src/metrics_task.rs b/engine/packages/pegboard-gateway2/src/metrics_task.rs index 911282cbd7..8b2ab6f213 100644 --- a/engine/packages/pegboard-gateway2/src/metrics_task.rs +++ b/engine/packages/pegboard-gateway2/src/metrics_task.rs @@ -21,7 +21,7 @@ pub async fn task( _ = tokio::time::sleep(UPDATE_METRICS_INTERVAL) => {} _ = metrics_abort_rx.changed() => { // Record final values before abort - record_ws_transfer( + record_transfer( &metrics, &ingress_bytes, &egress_bytes, @@ -33,7 +33,7 @@ pub async fn task( } } - record_ws_transfer( + record_transfer( &metrics, &ingress_bytes, &egress_bytes, @@ -44,7 +44,7 @@ pub async fn task( } } -async fn record_ws_transfer( +async fn record_transfer( metrics: &RequestMetrics, ingress_bytes: &AtomicU64, egress_bytes: &AtomicU64, diff --git a/engine/sdks/rust/envoy-client/src/actor/http.rs b/engine/sdks/rust/envoy-client/src/actor/http.rs index a315cc1679..6228a3c184 100644 --- a/engine/sdks/rust/envoy-client/src/actor/http.rs +++ b/engine/sdks/rust/envoy-client/src/actor/http.rs @@ -215,16 +215,7 @@ pub(super) fn handle_req_chunk( ), }; tracing::warn!("streamed request body channel overloaded"); - if let Some(body_abort_tx) = pending.body_abort_tx.take() { - body_abort_tx.send_replace(Some(HttpRequestBodyError { - reason: reason.clone(), - })); - } - if let Some(task_abort_handle) = pending.task_abort_handle.take() { - task_abort_handle.abort(); - } - pending.body_tx = None; - pending.body_rejected = true; + reject_pending_request(pending, &reason); response_aborted = true; let shared = ctx.shared.clone(); @@ -258,6 +249,22 @@ pub(super) fn handle_req_chunk( } } +fn reject_pending_request( + pending: &mut PendingHttpRequest, + reason: &protocol::HttpStreamAbortReason, +) { + if let Some(body_abort_tx) = pending.body_abort_tx.take() { + body_abort_tx.send_replace(Some(HttpRequestBodyError { + reason: reason.clone(), + })); + } + if let Some(task_abort_handle) = pending.task_abort_handle.take() { + task_abort_handle.abort(); + } + pending.body_tx = None; + pending.body_rejected = true; +} + pub(super) fn handle_req_complete(ctx: &mut ActorContext, message_id: protocol::MessageId) { complete_phase(ctx, message_id, RequestPhase::Response); } diff --git a/engine/sdks/rust/envoy-client/tests/support/actor_http_stream.rs b/engine/sdks/rust/envoy-client/tests/support/actor_http_stream.rs index 39d529130e..d21b319df8 100644 --- a/engine/sdks/rust/envoy-client/tests/support/actor_http_stream.rs +++ b/engine/sdks/rust/envoy-client/tests/support/actor_http_stream.rs @@ -11,84 +11,16 @@ use tokio::task::yield_now; use super::http::ActiveHttpRequestGuard; use super::tests::{ StreamingCallbacks, TestCallbacks, actor_config, build_shared_context, message_id, - recv_ws_tunnel_msg, request_start, wait_for_stopped_event, wait_for_zero, + recv_ws_tunnel_msg, request_start, wait_for_zero, }; use super::{ToActor, create_actor, protocol}; use crate::{ async_counter::AsyncCounter, context::SharedActorEntry, handle::EnvoyHandle, - http::{HTTP_BODY_MAX_CHUNK_SIZE, HTTP_BODY_STREAM_CHANNEL_CAPACITY, ResponseChunk}, + http::{HTTP_BODY_MAX_CHUNK_SIZE, ResponseChunk}, }; -#[tokio::test] -async fn streamed_request_backpressure_does_not_block_actor_control_loop() { - let (fetch_started_tx, fetch_started_rx) = oneshot::channel(); - let (fetch_dropped_tx, fetch_dropped_rx) = oneshot::channel(); - let callbacks = Arc::new(TestCallbacks::hanging(fetch_started_tx, fetch_dropped_tx)); - let (shared, mut envoy_rx) = build_shared_context(callbacks); - let (ws_tx, mut ws_rx) = mpsc::unbounded_channel(); - *shared.ws_tx.lock().await = Some(ws_tx); - let (actor_tx, _) = create_actor( - shared, - "actor-streamed-request".to_string(), - 1, - actor_config(), - Vec::new(), - None, - ); - let mut request = request_start(); - request.method = "POST".to_owned(); - request.stream = true; - - actor_tx - .send(ToActor::ReqStart { - message_id: message_id(), - req: request, - }) - .expect("failed to send request start"); - fetch_started_rx - .await - .expect("fetch start sender dropped before request began"); - - for index in 0..=HTTP_BODY_STREAM_CHANNEL_CAPACITY { - let mut chunk_message_id = message_id(); - chunk_message_id.message_index = index as u16 + 1; - actor_tx - .send(ToActor::ReqChunk { - message_id: chunk_message_id, - chunk: protocol::ToEnvoyRequestChunk { - body: vec![index as u8], - finish: false, - }, - }) - .expect("failed to send streamed request chunk"); - } - - tokio::time::timeout(Duration::from_secs(2), fetch_dropped_rx) - .await - .expect("overloaded request did not cancel its handler") - .expect("fetch drop sender dropped"); - let abort = recv_ws_tunnel_msg(&mut ws_rx).await; - assert!(matches!( - abort.message_kind, - protocol::ToRivetTunnelMessageKind::ToRivetResponseAbort(protocol::ToRivetResponseAbort { - reason: protocol::HttpStreamAbortReason { - kind: protocol::HttpStreamAbortReasonKind::Overloaded, - .. - } - }) - )); - - actor_tx - .send(ToActor::Stop { - command_idx: 1, - reason: protocol::StopActorReason::StopIntent, - }) - .expect("failed to send stop after request overload"); - wait_for_stopped_event(&mut envoy_rx).await; -} - #[tokio::test] async fn streamed_request_remains_cancellable_after_upload_finishes() { let (fetch_started_tx, fetch_started_rx) = oneshot::channel(); diff --git a/engine/sdks/rust/envoy-protocol/schemas/v8.bare b/engine/sdks/rust/envoy-protocol/schemas/v8.bare new file mode 100644 index 0000000000..f0532a6abc --- /dev/null +++ b/engine/sdks/rust/envoy-protocol/schemas/v8.bare @@ -0,0 +1,696 @@ +# MARK: Core Primitives + +type Id str +type Json str + +type GatewayId data[4] +type RequestId data[4] +type MessageIndex u16 + +# MARK: KV + +# Basic types +type KvKey data +type KvValue data +type KvMetadata struct { + version: data + updateTs: i64 +} + +# Query types +type KvListAllQuery void +type KvListRangeQuery struct { + start: KvKey + end: KvKey + exclusive: bool +} + +type KvListPrefixQuery struct { + key: KvKey +} + +type KvListQuery union { + KvListAllQuery | + KvListRangeQuery | + KvListPrefixQuery +} + +# Request types +type KvGetRequest struct { + keys: list +} + +type KvListRequest struct { + query: KvListQuery + reverse: optional + limit: optional +} + +type KvPutRequest struct { + keys: list + values: list +} + +type KvDeleteRequest struct { + keys: list +} + +type KvDeleteRangeRequest struct { + start: KvKey + end: KvKey +} + +type KvDropRequest void + +# Response types +type KvErrorResponse struct { + message: str +} + +type KvGetResponse struct { + keys: list + values: list + metadata: list +} + +type KvListResponse struct { + keys: list + values: list + metadata: list +} + +type KvPutResponse void +type KvDeleteResponse void +type KvDropResponse void + +# Request/Response unions +type KvRequestData union { + KvGetRequest | + KvListRequest | + KvPutRequest | + KvDeleteRequest | + KvDeleteRangeRequest | + KvDropRequest +} + +type KvResponseData union { + KvErrorResponse | + KvGetResponse | + KvListResponse | + KvPutResponse | + KvDeleteResponse | + KvDropResponse +} + +# MARK: SQLite + +type SqlitePgno u32 +type SqliteGeneration u64 +type SqlitePageBytes data + +type SqliteDirtyPage struct { + pgno: SqlitePgno + bytes: SqlitePageBytes +} + +type SqliteFetchedPage struct { + pgno: SqlitePgno + bytes: optional +} + +type SqliteGetPagesRequest struct { + actorId: Id + pgnos: list + expectedGeneration: optional + expectedHeadTxid: optional +} + +type SqliteGetPagesOk struct { + pages: list + headTxid: optional +} + +type SqliteErrorResponse struct { + group: str + code: str + message: str +} + +type SqliteGetPagesResponse union { + SqliteGetPagesOk | + SqliteErrorResponse +} + +type SqliteCommitRequest struct { + actorId: Id + dirtyPages: list + dbSizePages: u32 + nowMs: i64 + expectedGeneration: optional + expectedHeadTxid: optional +} + +type SqliteCommitOk struct { + headTxid: optional +} + +type SqliteCommitResponse union { + SqliteCommitOk | + SqliteErrorResponse +} + +# MARK: SQLite Remote Execution + +type SqliteValueNull void + +type SqliteValueInteger struct { + value: i64 +} + +type SqliteValueFloat struct { + value: data[8] +} + +type SqliteValueText struct { + value: str +} + +type SqliteValueBlob struct { + value: data +} + +type SqliteBindParam union { + SqliteValueNull | + SqliteValueInteger | + SqliteValueFloat | + SqliteValueText | + SqliteValueBlob +} + +type SqliteColumnValue union { + SqliteValueNull | + SqliteValueInteger | + SqliteValueFloat | + SqliteValueText | + SqliteValueBlob +} + +type SqliteQueryResult struct { + columns: list + rows: list> +} + +type SqliteExecuteResult struct { + columns: list + rows: list> + changes: i64 + lastInsertRowId: optional +} + +type SqliteExecRequest struct { + namespaceId: Id + actorId: Id + generation: SqliteGeneration + sql: str +} + +type SqliteExecuteRequest struct { + namespaceId: Id + actorId: Id + generation: SqliteGeneration + sql: str + params: optional> +} + +type SqliteBatchStatement struct { + sql: str + params: optional> +} + +type SqliteExecuteBatchRequest struct { + namespaceId: Id + actorId: Id + generation: SqliteGeneration + statements: list +} + +type SqliteExecOk struct { + result: SqliteQueryResult +} + +type SqliteExecuteOk struct { + result: SqliteExecuteResult +} + +type SqliteExecuteBatchOk struct { + results: list +} + +type SqliteExecResponse union { + SqliteExecOk | + SqliteErrorResponse +} + +type SqliteExecuteResponse union { + SqliteExecuteOk | + SqliteErrorResponse +} + +type SqliteExecuteBatchResponse union { + SqliteExecuteBatchOk | + SqliteErrorResponse +} + +# MARK: Actor + +# Core +type StopCode enum { + OK + ERROR +} + +type ActorName struct { + metadata: Json +} + +type ActorConfig struct { + name: str + key: optional + createTs: i64 + input: optional +} + +type ActorCheckpoint struct { + actorId: Id + generation: u32 + index: i64 +} + +# Intent +type ActorIntentSleep void + +type ActorIntentStop void + +type ActorIntent union { + ActorIntentSleep | + ActorIntentStop +} + +# State +type ActorStateRunning void + +type ActorStateStopped struct { + code: StopCode + message: optional +} + +type ActorState union { + ActorStateRunning | + ActorStateStopped +} + +# MARK: Events +type EventActorIntent struct { + intent: ActorIntent +} + +type EventActorStateUpdate struct { + state: ActorState +} + +type EventActorSetAlarm struct { + alarmTs: optional +} + +type Event union { + EventActorIntent | + EventActorStateUpdate | + EventActorSetAlarm +} + +type EventWrapper struct { + checkpoint: ActorCheckpoint + inner: Event +} + +# MARK: Preloaded KV + +type PreloadedKvEntry struct { + key: KvKey + value: KvValue + metadata: KvMetadata +} + +type PreloadedKv struct { + entries: list + requestedGetKeys: list + requestedPrefixes: list +} + +# MARK: Commands + +type HibernatingRequest struct { + gatewayId: GatewayId + requestId: RequestId +} + +type CommandStartActor struct { + config: ActorConfig + hibernatingRequests: list + preloadedKv: optional +} + +type StopActorReason enum { + SLEEP_INTENT + STOP_INTENT + DESTROY + GOING_AWAY + LOST +} + +type CommandStopActor struct { + reason: StopActorReason +} + +type Command union { + CommandStartActor | + CommandStopActor +} + +type CommandWrapper struct { + checkpoint: ActorCheckpoint + inner: Command +} + +# We redeclare this so its top level +type ActorCommandKeyData union { + CommandStartActor | + CommandStopActor +} + +# MARK: Tunnel + +# Message ID + +type MessageId struct { + # Globally unique ID + gatewayId: GatewayId + # Unique ID to the gateway + requestId: RequestId + # Unique ID to the request + messageIndex: MessageIndex +} + +# HTTP +type ToEnvoyRequestStart struct { + actorId: Id + method: str + path: str + headers: map + body: optional + stream: bool +} + +type ToEnvoyRequestChunk struct { + body: data + finish: bool +} + +type HttpStreamAbortReasonKind enum { + UNKNOWN + CLIENT_DISCONNECT + HANDLER_ERROR + IDLE_TIMEOUT + OVERLOADED + BODY_TOO_LARGE + OUT_OF_MEMORY + SHUTDOWN + INTERNAL_ERROR +} + +type HttpStreamAbortReason struct { + kind: HttpStreamAbortReasonKind + detail: optional +} + +type ToEnvoyRequestAbort struct { + reason: HttpStreamAbortReason +} + +type ToRivetResponseStart struct { + status: u16 + headers: map + body: optional + stream: bool +} + +type ToRivetResponseChunk struct { + body: data + finish: bool +} + +type ToRivetResponseAbort struct { + reason: HttpStreamAbortReason +} + +# WebSocket +type ToEnvoyWebSocketOpen struct { + actorId: Id + path: str + headers: map +} + +type ToEnvoyWebSocketMessage struct { + data: data + binary: bool +} + +type ToEnvoyWebSocketClose struct { + code: optional + reason: optional +} + +type ToRivetWebSocketOpen struct { + canHibernate: bool +} + +type ToRivetWebSocketMessage struct { + data: data + binary: bool +} + +type ToRivetWebSocketMessageAck struct { + index: MessageIndex +} + +type ToRivetWebSocketClose struct { + code: optional + reason: optional + hibernate: bool +} + +# To Rivet +type ToRivetTunnelMessageKind union { + # HTTP + ToRivetResponseStart | + ToRivetResponseChunk | + ToRivetResponseAbort | + + # WebSocket + ToRivetWebSocketOpen | + ToRivetWebSocketMessage | + ToRivetWebSocketMessageAck | + ToRivetWebSocketClose +} + +type ToRivetTunnelMessage struct { + messageId: MessageId + messageKind: ToRivetTunnelMessageKind +} + +# To Envoy +type ToEnvoyTunnelMessageKind union { + # HTTP + ToEnvoyRequestStart | + ToEnvoyRequestChunk | + ToEnvoyRequestAbort | + + # WebSocket + ToEnvoyWebSocketOpen | + ToEnvoyWebSocketMessage | + ToEnvoyWebSocketClose +} + +type ToEnvoyTunnelMessage struct { + messageId: MessageId + messageKind: ToEnvoyTunnelMessageKind +} + +type ToEnvoyPing struct { + ts: i64 +} + +# MARK: To Rivet +type ToRivetMetadata struct { + prepopulateActorNames: optional> + metadata: optional +} + +type ToRivetEvents list + +type ToRivetAckCommands struct { + lastCommandCheckpoints: list +} + +type ToRivetStopping void + +type ToRivetPong struct { + ts: i64 +} + +type ToRivetKvRequest struct { + actorId: Id + requestId: u32 + data: KvRequestData +} + +type ToRivetSqliteGetPagesRequest struct { + requestId: u32 + data: SqliteGetPagesRequest +} + +type ToRivetSqliteCommitRequest struct { + requestId: u32 + data: SqliteCommitRequest +} + +type ToRivetSqliteExecRequest struct { + requestId: u32 + data: SqliteExecRequest +} + +type ToRivetSqliteExecuteRequest struct { + requestId: u32 + data: SqliteExecuteRequest +} + +type ToRivetSqliteExecuteBatchRequest struct { + requestId: u32 + data: SqliteExecuteBatchRequest +} + +type ToRivet union { + ToRivetMetadata | + ToRivetEvents | + ToRivetAckCommands | + ToRivetStopping | + ToRivetPong | + ToRivetKvRequest | + ToRivetTunnelMessage | + ToRivetSqliteGetPagesRequest | + ToRivetSqliteCommitRequest | + ToRivetSqliteExecRequest | + ToRivetSqliteExecuteRequest | + ToRivetSqliteExecuteBatchRequest +} + +# MARK: To Envoy +type ProtocolMetadata struct { + envoyLostThreshold: i64 + actorStopThreshold: i64 + maxResponsePayloadSize: u64 +} + +type ToEnvoyInit struct { + metadata: ProtocolMetadata +} + +type ToEnvoyCommands list + +type ToEnvoyAckEvents struct { + lastEventCheckpoints: list +} + +type ToEnvoyKvResponse struct { + requestId: u32 + data: KvResponseData +} + +type ToEnvoySqliteGetPagesResponse struct { + requestId: u32 + data: SqliteGetPagesResponse +} + +type ToEnvoySqliteCommitResponse struct { + requestId: u32 + data: SqliteCommitResponse +} + +type ToEnvoySqliteExecResponse struct { + requestId: u32 + data: SqliteExecResponse +} + +type ToEnvoySqliteExecuteResponse struct { + requestId: u32 + data: SqliteExecuteResponse +} + +type ToEnvoySqliteExecuteBatchResponse struct { + requestId: u32 + data: SqliteExecuteBatchResponse +} + +type ToEnvoy union { + ToEnvoyInit | + ToEnvoyCommands | + ToEnvoyAckEvents | + ToEnvoyKvResponse | + ToEnvoyTunnelMessage | + ToEnvoyPing | + ToEnvoySqliteGetPagesResponse | + ToEnvoySqliteCommitResponse | + ToEnvoySqliteExecResponse | + ToEnvoySqliteExecuteResponse | + ToEnvoySqliteExecuteBatchResponse +} + +# MARK: To Envoy Conn +type ToEnvoyConnPing struct { + gatewayId: GatewayId + requestId: RequestId + ts: i64 +} + +type ToEnvoyConnClose void + +type ToEnvoyConn union { + ToEnvoyConnPing | + ToEnvoyConnClose | + ToEnvoyCommands | + ToEnvoyAckEvents | + ToEnvoyTunnelMessage +} + +# MARK: To Gateway +type ToGatewayPong struct { + requestId: RequestId + ts: i64 +} + +type ToGateway union { + ToGatewayPong | + ToRivetTunnelMessage +} + +# MARK: To Outbound +type ToOutboundActorStart struct { + namespaceId: Id + poolName: str + checkpoint: ActorCheckpoint + actorConfig: ActorConfig +} + +type ToOutbound union { + ToOutboundActorStart +} diff --git a/engine/sdks/rust/envoy-protocol/src/lib.rs b/engine/sdks/rust/envoy-protocol/src/lib.rs index 899708988f..95f744f0d0 100644 --- a/engine/sdks/rust/envoy-protocol/src/lib.rs +++ b/engine/sdks/rust/envoy-protocol/src/lib.rs @@ -3,6 +3,6 @@ pub mod util; pub mod versioned; // Re-export latest -pub use generated::v7::*; +pub use generated::v8::*; pub use generated::PROTOCOL_VERSION; diff --git a/engine/sdks/rust/envoy-protocol/src/versioned/mod.rs b/engine/sdks/rust/envoy-protocol/src/versioned/mod.rs index ab9fd3c8a0..0785fabf7c 100644 --- a/engine/sdks/rust/envoy-protocol/src/versioned/mod.rs +++ b/engine/sdks/rust/envoy-protocol/src/versioned/mod.rs @@ -3,7 +3,7 @@ use std::{error::Error, fmt}; use anyhow::{Result, bail}; use vbare::OwnedVersionedData; -use crate::generated::{v1, v2, v3, v4, v5, v6, v7}; +use crate::generated::{v1, v2, v3, v4, v5, v6, v7, v8}; mod v1_to_v2; mod v2_to_v1; @@ -17,6 +17,8 @@ mod v5_to_v6; mod v6_to_v5; mod v6_to_v7; mod v7_to_v6; +mod v7_to_v8; +mod v8_to_v7; // MARK: Protocol compatibility errors @@ -114,18 +116,19 @@ pub enum ToEnvoy { V5(v5::ToEnvoy), V6(v6::ToEnvoy), V7(v7::ToEnvoy), + V8(v8::ToEnvoy), } impl OwnedVersionedData for ToEnvoy { - type Latest = v7::ToEnvoy; + type Latest = v8::ToEnvoy; fn wrap_latest(latest: Self::Latest) -> Self { - Self::V7(latest) + Self::V8(latest) } fn unwrap_latest(self) -> Result { match self { - Self::V7(x) => Ok(x), + Self::V8(x) => Ok(x), _ => bail!("version not latest"), } } @@ -139,6 +142,7 @@ impl OwnedVersionedData for ToEnvoy { 5 => Ok(Self::V5(serde_bare::from_slice(payload)?)), 6 => Ok(Self::V6(serde_bare::from_slice(payload)?)), 7 => Ok(Self::V7(serde_bare::from_slice(payload)?)), + 8 => Ok(Self::V8(serde_bare::from_slice(payload)?)), _ => bail!("invalid version: {version}"), } } @@ -152,6 +156,7 @@ impl OwnedVersionedData for ToEnvoy { Self::V5(x) => serde_bare::to_vec(&x).map_err(Into::into), Self::V6(x) => serde_bare::to_vec(&x).map_err(Into::into), Self::V7(x) => serde_bare::to_vec(&x).map_err(Into::into), + Self::V8(x) => serde_bare::to_vec(&x).map_err(Into::into), } } @@ -163,11 +168,13 @@ impl OwnedVersionedData for ToEnvoy { Self::v4_to_v5, Self::v5_to_v6, Self::v6_to_v7, + Self::v7_to_v8, ] } fn serialize_converters() -> Vec Result> { vec![ + Self::v8_to_v7, Self::v7_to_v6, Self::v6_to_v5, Self::v5_to_v4, @@ -251,6 +258,18 @@ impl ToEnvoy { _ => bail!("unexpected version"), } } + fn v7_to_v8(self) -> Result { + match self { + Self::V7(x) => Ok(Self::V8(v7_to_v8::convert_to_envoy_v7_to_v8(x)?)), + _ => bail!("unexpected version"), + } + } + fn v8_to_v7(self) -> Result { + match self { + Self::V8(x) => Ok(Self::V7(v8_to_v7::convert_to_envoy_v8_to_v7(x)?)), + _ => bail!("unexpected version"), + } + } } // MARK: ToRivet @@ -263,18 +282,19 @@ pub enum ToRivet { V5(v5::ToRivet), V6(v6::ToRivet), V7(v7::ToRivet), + V8(v8::ToRivet), } impl OwnedVersionedData for ToRivet { - type Latest = v7::ToRivet; + type Latest = v8::ToRivet; fn wrap_latest(latest: Self::Latest) -> Self { - Self::V7(latest) + Self::V8(latest) } fn unwrap_latest(self) -> Result { match self { - Self::V7(x) => Ok(x), + Self::V8(x) => Ok(x), _ => bail!("version not latest"), } } @@ -288,6 +308,7 @@ impl OwnedVersionedData for ToRivet { 5 => Ok(Self::V5(serde_bare::from_slice(payload)?)), 6 => Ok(Self::V6(serde_bare::from_slice(payload)?)), 7 => Ok(Self::V7(serde_bare::from_slice(payload)?)), + 8 => Ok(Self::V8(serde_bare::from_slice(payload)?)), _ => bail!("invalid version: {version}"), } } @@ -301,6 +322,7 @@ impl OwnedVersionedData for ToRivet { Self::V5(x) => serde_bare::to_vec(&x).map_err(Into::into), Self::V6(x) => serde_bare::to_vec(&x).map_err(Into::into), Self::V7(x) => serde_bare::to_vec(&x).map_err(Into::into), + Self::V8(x) => serde_bare::to_vec(&x).map_err(Into::into), } } @@ -312,11 +334,13 @@ impl OwnedVersionedData for ToRivet { Self::v4_to_v5, Self::v5_to_v6, Self::v6_to_v7, + Self::v7_to_v8, ] } fn serialize_converters() -> Vec Result> { vec![ + Self::v8_to_v7, Self::v7_to_v6, Self::v6_to_v5, Self::v5_to_v4, @@ -400,6 +424,18 @@ impl ToRivet { _ => bail!("unexpected version"), } } + fn v7_to_v8(self) -> Result { + match self { + Self::V7(x) => Ok(Self::V8(v7_to_v8::convert_to_rivet_v7_to_v8(x)?)), + _ => bail!("unexpected version"), + } + } + fn v8_to_v7(self) -> Result { + match self { + Self::V8(x) => Ok(Self::V7(v8_to_v7::convert_to_rivet_v8_to_v7(x)?)), + _ => bail!("unexpected version"), + } + } } // MARK: ToEnvoyConn @@ -412,18 +448,19 @@ pub enum ToEnvoyConn { V5(v5::ToEnvoyConn), V6(v6::ToEnvoyConn), V7(v7::ToEnvoyConn), + V8(v8::ToEnvoyConn), } impl OwnedVersionedData for ToEnvoyConn { - type Latest = v7::ToEnvoyConn; + type Latest = v8::ToEnvoyConn; fn wrap_latest(latest: Self::Latest) -> Self { - Self::V7(latest) + Self::V8(latest) } fn unwrap_latest(self) -> Result { match self { - Self::V7(x) => Ok(x), + Self::V8(x) => Ok(x), _ => bail!("version not latest"), } } @@ -437,6 +474,7 @@ impl OwnedVersionedData for ToEnvoyConn { 5 => Ok(Self::V5(serde_bare::from_slice(payload)?)), 6 => Ok(Self::V6(serde_bare::from_slice(payload)?)), 7 => Ok(Self::V7(serde_bare::from_slice(payload)?)), + 8 => Ok(Self::V8(serde_bare::from_slice(payload)?)), _ => bail!("invalid version: {version}"), } } @@ -450,6 +488,7 @@ impl OwnedVersionedData for ToEnvoyConn { Self::V5(x) => serde_bare::to_vec(&x).map_err(Into::into), Self::V6(x) => serde_bare::to_vec(&x).map_err(Into::into), Self::V7(x) => serde_bare::to_vec(&x).map_err(Into::into), + Self::V8(x) => serde_bare::to_vec(&x).map_err(Into::into), } } @@ -461,11 +500,13 @@ impl OwnedVersionedData for ToEnvoyConn { Self::v4_to_v5, Self::v5_to_v6, Self::v6_to_v7, + Self::v7_to_v8, ] } fn serialize_converters() -> Vec Result> { vec![ + Self::v8_to_v7, Self::v7_to_v6, Self::v6_to_v5, Self::v5_to_v4, @@ -549,6 +590,18 @@ impl ToEnvoyConn { _ => bail!("unexpected version"), } } + fn v7_to_v8(self) -> Result { + match self { + Self::V7(x) => Ok(Self::V8(v7_to_v8::convert_to_envoy_conn_v7_to_v8(x)?)), + _ => bail!("unexpected version"), + } + } + fn v8_to_v7(self) -> Result { + match self { + Self::V8(x) => Ok(Self::V7(v8_to_v7::convert_to_envoy_conn_v8_to_v7(x)?)), + _ => bail!("unexpected version"), + } + } } // MARK: ToGateway @@ -561,18 +614,19 @@ pub enum ToGateway { V5(v5::ToGateway), V6(v6::ToGateway), V7(v7::ToGateway), + V8(v8::ToGateway), } impl OwnedVersionedData for ToGateway { - type Latest = v7::ToGateway; + type Latest = v8::ToGateway; fn wrap_latest(latest: Self::Latest) -> Self { - Self::V7(latest) + Self::V8(latest) } fn unwrap_latest(self) -> Result { match self { - Self::V7(x) => Ok(x), + Self::V8(x) => Ok(x), _ => bail!("version not latest"), } } @@ -586,6 +640,7 @@ impl OwnedVersionedData for ToGateway { 5 => Ok(Self::V5(serde_bare::from_slice(payload)?)), 6 => Ok(Self::V6(serde_bare::from_slice(payload)?)), 7 => Ok(Self::V7(serde_bare::from_slice(payload)?)), + 8 => Ok(Self::V8(serde_bare::from_slice(payload)?)), _ => bail!("invalid version: {version}"), } } @@ -599,6 +654,7 @@ impl OwnedVersionedData for ToGateway { Self::V5(x) => serde_bare::to_vec(&x).map_err(Into::into), Self::V6(x) => serde_bare::to_vec(&x).map_err(Into::into), Self::V7(x) => serde_bare::to_vec(&x).map_err(Into::into), + Self::V8(x) => serde_bare::to_vec(&x).map_err(Into::into), } } @@ -610,11 +666,13 @@ impl OwnedVersionedData for ToGateway { Self::v4_to_v5, Self::v5_to_v6, Self::v6_to_v7, + Self::v7_to_v8, ] } fn serialize_converters() -> Vec Result> { vec![ + Self::v8_to_v7, Self::v7_to_v6, Self::v6_to_v5, Self::v5_to_v4, @@ -698,6 +756,18 @@ impl ToGateway { _ => bail!("unexpected version"), } } + fn v7_to_v8(self) -> Result { + match self { + Self::V7(x) => Ok(Self::V8(v7_to_v8::convert_to_gateway_v7_to_v8(x)?)), + _ => bail!("unexpected version"), + } + } + fn v8_to_v7(self) -> Result { + match self { + Self::V8(x) => Ok(Self::V7(v8_to_v7::convert_to_gateway_v8_to_v7(x)?)), + _ => bail!("unexpected version"), + } + } } // MARK: ToOutbound @@ -710,18 +780,19 @@ pub enum ToOutbound { V5(v5::ToOutbound), V6(v6::ToOutbound), V7(v7::ToOutbound), + V8(v8::ToOutbound), } impl OwnedVersionedData for ToOutbound { - type Latest = v7::ToOutbound; + type Latest = v8::ToOutbound; fn wrap_latest(latest: Self::Latest) -> Self { - Self::V7(latest) + Self::V8(latest) } fn unwrap_latest(self) -> Result { match self { - Self::V7(x) => Ok(x), + Self::V8(x) => Ok(x), _ => bail!("version not latest"), } } @@ -735,6 +806,7 @@ impl OwnedVersionedData for ToOutbound { 5 => Ok(Self::V5(serde_bare::from_slice(payload)?)), 6 => Ok(Self::V6(serde_bare::from_slice(payload)?)), 7 => Ok(Self::V7(serde_bare::from_slice(payload)?)), + 8 => Ok(Self::V8(serde_bare::from_slice(payload)?)), _ => bail!("invalid version: {version}"), } } @@ -748,6 +820,7 @@ impl OwnedVersionedData for ToOutbound { Self::V5(x) => serde_bare::to_vec(&x).map_err(Into::into), Self::V6(x) => serde_bare::to_vec(&x).map_err(Into::into), Self::V7(x) => serde_bare::to_vec(&x).map_err(Into::into), + Self::V8(x) => serde_bare::to_vec(&x).map_err(Into::into), } } @@ -759,11 +832,13 @@ impl OwnedVersionedData for ToOutbound { Self::v4_to_v5, Self::v5_to_v6, Self::v6_to_v7, + Self::v7_to_v8, ] } fn serialize_converters() -> Vec Result> { vec![ + Self::v8_to_v7, Self::v7_to_v6, Self::v6_to_v5, Self::v5_to_v4, @@ -847,6 +922,18 @@ impl ToOutbound { _ => bail!("unexpected version"), } } + fn v7_to_v8(self) -> Result { + match self { + Self::V7(x) => Ok(Self::V8(v7_to_v8::convert_to_outbound_v7_to_v8(x)?)), + _ => bail!("unexpected version"), + } + } + fn v8_to_v7(self) -> Result { + match self { + Self::V8(x) => Ok(Self::V7(v8_to_v7::convert_to_outbound_v8_to_v7(x)?)), + _ => bail!("unexpected version"), + } + } } // MARK: ActorCommandKeyData @@ -859,18 +946,19 @@ pub enum ActorCommandKeyData { V5(v5::ActorCommandKeyData), V6(v6::ActorCommandKeyData), V7(v7::ActorCommandKeyData), + V8(v8::ActorCommandKeyData), } impl OwnedVersionedData for ActorCommandKeyData { - type Latest = v7::ActorCommandKeyData; + type Latest = v8::ActorCommandKeyData; fn wrap_latest(latest: Self::Latest) -> Self { - Self::V7(latest) + Self::V8(latest) } fn unwrap_latest(self) -> Result { match self { - Self::V7(x) => Ok(x), + Self::V8(x) => Ok(x), _ => bail!("version not latest"), } } @@ -884,6 +972,7 @@ impl OwnedVersionedData for ActorCommandKeyData { 5 => Ok(Self::V5(serde_bare::from_slice(payload)?)), 6 => Ok(Self::V6(serde_bare::from_slice(payload)?)), 7 => Ok(Self::V7(serde_bare::from_slice(payload)?)), + 8 => Ok(Self::V8(serde_bare::from_slice(payload)?)), _ => bail!("invalid version: {version}"), } } @@ -897,6 +986,7 @@ impl OwnedVersionedData for ActorCommandKeyData { Self::V5(x) => serde_bare::to_vec(&x).map_err(Into::into), Self::V6(x) => serde_bare::to_vec(&x).map_err(Into::into), Self::V7(x) => serde_bare::to_vec(&x).map_err(Into::into), + Self::V8(x) => serde_bare::to_vec(&x).map_err(Into::into), } } @@ -908,11 +998,13 @@ impl OwnedVersionedData for ActorCommandKeyData { Self::v4_to_v5, Self::v5_to_v6, Self::v6_to_v7, + Self::v7_to_v8, ] } fn serialize_converters() -> Vec Result> { vec![ + Self::v8_to_v7, Self::v7_to_v6, Self::v6_to_v5, Self::v5_to_v4, @@ -1020,6 +1112,22 @@ impl ActorCommandKeyData { _ => bail!("unexpected version"), } } + fn v7_to_v8(self) -> Result { + match self { + Self::V7(x) => Ok(Self::V8(v7_to_v8::convert_actor_command_key_data_v7_to_v8( + x, + )?)), + _ => bail!("unexpected version"), + } + } + fn v8_to_v7(self) -> Result { + match self { + Self::V8(x) => Ok(Self::V7(v8_to_v7::convert_actor_command_key_data_v8_to_v7( + x, + )?)), + _ => bail!("unexpected version"), + } + } } // MARK: Tests @@ -1032,12 +1140,12 @@ mod tests { use super::{ActorCommandKeyData, ToEnvoy}; use crate::{ PROTOCOL_VERSION, - generated::{v1, v2, v7}, + generated::{v1, v2, v8}, }; #[test] fn protocol_version_constant_matches_schema_version() { - assert_eq!(PROTOCOL_VERSION, 7); + assert_eq!(PROTOCOL_VERSION, 8); } #[test] @@ -1062,10 +1170,10 @@ mod tests { }]))?; let decoded = ToEnvoy::deserialize(&payload, 1)?; - let v7::ToEnvoy::ToEnvoyCommands(commands) = decoded else { + let v8::ToEnvoy::ToEnvoyCommands(commands) = decoded else { panic!("expected commands"); }; - let v7::Command::CommandStartActor(start) = &commands[0].inner else { + let v8::Command::CommandStartActor(start) = &commands[0].inner else { panic!("expected start actor"); }; @@ -1092,9 +1200,9 @@ mod tests { #[test] fn actor_command_key_data_round_trips_to_v1() -> Result<()> { - let encoded = ActorCommandKeyData::wrap_latest(v7::ActorCommandKeyData::CommandStartActor( - v7::CommandStartActor { - config: v7::ActorConfig { + let encoded = ActorCommandKeyData::wrap_latest(v8::ActorCommandKeyData::CommandStartActor( + v8::CommandStartActor { + config: v8::ActorConfig { name: "demo".into(), key: None, create_ts: 7, @@ -1107,7 +1215,7 @@ mod tests { .serialize(1)?; let decoded = ActorCommandKeyData::deserialize(&encoded, 1)?; - let v7::ActorCommandKeyData::CommandStartActor(start) = decoded else { + let v8::ActorCommandKeyData::CommandStartActor(start) = decoded else { panic!("expected start actor"); }; assert_eq!(start.config.name, "demo"); diff --git a/engine/sdks/rust/envoy-protocol/src/versioned/v7_to_v8.rs b/engine/sdks/rust/envoy-protocol/src/versioned/v7_to_v8.rs new file mode 100644 index 0000000000..be08e5b02e --- /dev/null +++ b/engine/sdks/rust/envoy-protocol/src/versioned/v7_to_v8.rs @@ -0,0 +1,1238 @@ +// from: v7.bare, to: v8.bare + +#![allow(dead_code, unused_variables)] + +use anyhow::Result; + +use crate::generated::{v7, v8}; + +pub fn convert_kv_metadata_v7_to_v8(x: v7::KvMetadata) -> Result { + Ok(v8::KvMetadata { + version: x.version, + update_ts: x.update_ts, + }) +} + +pub fn convert_kv_list_range_query_v7_to_v8( + x: v7::KvListRangeQuery, +) -> Result { + Ok(v8::KvListRangeQuery { + start: x.start, + end: x.end, + exclusive: x.exclusive, + }) +} + +pub fn convert_kv_list_prefix_query_v7_to_v8( + x: v7::KvListPrefixQuery, +) -> Result { + Ok(v8::KvListPrefixQuery { key: x.key }) +} + +pub fn convert_kv_list_query_v7_to_v8(x: v7::KvListQuery) -> Result { + Ok(match x { + v7::KvListQuery::KvListAllQuery => v8::KvListQuery::KvListAllQuery, + v7::KvListQuery::KvListRangeQuery(v) => { + v8::KvListQuery::KvListRangeQuery(convert_kv_list_range_query_v7_to_v8(v)?) + } + v7::KvListQuery::KvListPrefixQuery(v) => { + v8::KvListQuery::KvListPrefixQuery(convert_kv_list_prefix_query_v7_to_v8(v)?) + } + }) +} + +pub fn convert_kv_get_request_v7_to_v8(x: v7::KvGetRequest) -> Result { + Ok(v8::KvGetRequest { keys: x.keys }) +} + +pub fn convert_kv_list_request_v7_to_v8(x: v7::KvListRequest) -> Result { + Ok(v8::KvListRequest { + query: convert_kv_list_query_v7_to_v8(x.query)?, + reverse: x.reverse, + limit: x.limit, + }) +} + +pub fn convert_kv_put_request_v7_to_v8(x: v7::KvPutRequest) -> Result { + Ok(v8::KvPutRequest { + keys: x.keys, + values: x.values, + }) +} + +pub fn convert_kv_delete_request_v7_to_v8(x: v7::KvDeleteRequest) -> Result { + Ok(v8::KvDeleteRequest { keys: x.keys }) +} + +pub fn convert_kv_delete_range_request_v7_to_v8( + x: v7::KvDeleteRangeRequest, +) -> Result { + Ok(v8::KvDeleteRangeRequest { + start: x.start, + end: x.end, + }) +} + +pub fn convert_kv_error_response_v7_to_v8(x: v7::KvErrorResponse) -> Result { + Ok(v8::KvErrorResponse { message: x.message }) +} + +pub fn convert_kv_get_response_v7_to_v8(x: v7::KvGetResponse) -> Result { + Ok(v8::KvGetResponse { + keys: x.keys, + values: x.values, + metadata: x + .metadata + .into_iter() + .map(|v| convert_kv_metadata_v7_to_v8(v)) + .collect::>>()?, + }) +} + +pub fn convert_kv_list_response_v7_to_v8(x: v7::KvListResponse) -> Result { + Ok(v8::KvListResponse { + keys: x.keys, + values: x.values, + metadata: x + .metadata + .into_iter() + .map(|v| convert_kv_metadata_v7_to_v8(v)) + .collect::>>()?, + }) +} + +pub fn convert_kv_request_data_v7_to_v8(x: v7::KvRequestData) -> Result { + Ok(match x { + v7::KvRequestData::KvGetRequest(v) => { + v8::KvRequestData::KvGetRequest(convert_kv_get_request_v7_to_v8(v)?) + } + v7::KvRequestData::KvListRequest(v) => { + v8::KvRequestData::KvListRequest(convert_kv_list_request_v7_to_v8(v)?) + } + v7::KvRequestData::KvPutRequest(v) => { + v8::KvRequestData::KvPutRequest(convert_kv_put_request_v7_to_v8(v)?) + } + v7::KvRequestData::KvDeleteRequest(v) => { + v8::KvRequestData::KvDeleteRequest(convert_kv_delete_request_v7_to_v8(v)?) + } + v7::KvRequestData::KvDeleteRangeRequest(v) => { + v8::KvRequestData::KvDeleteRangeRequest(convert_kv_delete_range_request_v7_to_v8(v)?) + } + v7::KvRequestData::KvDropRequest => v8::KvRequestData::KvDropRequest, + }) +} + +pub fn convert_kv_response_data_v7_to_v8(x: v7::KvResponseData) -> Result { + Ok(match x { + v7::KvResponseData::KvErrorResponse(v) => { + v8::KvResponseData::KvErrorResponse(convert_kv_error_response_v7_to_v8(v)?) + } + v7::KvResponseData::KvGetResponse(v) => { + v8::KvResponseData::KvGetResponse(convert_kv_get_response_v7_to_v8(v)?) + } + v7::KvResponseData::KvListResponse(v) => { + v8::KvResponseData::KvListResponse(convert_kv_list_response_v7_to_v8(v)?) + } + v7::KvResponseData::KvPutResponse => v8::KvResponseData::KvPutResponse, + v7::KvResponseData::KvDeleteResponse => v8::KvResponseData::KvDeleteResponse, + v7::KvResponseData::KvDropResponse => v8::KvResponseData::KvDropResponse, + }) +} + +pub fn convert_sqlite_dirty_page_v7_to_v8(x: v7::SqliteDirtyPage) -> Result { + Ok(v8::SqliteDirtyPage { + pgno: x.pgno, + bytes: x.bytes, + }) +} + +pub fn convert_sqlite_fetched_page_v7_to_v8( + x: v7::SqliteFetchedPage, +) -> Result { + Ok(v8::SqliteFetchedPage { + pgno: x.pgno, + bytes: x.bytes, + }) +} + +pub fn convert_sqlite_get_pages_request_v7_to_v8( + x: v7::SqliteGetPagesRequest, +) -> Result { + Ok(v8::SqliteGetPagesRequest { + actor_id: x.actor_id, + pgnos: x.pgnos, + expected_generation: x.expected_generation, + expected_head_txid: x.expected_head_txid, + }) +} + +pub fn convert_sqlite_get_pages_ok_v7_to_v8( + x: v7::SqliteGetPagesOk, +) -> Result { + Ok(v8::SqliteGetPagesOk { + pages: x + .pages + .into_iter() + .map(|v| convert_sqlite_fetched_page_v7_to_v8(v)) + .collect::>>()?, + head_txid: x.head_txid, + }) +} + +pub fn convert_sqlite_error_response_v7_to_v8( + x: v7::SqliteErrorResponse, +) -> Result { + Ok(v8::SqliteErrorResponse { + group: x.group, + code: x.code, + message: x.message, + }) +} + +pub fn convert_sqlite_get_pages_response_v7_to_v8( + x: v7::SqliteGetPagesResponse, +) -> Result { + Ok(match x { + v7::SqliteGetPagesResponse::SqliteGetPagesOk(v) => { + v8::SqliteGetPagesResponse::SqliteGetPagesOk(convert_sqlite_get_pages_ok_v7_to_v8(v)?) + } + v7::SqliteGetPagesResponse::SqliteErrorResponse(v) => { + v8::SqliteGetPagesResponse::SqliteErrorResponse(convert_sqlite_error_response_v7_to_v8( + v, + )?) + } + }) +} + +pub fn convert_sqlite_commit_request_v7_to_v8( + x: v7::SqliteCommitRequest, +) -> Result { + Ok(v8::SqliteCommitRequest { + actor_id: x.actor_id, + dirty_pages: x + .dirty_pages + .into_iter() + .map(|v| convert_sqlite_dirty_page_v7_to_v8(v)) + .collect::>>()?, + db_size_pages: x.db_size_pages, + now_ms: x.now_ms, + expected_generation: x.expected_generation, + expected_head_txid: x.expected_head_txid, + }) +} + +pub fn convert_sqlite_commit_ok_v7_to_v8(x: v7::SqliteCommitOk) -> Result { + Ok(v8::SqliteCommitOk { + head_txid: x.head_txid, + }) +} + +pub fn convert_sqlite_commit_response_v7_to_v8( + x: v7::SqliteCommitResponse, +) -> Result { + Ok(match x { + v7::SqliteCommitResponse::SqliteCommitOk(v) => { + v8::SqliteCommitResponse::SqliteCommitOk(convert_sqlite_commit_ok_v7_to_v8(v)?) + } + v7::SqliteCommitResponse::SqliteErrorResponse(v) => { + v8::SqliteCommitResponse::SqliteErrorResponse(convert_sqlite_error_response_v7_to_v8( + v, + )?) + } + }) +} + +pub fn convert_sqlite_value_integer_v7_to_v8( + x: v7::SqliteValueInteger, +) -> Result { + Ok(v8::SqliteValueInteger { value: x.value }) +} + +pub fn convert_sqlite_value_float_v7_to_v8( + x: v7::SqliteValueFloat, +) -> Result { + Ok(v8::SqliteValueFloat { value: x.value }) +} + +pub fn convert_sqlite_value_text_v7_to_v8(x: v7::SqliteValueText) -> Result { + Ok(v8::SqliteValueText { value: x.value }) +} + +pub fn convert_sqlite_value_blob_v7_to_v8(x: v7::SqliteValueBlob) -> Result { + Ok(v8::SqliteValueBlob { value: x.value }) +} + +pub fn convert_sqlite_bind_param_v7_to_v8(x: v7::SqliteBindParam) -> Result { + Ok(match x { + v7::SqliteBindParam::SqliteValueNull => v8::SqliteBindParam::SqliteValueNull, + v7::SqliteBindParam::SqliteValueInteger(v) => { + v8::SqliteBindParam::SqliteValueInteger(convert_sqlite_value_integer_v7_to_v8(v)?) + } + v7::SqliteBindParam::SqliteValueFloat(v) => { + v8::SqliteBindParam::SqliteValueFloat(convert_sqlite_value_float_v7_to_v8(v)?) + } + v7::SqliteBindParam::SqliteValueText(v) => { + v8::SqliteBindParam::SqliteValueText(convert_sqlite_value_text_v7_to_v8(v)?) + } + v7::SqliteBindParam::SqliteValueBlob(v) => { + v8::SqliteBindParam::SqliteValueBlob(convert_sqlite_value_blob_v7_to_v8(v)?) + } + }) +} + +pub fn convert_sqlite_column_value_v7_to_v8( + x: v7::SqliteColumnValue, +) -> Result { + Ok(match x { + v7::SqliteColumnValue::SqliteValueNull => v8::SqliteColumnValue::SqliteValueNull, + v7::SqliteColumnValue::SqliteValueInteger(v) => { + v8::SqliteColumnValue::SqliteValueInteger(convert_sqlite_value_integer_v7_to_v8(v)?) + } + v7::SqliteColumnValue::SqliteValueFloat(v) => { + v8::SqliteColumnValue::SqliteValueFloat(convert_sqlite_value_float_v7_to_v8(v)?) + } + v7::SqliteColumnValue::SqliteValueText(v) => { + v8::SqliteColumnValue::SqliteValueText(convert_sqlite_value_text_v7_to_v8(v)?) + } + v7::SqliteColumnValue::SqliteValueBlob(v) => { + v8::SqliteColumnValue::SqliteValueBlob(convert_sqlite_value_blob_v7_to_v8(v)?) + } + }) +} + +pub fn convert_sqlite_query_result_v7_to_v8( + x: v7::SqliteQueryResult, +) -> Result { + Ok(v8::SqliteQueryResult { + columns: x.columns, + rows: x + .rows + .into_iter() + .map(|v| { + v.into_iter() + .map(|v| convert_sqlite_column_value_v7_to_v8(v)) + .collect::>>() + }) + .collect::>>()?, + }) +} + +pub fn convert_sqlite_execute_result_v7_to_v8( + x: v7::SqliteExecuteResult, +) -> Result { + Ok(v8::SqliteExecuteResult { + columns: x.columns, + rows: x + .rows + .into_iter() + .map(|v| { + v.into_iter() + .map(|v| convert_sqlite_column_value_v7_to_v8(v)) + .collect::>>() + }) + .collect::>>()?, + changes: x.changes, + last_insert_row_id: x.last_insert_row_id, + }) +} + +pub fn convert_sqlite_exec_request_v7_to_v8( + x: v7::SqliteExecRequest, +) -> Result { + Ok(v8::SqliteExecRequest { + namespace_id: x.namespace_id, + actor_id: x.actor_id, + generation: x.generation, + sql: x.sql, + }) +} + +pub fn convert_sqlite_execute_request_v7_to_v8( + x: v7::SqliteExecuteRequest, +) -> Result { + Ok(v8::SqliteExecuteRequest { + namespace_id: x.namespace_id, + actor_id: x.actor_id, + generation: x.generation, + sql: x.sql, + params: x + .params + .map(|v| { + v.into_iter() + .map(|v| convert_sqlite_bind_param_v7_to_v8(v)) + .collect::>>() + }) + .transpose()?, + }) +} + +pub fn convert_sqlite_batch_statement_v7_to_v8( + x: v7::SqliteBatchStatement, +) -> Result { + Ok(v8::SqliteBatchStatement { + sql: x.sql, + params: x + .params + .map(|v| { + v.into_iter() + .map(|v| convert_sqlite_bind_param_v7_to_v8(v)) + .collect::>>() + }) + .transpose()?, + }) +} + +pub fn convert_sqlite_execute_batch_request_v7_to_v8( + x: v7::SqliteExecuteBatchRequest, +) -> Result { + Ok(v8::SqliteExecuteBatchRequest { + namespace_id: x.namespace_id, + actor_id: x.actor_id, + generation: x.generation, + statements: x + .statements + .into_iter() + .map(|v| convert_sqlite_batch_statement_v7_to_v8(v)) + .collect::>>()?, + }) +} + +pub fn convert_sqlite_exec_ok_v7_to_v8(x: v7::SqliteExecOk) -> Result { + Ok(v8::SqliteExecOk { + result: convert_sqlite_query_result_v7_to_v8(x.result)?, + }) +} + +pub fn convert_sqlite_execute_ok_v7_to_v8(x: v7::SqliteExecuteOk) -> Result { + Ok(v8::SqliteExecuteOk { + result: convert_sqlite_execute_result_v7_to_v8(x.result)?, + }) +} + +pub fn convert_sqlite_execute_batch_ok_v7_to_v8( + x: v7::SqliteExecuteBatchOk, +) -> Result { + Ok(v8::SqliteExecuteBatchOk { + results: x + .results + .into_iter() + .map(|v| convert_sqlite_execute_result_v7_to_v8(v)) + .collect::>>()?, + }) +} + +pub fn convert_sqlite_exec_response_v7_to_v8( + x: v7::SqliteExecResponse, +) -> Result { + Ok(match x { + v7::SqliteExecResponse::SqliteExecOk(v) => { + v8::SqliteExecResponse::SqliteExecOk(convert_sqlite_exec_ok_v7_to_v8(v)?) + } + v7::SqliteExecResponse::SqliteErrorResponse(v) => { + v8::SqliteExecResponse::SqliteErrorResponse(convert_sqlite_error_response_v7_to_v8(v)?) + } + }) +} + +pub fn convert_sqlite_execute_response_v7_to_v8( + x: v7::SqliteExecuteResponse, +) -> Result { + Ok(match x { + v7::SqliteExecuteResponse::SqliteExecuteOk(v) => { + v8::SqliteExecuteResponse::SqliteExecuteOk(convert_sqlite_execute_ok_v7_to_v8(v)?) + } + v7::SqliteExecuteResponse::SqliteErrorResponse(v) => { + v8::SqliteExecuteResponse::SqliteErrorResponse(convert_sqlite_error_response_v7_to_v8( + v, + )?) + } + }) +} + +pub fn convert_sqlite_execute_batch_response_v7_to_v8( + x: v7::SqliteExecuteBatchResponse, +) -> Result { + Ok(match x { + v7::SqliteExecuteBatchResponse::SqliteExecuteBatchOk(v) => { + v8::SqliteExecuteBatchResponse::SqliteExecuteBatchOk( + convert_sqlite_execute_batch_ok_v7_to_v8(v)?, + ) + } + v7::SqliteExecuteBatchResponse::SqliteErrorResponse(v) => { + v8::SqliteExecuteBatchResponse::SqliteErrorResponse( + convert_sqlite_error_response_v7_to_v8(v)?, + ) + } + }) +} + +pub fn convert_stop_code_v7_to_v8(x: v7::StopCode) -> Result { + Ok(match x { + v7::StopCode::Ok => v8::StopCode::Ok, + v7::StopCode::Error => v8::StopCode::Error, + }) +} + +pub fn convert_actor_name_v7_to_v8(x: v7::ActorName) -> Result { + Ok(v8::ActorName { + metadata: x.metadata, + }) +} + +pub fn convert_actor_config_v7_to_v8(x: v7::ActorConfig) -> Result { + Ok(v8::ActorConfig { + name: x.name, + key: x.key, + create_ts: x.create_ts, + input: x.input, + }) +} + +pub fn convert_actor_checkpoint_v7_to_v8(x: v7::ActorCheckpoint) -> Result { + Ok(v8::ActorCheckpoint { + actor_id: x.actor_id, + generation: x.generation, + index: x.index, + }) +} + +pub fn convert_actor_intent_v7_to_v8(x: v7::ActorIntent) -> Result { + Ok(match x { + v7::ActorIntent::ActorIntentSleep => v8::ActorIntent::ActorIntentSleep, + v7::ActorIntent::ActorIntentStop => v8::ActorIntent::ActorIntentStop, + }) +} + +pub fn convert_actor_state_stopped_v7_to_v8( + x: v7::ActorStateStopped, +) -> Result { + Ok(v8::ActorStateStopped { + code: convert_stop_code_v7_to_v8(x.code)?, + message: x.message, + }) +} + +pub fn convert_actor_state_v7_to_v8(x: v7::ActorState) -> Result { + Ok(match x { + v7::ActorState::ActorStateRunning => v8::ActorState::ActorStateRunning, + v7::ActorState::ActorStateStopped(v) => { + v8::ActorState::ActorStateStopped(convert_actor_state_stopped_v7_to_v8(v)?) + } + }) +} + +pub fn convert_event_actor_intent_v7_to_v8( + x: v7::EventActorIntent, +) -> Result { + Ok(v8::EventActorIntent { + intent: convert_actor_intent_v7_to_v8(x.intent)?, + }) +} + +pub fn convert_event_actor_state_update_v7_to_v8( + x: v7::EventActorStateUpdate, +) -> Result { + Ok(v8::EventActorStateUpdate { + state: convert_actor_state_v7_to_v8(x.state)?, + }) +} + +pub fn convert_event_actor_set_alarm_v7_to_v8( + x: v7::EventActorSetAlarm, +) -> Result { + Ok(v8::EventActorSetAlarm { + alarm_ts: x.alarm_ts, + }) +} + +pub fn convert_event_v7_to_v8(x: v7::Event) -> Result { + Ok(match x { + v7::Event::EventActorIntent(v) => { + v8::Event::EventActorIntent(convert_event_actor_intent_v7_to_v8(v)?) + } + v7::Event::EventActorStateUpdate(v) => { + v8::Event::EventActorStateUpdate(convert_event_actor_state_update_v7_to_v8(v)?) + } + v7::Event::EventActorSetAlarm(v) => { + v8::Event::EventActorSetAlarm(convert_event_actor_set_alarm_v7_to_v8(v)?) + } + }) +} + +pub fn convert_event_wrapper_v7_to_v8(x: v7::EventWrapper) -> Result { + Ok(v8::EventWrapper { + checkpoint: convert_actor_checkpoint_v7_to_v8(x.checkpoint)?, + inner: convert_event_v7_to_v8(x.inner)?, + }) +} + +pub fn convert_preloaded_kv_entry_v7_to_v8( + x: v7::PreloadedKvEntry, +) -> Result { + Ok(v8::PreloadedKvEntry { + key: x.key, + value: x.value, + metadata: convert_kv_metadata_v7_to_v8(x.metadata)?, + }) +} + +pub fn convert_preloaded_kv_v7_to_v8(x: v7::PreloadedKv) -> Result { + Ok(v8::PreloadedKv { + entries: x + .entries + .into_iter() + .map(|v| convert_preloaded_kv_entry_v7_to_v8(v)) + .collect::>>()?, + requested_get_keys: x.requested_get_keys, + requested_prefixes: x.requested_prefixes, + }) +} + +pub fn convert_hibernating_request_v7_to_v8( + x: v7::HibernatingRequest, +) -> Result { + Ok(v8::HibernatingRequest { + gateway_id: x.gateway_id, + request_id: x.request_id, + }) +} + +pub fn convert_command_start_actor_v7_to_v8( + x: v7::CommandStartActor, +) -> Result { + Ok(v8::CommandStartActor { + config: convert_actor_config_v7_to_v8(x.config)?, + hibernating_requests: x + .hibernating_requests + .into_iter() + .map(|v| convert_hibernating_request_v7_to_v8(v)) + .collect::>>()?, + preloaded_kv: x + .preloaded_kv + .map(|v| convert_preloaded_kv_v7_to_v8(v)) + .transpose()?, + }) +} + +pub fn convert_stop_actor_reason_v7_to_v8(x: v7::StopActorReason) -> Result { + Ok(match x { + v7::StopActorReason::SleepIntent => v8::StopActorReason::SleepIntent, + v7::StopActorReason::StopIntent => v8::StopActorReason::StopIntent, + v7::StopActorReason::Destroy => v8::StopActorReason::Destroy, + v7::StopActorReason::GoingAway => v8::StopActorReason::GoingAway, + v7::StopActorReason::Lost => v8::StopActorReason::Lost, + }) +} + +pub fn convert_command_stop_actor_v7_to_v8( + x: v7::CommandStopActor, +) -> Result { + Ok(v8::CommandStopActor { + reason: convert_stop_actor_reason_v7_to_v8(x.reason)?, + }) +} + +pub fn convert_command_v7_to_v8(x: v7::Command) -> Result { + Ok(match x { + v7::Command::CommandStartActor(v) => { + v8::Command::CommandStartActor(convert_command_start_actor_v7_to_v8(v)?) + } + v7::Command::CommandStopActor(v) => { + v8::Command::CommandStopActor(convert_command_stop_actor_v7_to_v8(v)?) + } + }) +} + +pub fn convert_command_wrapper_v7_to_v8(x: v7::CommandWrapper) -> Result { + Ok(v8::CommandWrapper { + checkpoint: convert_actor_checkpoint_v7_to_v8(x.checkpoint)?, + inner: convert_command_v7_to_v8(x.inner)?, + }) +} + +pub fn convert_actor_command_key_data_v7_to_v8( + x: v7::ActorCommandKeyData, +) -> Result { + Ok(match x { + v7::ActorCommandKeyData::CommandStartActor(v) => { + v8::ActorCommandKeyData::CommandStartActor(convert_command_start_actor_v7_to_v8(v)?) + } + v7::ActorCommandKeyData::CommandStopActor(v) => { + v8::ActorCommandKeyData::CommandStopActor(convert_command_stop_actor_v7_to_v8(v)?) + } + }) +} + +pub fn convert_message_id_v7_to_v8(x: v7::MessageId) -> Result { + Ok(v8::MessageId { + gateway_id: x.gateway_id, + request_id: x.request_id, + message_index: x.message_index, + }) +} + +pub fn convert_to_envoy_request_start_v7_to_v8( + x: v7::ToEnvoyRequestStart, +) -> Result { + Ok(v8::ToEnvoyRequestStart { + actor_id: x.actor_id, + method: x.method, + path: x.path, + headers: x.headers, + body: x.body, + stream: x.stream, + }) +} + +pub fn convert_to_envoy_request_chunk_v7_to_v8( + x: v7::ToEnvoyRequestChunk, +) -> Result { + Ok(v8::ToEnvoyRequestChunk { + body: x.body, + finish: x.finish, + }) +} + +pub fn convert_http_stream_abort_reason_kind_v7_to_v8( + x: v7::HttpStreamAbortReasonKind, +) -> Result { + Ok(match x { + v7::HttpStreamAbortReasonKind::Unknown => v8::HttpStreamAbortReasonKind::Unknown, + v7::HttpStreamAbortReasonKind::ClientDisconnect => { + v8::HttpStreamAbortReasonKind::ClientDisconnect + } + v7::HttpStreamAbortReasonKind::HandlerError => v8::HttpStreamAbortReasonKind::HandlerError, + v7::HttpStreamAbortReasonKind::IdleTimeout => v8::HttpStreamAbortReasonKind::IdleTimeout, + v7::HttpStreamAbortReasonKind::Overloaded => v8::HttpStreamAbortReasonKind::Overloaded, + v7::HttpStreamAbortReasonKind::BodyTooLarge => v8::HttpStreamAbortReasonKind::BodyTooLarge, + v7::HttpStreamAbortReasonKind::OutOfMemory => v8::HttpStreamAbortReasonKind::OutOfMemory, + v7::HttpStreamAbortReasonKind::Shutdown => v8::HttpStreamAbortReasonKind::Shutdown, + v7::HttpStreamAbortReasonKind::InternalError => { + v8::HttpStreamAbortReasonKind::InternalError + } + }) +} + +pub fn convert_http_stream_abort_reason_v7_to_v8( + x: v7::HttpStreamAbortReason, +) -> Result { + Ok(v8::HttpStreamAbortReason { + kind: convert_http_stream_abort_reason_kind_v7_to_v8(x.kind)?, + detail: x.detail, + }) +} + +pub fn convert_to_envoy_request_abort_v7_to_v8( + x: v7::ToEnvoyRequestAbort, +) -> Result { + Ok(v8::ToEnvoyRequestAbort { + reason: convert_http_stream_abort_reason_v7_to_v8(x.reason)?, + }) +} + +pub fn convert_to_rivet_response_abort_v7_to_v8( + x: v7::ToRivetResponseAbort, +) -> Result { + Ok(v8::ToRivetResponseAbort { + reason: convert_http_stream_abort_reason_v7_to_v8(x.reason)?, + }) +} + +pub fn convert_to_rivet_response_start_v7_to_v8( + x: v7::ToRivetResponseStart, +) -> Result { + Ok(v8::ToRivetResponseStart { + status: x.status, + headers: x.headers, + body: x.body, + stream: x.stream, + }) +} + +pub fn convert_to_rivet_response_chunk_v7_to_v8( + x: v7::ToRivetResponseChunk, +) -> Result { + Ok(v8::ToRivetResponseChunk { + body: x.body, + finish: x.finish, + }) +} + +pub fn convert_to_envoy_web_socket_open_v7_to_v8( + x: v7::ToEnvoyWebSocketOpen, +) -> Result { + Ok(v8::ToEnvoyWebSocketOpen { + actor_id: x.actor_id, + path: x.path, + headers: x.headers, + }) +} + +pub fn convert_to_envoy_web_socket_message_v7_to_v8( + x: v7::ToEnvoyWebSocketMessage, +) -> Result { + Ok(v8::ToEnvoyWebSocketMessage { + data: x.data, + binary: x.binary, + }) +} + +pub fn convert_to_envoy_web_socket_close_v7_to_v8( + x: v7::ToEnvoyWebSocketClose, +) -> Result { + Ok(v8::ToEnvoyWebSocketClose { + code: x.code, + reason: x.reason, + }) +} + +pub fn convert_to_rivet_web_socket_open_v7_to_v8( + x: v7::ToRivetWebSocketOpen, +) -> Result { + Ok(v8::ToRivetWebSocketOpen { + can_hibernate: x.can_hibernate, + }) +} + +pub fn convert_to_rivet_web_socket_message_v7_to_v8( + x: v7::ToRivetWebSocketMessage, +) -> Result { + Ok(v8::ToRivetWebSocketMessage { + data: x.data, + binary: x.binary, + }) +} + +pub fn convert_to_rivet_web_socket_message_ack_v7_to_v8( + x: v7::ToRivetWebSocketMessageAck, +) -> Result { + Ok(v8::ToRivetWebSocketMessageAck { index: x.index }) +} + +pub fn convert_to_rivet_web_socket_close_v7_to_v8( + x: v7::ToRivetWebSocketClose, +) -> Result { + Ok(v8::ToRivetWebSocketClose { + code: x.code, + reason: x.reason, + hibernate: x.hibernate, + }) +} + +pub fn convert_to_rivet_tunnel_message_kind_v7_to_v8( + x: v7::ToRivetTunnelMessageKind, +) -> Result { + Ok(match x { + v7::ToRivetTunnelMessageKind::ToRivetResponseStart(v) => { + v8::ToRivetTunnelMessageKind::ToRivetResponseStart( + convert_to_rivet_response_start_v7_to_v8(v)?, + ) + } + v7::ToRivetTunnelMessageKind::ToRivetResponseChunk(v) => { + v8::ToRivetTunnelMessageKind::ToRivetResponseChunk( + convert_to_rivet_response_chunk_v7_to_v8(v)?, + ) + } + v7::ToRivetTunnelMessageKind::ToRivetResponseAbort(v) => { + v8::ToRivetTunnelMessageKind::ToRivetResponseAbort( + convert_to_rivet_response_abort_v7_to_v8(v)?, + ) + } + v7::ToRivetTunnelMessageKind::ToRivetWebSocketOpen(v) => { + v8::ToRivetTunnelMessageKind::ToRivetWebSocketOpen( + convert_to_rivet_web_socket_open_v7_to_v8(v)?, + ) + } + v7::ToRivetTunnelMessageKind::ToRivetWebSocketMessage(v) => { + v8::ToRivetTunnelMessageKind::ToRivetWebSocketMessage( + convert_to_rivet_web_socket_message_v7_to_v8(v)?, + ) + } + v7::ToRivetTunnelMessageKind::ToRivetWebSocketMessageAck(v) => { + v8::ToRivetTunnelMessageKind::ToRivetWebSocketMessageAck( + convert_to_rivet_web_socket_message_ack_v7_to_v8(v)?, + ) + } + v7::ToRivetTunnelMessageKind::ToRivetWebSocketClose(v) => { + v8::ToRivetTunnelMessageKind::ToRivetWebSocketClose( + convert_to_rivet_web_socket_close_v7_to_v8(v)?, + ) + } + }) +} + +pub fn convert_to_rivet_tunnel_message_v7_to_v8( + x: v7::ToRivetTunnelMessage, +) -> Result { + Ok(v8::ToRivetTunnelMessage { + message_id: convert_message_id_v7_to_v8(x.message_id)?, + message_kind: convert_to_rivet_tunnel_message_kind_v7_to_v8(x.message_kind)?, + }) +} + +pub fn convert_to_envoy_tunnel_message_kind_v7_to_v8( + x: v7::ToEnvoyTunnelMessageKind, +) -> Result { + Ok(match x { + v7::ToEnvoyTunnelMessageKind::ToEnvoyRequestStart(v) => { + v8::ToEnvoyTunnelMessageKind::ToEnvoyRequestStart( + convert_to_envoy_request_start_v7_to_v8(v)?, + ) + } + v7::ToEnvoyTunnelMessageKind::ToEnvoyRequestChunk(v) => { + v8::ToEnvoyTunnelMessageKind::ToEnvoyRequestChunk( + convert_to_envoy_request_chunk_v7_to_v8(v)?, + ) + } + v7::ToEnvoyTunnelMessageKind::ToEnvoyRequestAbort(v) => { + v8::ToEnvoyTunnelMessageKind::ToEnvoyRequestAbort( + convert_to_envoy_request_abort_v7_to_v8(v)?, + ) + } + v7::ToEnvoyTunnelMessageKind::ToEnvoyWebSocketOpen(v) => { + v8::ToEnvoyTunnelMessageKind::ToEnvoyWebSocketOpen( + convert_to_envoy_web_socket_open_v7_to_v8(v)?, + ) + } + v7::ToEnvoyTunnelMessageKind::ToEnvoyWebSocketMessage(v) => { + v8::ToEnvoyTunnelMessageKind::ToEnvoyWebSocketMessage( + convert_to_envoy_web_socket_message_v7_to_v8(v)?, + ) + } + v7::ToEnvoyTunnelMessageKind::ToEnvoyWebSocketClose(v) => { + v8::ToEnvoyTunnelMessageKind::ToEnvoyWebSocketClose( + convert_to_envoy_web_socket_close_v7_to_v8(v)?, + ) + } + }) +} + +pub fn convert_to_envoy_tunnel_message_v7_to_v8( + x: v7::ToEnvoyTunnelMessage, +) -> Result { + Ok(v8::ToEnvoyTunnelMessage { + message_id: convert_message_id_v7_to_v8(x.message_id)?, + message_kind: convert_to_envoy_tunnel_message_kind_v7_to_v8(x.message_kind)?, + }) +} + +pub fn convert_to_envoy_ping_v7_to_v8(x: v7::ToEnvoyPing) -> Result { + Ok(v8::ToEnvoyPing { ts: x.ts }) +} + +pub fn convert_to_rivet_metadata_v7_to_v8(x: v7::ToRivetMetadata) -> Result { + Ok(v8::ToRivetMetadata { + prepopulate_actor_names: x + .prepopulate_actor_names + .map(|v| { + v.into_iter() + .map(|(k, v)| -> Result<_> { Ok((k, convert_actor_name_v7_to_v8(v)?)) }) + .collect::>() + }) + .transpose()?, + metadata: x.metadata, + }) +} + +pub fn convert_to_rivet_events_v7_to_v8(x: v7::ToRivetEvents) -> Result { + Ok(x.into_iter() + .map(|v| convert_event_wrapper_v7_to_v8(v)) + .collect::>>()?) +} + +pub fn convert_to_rivet_ack_commands_v7_to_v8( + x: v7::ToRivetAckCommands, +) -> Result { + Ok(v8::ToRivetAckCommands { + last_command_checkpoints: x + .last_command_checkpoints + .into_iter() + .map(|v| convert_actor_checkpoint_v7_to_v8(v)) + .collect::>>()?, + }) +} + +pub fn convert_to_rivet_pong_v7_to_v8(x: v7::ToRivetPong) -> Result { + Ok(v8::ToRivetPong { ts: x.ts }) +} + +pub fn convert_to_rivet_kv_request_v7_to_v8( + x: v7::ToRivetKvRequest, +) -> Result { + Ok(v8::ToRivetKvRequest { + actor_id: x.actor_id, + request_id: x.request_id, + data: convert_kv_request_data_v7_to_v8(x.data)?, + }) +} + +pub fn convert_to_rivet_sqlite_get_pages_request_v7_to_v8( + x: v7::ToRivetSqliteGetPagesRequest, +) -> Result { + Ok(v8::ToRivetSqliteGetPagesRequest { + request_id: x.request_id, + data: convert_sqlite_get_pages_request_v7_to_v8(x.data)?, + }) +} + +pub fn convert_to_rivet_sqlite_commit_request_v7_to_v8( + x: v7::ToRivetSqliteCommitRequest, +) -> Result { + Ok(v8::ToRivetSqliteCommitRequest { + request_id: x.request_id, + data: convert_sqlite_commit_request_v7_to_v8(x.data)?, + }) +} + +pub fn convert_to_rivet_sqlite_exec_request_v7_to_v8( + x: v7::ToRivetSqliteExecRequest, +) -> Result { + Ok(v8::ToRivetSqliteExecRequest { + request_id: x.request_id, + data: convert_sqlite_exec_request_v7_to_v8(x.data)?, + }) +} + +pub fn convert_to_rivet_sqlite_execute_request_v7_to_v8( + x: v7::ToRivetSqliteExecuteRequest, +) -> Result { + Ok(v8::ToRivetSqliteExecuteRequest { + request_id: x.request_id, + data: convert_sqlite_execute_request_v7_to_v8(x.data)?, + }) +} + +pub fn convert_to_rivet_sqlite_execute_batch_request_v7_to_v8( + x: v7::ToRivetSqliteExecuteBatchRequest, +) -> Result { + Ok(v8::ToRivetSqliteExecuteBatchRequest { + request_id: x.request_id, + data: convert_sqlite_execute_batch_request_v7_to_v8(x.data)?, + }) +} + +pub fn convert_to_rivet_v7_to_v8(x: v7::ToRivet) -> Result { + Ok(match x { + v7::ToRivet::ToRivetMetadata(v) => { + v8::ToRivet::ToRivetMetadata(convert_to_rivet_metadata_v7_to_v8(v)?) + } + v7::ToRivet::ToRivetEvents(v) => { + v8::ToRivet::ToRivetEvents(convert_to_rivet_events_v7_to_v8(v)?) + } + v7::ToRivet::ToRivetAckCommands(v) => { + v8::ToRivet::ToRivetAckCommands(convert_to_rivet_ack_commands_v7_to_v8(v)?) + } + v7::ToRivet::ToRivetStopping => v8::ToRivet::ToRivetStopping, + v7::ToRivet::ToRivetPong(v) => v8::ToRivet::ToRivetPong(convert_to_rivet_pong_v7_to_v8(v)?), + v7::ToRivet::ToRivetKvRequest(v) => { + v8::ToRivet::ToRivetKvRequest(convert_to_rivet_kv_request_v7_to_v8(v)?) + } + v7::ToRivet::ToRivetTunnelMessage(v) => { + v8::ToRivet::ToRivetTunnelMessage(convert_to_rivet_tunnel_message_v7_to_v8(v)?) + } + v7::ToRivet::ToRivetSqliteGetPagesRequest(v) => v8::ToRivet::ToRivetSqliteGetPagesRequest( + convert_to_rivet_sqlite_get_pages_request_v7_to_v8(v)?, + ), + v7::ToRivet::ToRivetSqliteCommitRequest(v) => v8::ToRivet::ToRivetSqliteCommitRequest( + convert_to_rivet_sqlite_commit_request_v7_to_v8(v)?, + ), + v7::ToRivet::ToRivetSqliteExecRequest(v) => { + v8::ToRivet::ToRivetSqliteExecRequest(convert_to_rivet_sqlite_exec_request_v7_to_v8(v)?) + } + v7::ToRivet::ToRivetSqliteExecuteRequest(v) => v8::ToRivet::ToRivetSqliteExecuteRequest( + convert_to_rivet_sqlite_execute_request_v7_to_v8(v)?, + ), + v7::ToRivet::ToRivetSqliteExecuteBatchRequest(v) => { + v8::ToRivet::ToRivetSqliteExecuteBatchRequest( + convert_to_rivet_sqlite_execute_batch_request_v7_to_v8(v)?, + ) + } + }) +} + +pub fn convert_protocol_metadata_v7_to_v8(x: v7::ProtocolMetadata) -> Result { + Ok(v8::ProtocolMetadata { + envoy_lost_threshold: x.envoy_lost_threshold, + actor_stop_threshold: x.actor_stop_threshold, + max_response_payload_size: x.max_response_payload_size, + }) +} + +pub fn convert_to_envoy_init_v7_to_v8(x: v7::ToEnvoyInit) -> Result { + Ok(v8::ToEnvoyInit { + metadata: convert_protocol_metadata_v7_to_v8(x.metadata)?, + }) +} + +pub fn convert_to_envoy_commands_v7_to_v8(x: v7::ToEnvoyCommands) -> Result { + Ok(x.into_iter() + .map(|v| convert_command_wrapper_v7_to_v8(v)) + .collect::>>()?) +} + +pub fn convert_to_envoy_ack_events_v7_to_v8( + x: v7::ToEnvoyAckEvents, +) -> Result { + Ok(v8::ToEnvoyAckEvents { + last_event_checkpoints: x + .last_event_checkpoints + .into_iter() + .map(|v| convert_actor_checkpoint_v7_to_v8(v)) + .collect::>>()?, + }) +} + +pub fn convert_to_envoy_kv_response_v7_to_v8( + x: v7::ToEnvoyKvResponse, +) -> Result { + Ok(v8::ToEnvoyKvResponse { + request_id: x.request_id, + data: convert_kv_response_data_v7_to_v8(x.data)?, + }) +} + +pub fn convert_to_envoy_sqlite_get_pages_response_v7_to_v8( + x: v7::ToEnvoySqliteGetPagesResponse, +) -> Result { + Ok(v8::ToEnvoySqliteGetPagesResponse { + request_id: x.request_id, + data: convert_sqlite_get_pages_response_v7_to_v8(x.data)?, + }) +} + +pub fn convert_to_envoy_sqlite_commit_response_v7_to_v8( + x: v7::ToEnvoySqliteCommitResponse, +) -> Result { + Ok(v8::ToEnvoySqliteCommitResponse { + request_id: x.request_id, + data: convert_sqlite_commit_response_v7_to_v8(x.data)?, + }) +} + +pub fn convert_to_envoy_sqlite_exec_response_v7_to_v8( + x: v7::ToEnvoySqliteExecResponse, +) -> Result { + Ok(v8::ToEnvoySqliteExecResponse { + request_id: x.request_id, + data: convert_sqlite_exec_response_v7_to_v8(x.data)?, + }) +} + +pub fn convert_to_envoy_sqlite_execute_response_v7_to_v8( + x: v7::ToEnvoySqliteExecuteResponse, +) -> Result { + Ok(v8::ToEnvoySqliteExecuteResponse { + request_id: x.request_id, + data: convert_sqlite_execute_response_v7_to_v8(x.data)?, + }) +} + +pub fn convert_to_envoy_sqlite_execute_batch_response_v7_to_v8( + x: v7::ToEnvoySqliteExecuteBatchResponse, +) -> Result { + Ok(v8::ToEnvoySqliteExecuteBatchResponse { + request_id: x.request_id, + data: convert_sqlite_execute_batch_response_v7_to_v8(x.data)?, + }) +} + +pub fn convert_to_envoy_v7_to_v8(x: v7::ToEnvoy) -> Result { + Ok(match x { + v7::ToEnvoy::ToEnvoyInit(v) => v8::ToEnvoy::ToEnvoyInit(convert_to_envoy_init_v7_to_v8(v)?), + v7::ToEnvoy::ToEnvoyCommands(v) => { + v8::ToEnvoy::ToEnvoyCommands(convert_to_envoy_commands_v7_to_v8(v)?) + } + v7::ToEnvoy::ToEnvoyAckEvents(v) => { + v8::ToEnvoy::ToEnvoyAckEvents(convert_to_envoy_ack_events_v7_to_v8(v)?) + } + v7::ToEnvoy::ToEnvoyKvResponse(v) => { + v8::ToEnvoy::ToEnvoyKvResponse(convert_to_envoy_kv_response_v7_to_v8(v)?) + } + v7::ToEnvoy::ToEnvoyTunnelMessage(v) => { + v8::ToEnvoy::ToEnvoyTunnelMessage(convert_to_envoy_tunnel_message_v7_to_v8(v)?) + } + v7::ToEnvoy::ToEnvoyPing(v) => v8::ToEnvoy::ToEnvoyPing(convert_to_envoy_ping_v7_to_v8(v)?), + v7::ToEnvoy::ToEnvoySqliteGetPagesResponse(v) => { + v8::ToEnvoy::ToEnvoySqliteGetPagesResponse( + convert_to_envoy_sqlite_get_pages_response_v7_to_v8(v)?, + ) + } + v7::ToEnvoy::ToEnvoySqliteCommitResponse(v) => v8::ToEnvoy::ToEnvoySqliteCommitResponse( + convert_to_envoy_sqlite_commit_response_v7_to_v8(v)?, + ), + v7::ToEnvoy::ToEnvoySqliteExecResponse(v) => v8::ToEnvoy::ToEnvoySqliteExecResponse( + convert_to_envoy_sqlite_exec_response_v7_to_v8(v)?, + ), + v7::ToEnvoy::ToEnvoySqliteExecuteResponse(v) => v8::ToEnvoy::ToEnvoySqliteExecuteResponse( + convert_to_envoy_sqlite_execute_response_v7_to_v8(v)?, + ), + v7::ToEnvoy::ToEnvoySqliteExecuteBatchResponse(v) => { + v8::ToEnvoy::ToEnvoySqliteExecuteBatchResponse( + convert_to_envoy_sqlite_execute_batch_response_v7_to_v8(v)?, + ) + } + }) +} + +pub fn convert_to_envoy_conn_ping_v7_to_v8(x: v7::ToEnvoyConnPing) -> Result { + Ok(v8::ToEnvoyConnPing { + gateway_id: x.gateway_id, + request_id: x.request_id, + ts: x.ts, + }) +} + +pub fn convert_to_envoy_conn_v7_to_v8(x: v7::ToEnvoyConn) -> Result { + Ok(match x { + v7::ToEnvoyConn::ToEnvoyConnPing(v) => { + v8::ToEnvoyConn::ToEnvoyConnPing(convert_to_envoy_conn_ping_v7_to_v8(v)?) + } + v7::ToEnvoyConn::ToEnvoyConnClose => v8::ToEnvoyConn::ToEnvoyConnClose, + v7::ToEnvoyConn::ToEnvoyCommands(v) => { + v8::ToEnvoyConn::ToEnvoyCommands(convert_to_envoy_commands_v7_to_v8(v)?) + } + v7::ToEnvoyConn::ToEnvoyAckEvents(v) => { + v8::ToEnvoyConn::ToEnvoyAckEvents(convert_to_envoy_ack_events_v7_to_v8(v)?) + } + v7::ToEnvoyConn::ToEnvoyTunnelMessage(v) => { + v8::ToEnvoyConn::ToEnvoyTunnelMessage(convert_to_envoy_tunnel_message_v7_to_v8(v)?) + } + }) +} + +pub fn convert_to_gateway_pong_v7_to_v8(x: v7::ToGatewayPong) -> Result { + Ok(v8::ToGatewayPong { + request_id: x.request_id, + ts: x.ts, + }) +} + +pub fn convert_to_gateway_v7_to_v8(x: v7::ToGateway) -> Result { + Ok(match x { + v7::ToGateway::ToGatewayPong(v) => { + v8::ToGateway::ToGatewayPong(convert_to_gateway_pong_v7_to_v8(v)?) + } + v7::ToGateway::ToRivetTunnelMessage(v) => { + v8::ToGateway::ToRivetTunnelMessage(convert_to_rivet_tunnel_message_v7_to_v8(v)?) + } + }) +} + +pub fn convert_to_outbound_actor_start_v7_to_v8( + x: v7::ToOutboundActorStart, +) -> Result { + Ok(v8::ToOutboundActorStart { + namespace_id: x.namespace_id, + pool_name: x.pool_name, + checkpoint: convert_actor_checkpoint_v7_to_v8(x.checkpoint)?, + actor_config: convert_actor_config_v7_to_v8(x.actor_config)?, + }) +} + +pub fn convert_to_outbound_v7_to_v8(x: v7::ToOutbound) -> Result { + Ok(match x { + v7::ToOutbound::ToOutboundActorStart(v) => { + v8::ToOutbound::ToOutboundActorStart(convert_to_outbound_actor_start_v7_to_v8(v)?) + } + }) +} diff --git a/engine/sdks/rust/envoy-protocol/src/versioned/v8_to_v7.rs b/engine/sdks/rust/envoy-protocol/src/versioned/v8_to_v7.rs new file mode 100644 index 0000000000..583133d1fb --- /dev/null +++ b/engine/sdks/rust/envoy-protocol/src/versioned/v8_to_v7.rs @@ -0,0 +1,1238 @@ +// from: v8.bare, to: v7.bare + +#![allow(dead_code, unused_variables)] + +use anyhow::Result; + +use crate::generated::{v7, v8}; + +pub fn convert_kv_metadata_v8_to_v7(x: v8::KvMetadata) -> Result { + Ok(v7::KvMetadata { + version: x.version, + update_ts: x.update_ts, + }) +} + +pub fn convert_kv_list_range_query_v8_to_v7( + x: v8::KvListRangeQuery, +) -> Result { + Ok(v7::KvListRangeQuery { + start: x.start, + end: x.end, + exclusive: x.exclusive, + }) +} + +pub fn convert_kv_list_prefix_query_v8_to_v7( + x: v8::KvListPrefixQuery, +) -> Result { + Ok(v7::KvListPrefixQuery { key: x.key }) +} + +pub fn convert_kv_list_query_v8_to_v7(x: v8::KvListQuery) -> Result { + Ok(match x { + v8::KvListQuery::KvListAllQuery => v7::KvListQuery::KvListAllQuery, + v8::KvListQuery::KvListRangeQuery(v) => { + v7::KvListQuery::KvListRangeQuery(convert_kv_list_range_query_v8_to_v7(v)?) + } + v8::KvListQuery::KvListPrefixQuery(v) => { + v7::KvListQuery::KvListPrefixQuery(convert_kv_list_prefix_query_v8_to_v7(v)?) + } + }) +} + +pub fn convert_kv_get_request_v8_to_v7(x: v8::KvGetRequest) -> Result { + Ok(v7::KvGetRequest { keys: x.keys }) +} + +pub fn convert_kv_list_request_v8_to_v7(x: v8::KvListRequest) -> Result { + Ok(v7::KvListRequest { + query: convert_kv_list_query_v8_to_v7(x.query)?, + reverse: x.reverse, + limit: x.limit, + }) +} + +pub fn convert_kv_put_request_v8_to_v7(x: v8::KvPutRequest) -> Result { + Ok(v7::KvPutRequest { + keys: x.keys, + values: x.values, + }) +} + +pub fn convert_kv_delete_request_v8_to_v7(x: v8::KvDeleteRequest) -> Result { + Ok(v7::KvDeleteRequest { keys: x.keys }) +} + +pub fn convert_kv_delete_range_request_v8_to_v7( + x: v8::KvDeleteRangeRequest, +) -> Result { + Ok(v7::KvDeleteRangeRequest { + start: x.start, + end: x.end, + }) +} + +pub fn convert_kv_error_response_v8_to_v7(x: v8::KvErrorResponse) -> Result { + Ok(v7::KvErrorResponse { message: x.message }) +} + +pub fn convert_kv_get_response_v8_to_v7(x: v8::KvGetResponse) -> Result { + Ok(v7::KvGetResponse { + keys: x.keys, + values: x.values, + metadata: x + .metadata + .into_iter() + .map(|v| convert_kv_metadata_v8_to_v7(v)) + .collect::>>()?, + }) +} + +pub fn convert_kv_list_response_v8_to_v7(x: v8::KvListResponse) -> Result { + Ok(v7::KvListResponse { + keys: x.keys, + values: x.values, + metadata: x + .metadata + .into_iter() + .map(|v| convert_kv_metadata_v8_to_v7(v)) + .collect::>>()?, + }) +} + +pub fn convert_kv_request_data_v8_to_v7(x: v8::KvRequestData) -> Result { + Ok(match x { + v8::KvRequestData::KvGetRequest(v) => { + v7::KvRequestData::KvGetRequest(convert_kv_get_request_v8_to_v7(v)?) + } + v8::KvRequestData::KvListRequest(v) => { + v7::KvRequestData::KvListRequest(convert_kv_list_request_v8_to_v7(v)?) + } + v8::KvRequestData::KvPutRequest(v) => { + v7::KvRequestData::KvPutRequest(convert_kv_put_request_v8_to_v7(v)?) + } + v8::KvRequestData::KvDeleteRequest(v) => { + v7::KvRequestData::KvDeleteRequest(convert_kv_delete_request_v8_to_v7(v)?) + } + v8::KvRequestData::KvDeleteRangeRequest(v) => { + v7::KvRequestData::KvDeleteRangeRequest(convert_kv_delete_range_request_v8_to_v7(v)?) + } + v8::KvRequestData::KvDropRequest => v7::KvRequestData::KvDropRequest, + }) +} + +pub fn convert_kv_response_data_v8_to_v7(x: v8::KvResponseData) -> Result { + Ok(match x { + v8::KvResponseData::KvErrorResponse(v) => { + v7::KvResponseData::KvErrorResponse(convert_kv_error_response_v8_to_v7(v)?) + } + v8::KvResponseData::KvGetResponse(v) => { + v7::KvResponseData::KvGetResponse(convert_kv_get_response_v8_to_v7(v)?) + } + v8::KvResponseData::KvListResponse(v) => { + v7::KvResponseData::KvListResponse(convert_kv_list_response_v8_to_v7(v)?) + } + v8::KvResponseData::KvPutResponse => v7::KvResponseData::KvPutResponse, + v8::KvResponseData::KvDeleteResponse => v7::KvResponseData::KvDeleteResponse, + v8::KvResponseData::KvDropResponse => v7::KvResponseData::KvDropResponse, + }) +} + +pub fn convert_sqlite_dirty_page_v8_to_v7(x: v8::SqliteDirtyPage) -> Result { + Ok(v7::SqliteDirtyPage { + pgno: x.pgno, + bytes: x.bytes, + }) +} + +pub fn convert_sqlite_fetched_page_v8_to_v7( + x: v8::SqliteFetchedPage, +) -> Result { + Ok(v7::SqliteFetchedPage { + pgno: x.pgno, + bytes: x.bytes, + }) +} + +pub fn convert_sqlite_get_pages_request_v8_to_v7( + x: v8::SqliteGetPagesRequest, +) -> Result { + Ok(v7::SqliteGetPagesRequest { + actor_id: x.actor_id, + pgnos: x.pgnos, + expected_generation: x.expected_generation, + expected_head_txid: x.expected_head_txid, + }) +} + +pub fn convert_sqlite_get_pages_ok_v8_to_v7( + x: v8::SqliteGetPagesOk, +) -> Result { + Ok(v7::SqliteGetPagesOk { + pages: x + .pages + .into_iter() + .map(|v| convert_sqlite_fetched_page_v8_to_v7(v)) + .collect::>>()?, + head_txid: x.head_txid, + }) +} + +pub fn convert_sqlite_error_response_v8_to_v7( + x: v8::SqliteErrorResponse, +) -> Result { + Ok(v7::SqliteErrorResponse { + group: x.group, + code: x.code, + message: x.message, + }) +} + +pub fn convert_sqlite_get_pages_response_v8_to_v7( + x: v8::SqliteGetPagesResponse, +) -> Result { + Ok(match x { + v8::SqliteGetPagesResponse::SqliteGetPagesOk(v) => { + v7::SqliteGetPagesResponse::SqliteGetPagesOk(convert_sqlite_get_pages_ok_v8_to_v7(v)?) + } + v8::SqliteGetPagesResponse::SqliteErrorResponse(v) => { + v7::SqliteGetPagesResponse::SqliteErrorResponse(convert_sqlite_error_response_v8_to_v7( + v, + )?) + } + }) +} + +pub fn convert_sqlite_commit_request_v8_to_v7( + x: v8::SqliteCommitRequest, +) -> Result { + Ok(v7::SqliteCommitRequest { + actor_id: x.actor_id, + dirty_pages: x + .dirty_pages + .into_iter() + .map(|v| convert_sqlite_dirty_page_v8_to_v7(v)) + .collect::>>()?, + db_size_pages: x.db_size_pages, + now_ms: x.now_ms, + expected_generation: x.expected_generation, + expected_head_txid: x.expected_head_txid, + }) +} + +pub fn convert_sqlite_commit_ok_v8_to_v7(x: v8::SqliteCommitOk) -> Result { + Ok(v7::SqliteCommitOk { + head_txid: x.head_txid, + }) +} + +pub fn convert_sqlite_commit_response_v8_to_v7( + x: v8::SqliteCommitResponse, +) -> Result { + Ok(match x { + v8::SqliteCommitResponse::SqliteCommitOk(v) => { + v7::SqliteCommitResponse::SqliteCommitOk(convert_sqlite_commit_ok_v8_to_v7(v)?) + } + v8::SqliteCommitResponse::SqliteErrorResponse(v) => { + v7::SqliteCommitResponse::SqliteErrorResponse(convert_sqlite_error_response_v8_to_v7( + v, + )?) + } + }) +} + +pub fn convert_sqlite_value_integer_v8_to_v7( + x: v8::SqliteValueInteger, +) -> Result { + Ok(v7::SqliteValueInteger { value: x.value }) +} + +pub fn convert_sqlite_value_float_v8_to_v7( + x: v8::SqliteValueFloat, +) -> Result { + Ok(v7::SqliteValueFloat { value: x.value }) +} + +pub fn convert_sqlite_value_text_v8_to_v7(x: v8::SqliteValueText) -> Result { + Ok(v7::SqliteValueText { value: x.value }) +} + +pub fn convert_sqlite_value_blob_v8_to_v7(x: v8::SqliteValueBlob) -> Result { + Ok(v7::SqliteValueBlob { value: x.value }) +} + +pub fn convert_sqlite_bind_param_v8_to_v7(x: v8::SqliteBindParam) -> Result { + Ok(match x { + v8::SqliteBindParam::SqliteValueNull => v7::SqliteBindParam::SqliteValueNull, + v8::SqliteBindParam::SqliteValueInteger(v) => { + v7::SqliteBindParam::SqliteValueInteger(convert_sqlite_value_integer_v8_to_v7(v)?) + } + v8::SqliteBindParam::SqliteValueFloat(v) => { + v7::SqliteBindParam::SqliteValueFloat(convert_sqlite_value_float_v8_to_v7(v)?) + } + v8::SqliteBindParam::SqliteValueText(v) => { + v7::SqliteBindParam::SqliteValueText(convert_sqlite_value_text_v8_to_v7(v)?) + } + v8::SqliteBindParam::SqliteValueBlob(v) => { + v7::SqliteBindParam::SqliteValueBlob(convert_sqlite_value_blob_v8_to_v7(v)?) + } + }) +} + +pub fn convert_sqlite_column_value_v8_to_v7( + x: v8::SqliteColumnValue, +) -> Result { + Ok(match x { + v8::SqliteColumnValue::SqliteValueNull => v7::SqliteColumnValue::SqliteValueNull, + v8::SqliteColumnValue::SqliteValueInteger(v) => { + v7::SqliteColumnValue::SqliteValueInteger(convert_sqlite_value_integer_v8_to_v7(v)?) + } + v8::SqliteColumnValue::SqliteValueFloat(v) => { + v7::SqliteColumnValue::SqliteValueFloat(convert_sqlite_value_float_v8_to_v7(v)?) + } + v8::SqliteColumnValue::SqliteValueText(v) => { + v7::SqliteColumnValue::SqliteValueText(convert_sqlite_value_text_v8_to_v7(v)?) + } + v8::SqliteColumnValue::SqliteValueBlob(v) => { + v7::SqliteColumnValue::SqliteValueBlob(convert_sqlite_value_blob_v8_to_v7(v)?) + } + }) +} + +pub fn convert_sqlite_query_result_v8_to_v7( + x: v8::SqliteQueryResult, +) -> Result { + Ok(v7::SqliteQueryResult { + columns: x.columns, + rows: x + .rows + .into_iter() + .map(|v| { + v.into_iter() + .map(|v| convert_sqlite_column_value_v8_to_v7(v)) + .collect::>>() + }) + .collect::>>()?, + }) +} + +pub fn convert_sqlite_execute_result_v8_to_v7( + x: v8::SqliteExecuteResult, +) -> Result { + Ok(v7::SqliteExecuteResult { + columns: x.columns, + rows: x + .rows + .into_iter() + .map(|v| { + v.into_iter() + .map(|v| convert_sqlite_column_value_v8_to_v7(v)) + .collect::>>() + }) + .collect::>>()?, + changes: x.changes, + last_insert_row_id: x.last_insert_row_id, + }) +} + +pub fn convert_sqlite_exec_request_v8_to_v7( + x: v8::SqliteExecRequest, +) -> Result { + Ok(v7::SqliteExecRequest { + namespace_id: x.namespace_id, + actor_id: x.actor_id, + generation: x.generation, + sql: x.sql, + }) +} + +pub fn convert_sqlite_execute_request_v8_to_v7( + x: v8::SqliteExecuteRequest, +) -> Result { + Ok(v7::SqliteExecuteRequest { + namespace_id: x.namespace_id, + actor_id: x.actor_id, + generation: x.generation, + sql: x.sql, + params: x + .params + .map(|v| { + v.into_iter() + .map(|v| convert_sqlite_bind_param_v8_to_v7(v)) + .collect::>>() + }) + .transpose()?, + }) +} + +pub fn convert_sqlite_batch_statement_v8_to_v7( + x: v8::SqliteBatchStatement, +) -> Result { + Ok(v7::SqliteBatchStatement { + sql: x.sql, + params: x + .params + .map(|v| { + v.into_iter() + .map(|v| convert_sqlite_bind_param_v8_to_v7(v)) + .collect::>>() + }) + .transpose()?, + }) +} + +pub fn convert_sqlite_execute_batch_request_v8_to_v7( + x: v8::SqliteExecuteBatchRequest, +) -> Result { + Ok(v7::SqliteExecuteBatchRequest { + namespace_id: x.namespace_id, + actor_id: x.actor_id, + generation: x.generation, + statements: x + .statements + .into_iter() + .map(|v| convert_sqlite_batch_statement_v8_to_v7(v)) + .collect::>>()?, + }) +} + +pub fn convert_sqlite_exec_ok_v8_to_v7(x: v8::SqliteExecOk) -> Result { + Ok(v7::SqliteExecOk { + result: convert_sqlite_query_result_v8_to_v7(x.result)?, + }) +} + +pub fn convert_sqlite_execute_ok_v8_to_v7(x: v8::SqliteExecuteOk) -> Result { + Ok(v7::SqliteExecuteOk { + result: convert_sqlite_execute_result_v8_to_v7(x.result)?, + }) +} + +pub fn convert_sqlite_execute_batch_ok_v8_to_v7( + x: v8::SqliteExecuteBatchOk, +) -> Result { + Ok(v7::SqliteExecuteBatchOk { + results: x + .results + .into_iter() + .map(|v| convert_sqlite_execute_result_v8_to_v7(v)) + .collect::>>()?, + }) +} + +pub fn convert_sqlite_exec_response_v8_to_v7( + x: v8::SqliteExecResponse, +) -> Result { + Ok(match x { + v8::SqliteExecResponse::SqliteExecOk(v) => { + v7::SqliteExecResponse::SqliteExecOk(convert_sqlite_exec_ok_v8_to_v7(v)?) + } + v8::SqliteExecResponse::SqliteErrorResponse(v) => { + v7::SqliteExecResponse::SqliteErrorResponse(convert_sqlite_error_response_v8_to_v7(v)?) + } + }) +} + +pub fn convert_sqlite_execute_response_v8_to_v7( + x: v8::SqliteExecuteResponse, +) -> Result { + Ok(match x { + v8::SqliteExecuteResponse::SqliteExecuteOk(v) => { + v7::SqliteExecuteResponse::SqliteExecuteOk(convert_sqlite_execute_ok_v8_to_v7(v)?) + } + v8::SqliteExecuteResponse::SqliteErrorResponse(v) => { + v7::SqliteExecuteResponse::SqliteErrorResponse(convert_sqlite_error_response_v8_to_v7( + v, + )?) + } + }) +} + +pub fn convert_sqlite_execute_batch_response_v8_to_v7( + x: v8::SqliteExecuteBatchResponse, +) -> Result { + Ok(match x { + v8::SqliteExecuteBatchResponse::SqliteExecuteBatchOk(v) => { + v7::SqliteExecuteBatchResponse::SqliteExecuteBatchOk( + convert_sqlite_execute_batch_ok_v8_to_v7(v)?, + ) + } + v8::SqliteExecuteBatchResponse::SqliteErrorResponse(v) => { + v7::SqliteExecuteBatchResponse::SqliteErrorResponse( + convert_sqlite_error_response_v8_to_v7(v)?, + ) + } + }) +} + +pub fn convert_stop_code_v8_to_v7(x: v8::StopCode) -> Result { + Ok(match x { + v8::StopCode::Ok => v7::StopCode::Ok, + v8::StopCode::Error => v7::StopCode::Error, + }) +} + +pub fn convert_actor_name_v8_to_v7(x: v8::ActorName) -> Result { + Ok(v7::ActorName { + metadata: x.metadata, + }) +} + +pub fn convert_actor_config_v8_to_v7(x: v8::ActorConfig) -> Result { + Ok(v7::ActorConfig { + name: x.name, + key: x.key, + create_ts: x.create_ts, + input: x.input, + }) +} + +pub fn convert_actor_checkpoint_v8_to_v7(x: v8::ActorCheckpoint) -> Result { + Ok(v7::ActorCheckpoint { + actor_id: x.actor_id, + generation: x.generation, + index: x.index, + }) +} + +pub fn convert_actor_intent_v8_to_v7(x: v8::ActorIntent) -> Result { + Ok(match x { + v8::ActorIntent::ActorIntentSleep => v7::ActorIntent::ActorIntentSleep, + v8::ActorIntent::ActorIntentStop => v7::ActorIntent::ActorIntentStop, + }) +} + +pub fn convert_actor_state_stopped_v8_to_v7( + x: v8::ActorStateStopped, +) -> Result { + Ok(v7::ActorStateStopped { + code: convert_stop_code_v8_to_v7(x.code)?, + message: x.message, + }) +} + +pub fn convert_actor_state_v8_to_v7(x: v8::ActorState) -> Result { + Ok(match x { + v8::ActorState::ActorStateRunning => v7::ActorState::ActorStateRunning, + v8::ActorState::ActorStateStopped(v) => { + v7::ActorState::ActorStateStopped(convert_actor_state_stopped_v8_to_v7(v)?) + } + }) +} + +pub fn convert_event_actor_intent_v8_to_v7( + x: v8::EventActorIntent, +) -> Result { + Ok(v7::EventActorIntent { + intent: convert_actor_intent_v8_to_v7(x.intent)?, + }) +} + +pub fn convert_event_actor_state_update_v8_to_v7( + x: v8::EventActorStateUpdate, +) -> Result { + Ok(v7::EventActorStateUpdate { + state: convert_actor_state_v8_to_v7(x.state)?, + }) +} + +pub fn convert_event_actor_set_alarm_v8_to_v7( + x: v8::EventActorSetAlarm, +) -> Result { + Ok(v7::EventActorSetAlarm { + alarm_ts: x.alarm_ts, + }) +} + +pub fn convert_event_v8_to_v7(x: v8::Event) -> Result { + Ok(match x { + v8::Event::EventActorIntent(v) => { + v7::Event::EventActorIntent(convert_event_actor_intent_v8_to_v7(v)?) + } + v8::Event::EventActorStateUpdate(v) => { + v7::Event::EventActorStateUpdate(convert_event_actor_state_update_v8_to_v7(v)?) + } + v8::Event::EventActorSetAlarm(v) => { + v7::Event::EventActorSetAlarm(convert_event_actor_set_alarm_v8_to_v7(v)?) + } + }) +} + +pub fn convert_event_wrapper_v8_to_v7(x: v8::EventWrapper) -> Result { + Ok(v7::EventWrapper { + checkpoint: convert_actor_checkpoint_v8_to_v7(x.checkpoint)?, + inner: convert_event_v8_to_v7(x.inner)?, + }) +} + +pub fn convert_preloaded_kv_entry_v8_to_v7( + x: v8::PreloadedKvEntry, +) -> Result { + Ok(v7::PreloadedKvEntry { + key: x.key, + value: x.value, + metadata: convert_kv_metadata_v8_to_v7(x.metadata)?, + }) +} + +pub fn convert_preloaded_kv_v8_to_v7(x: v8::PreloadedKv) -> Result { + Ok(v7::PreloadedKv { + entries: x + .entries + .into_iter() + .map(|v| convert_preloaded_kv_entry_v8_to_v7(v)) + .collect::>>()?, + requested_get_keys: x.requested_get_keys, + requested_prefixes: x.requested_prefixes, + }) +} + +pub fn convert_hibernating_request_v8_to_v7( + x: v8::HibernatingRequest, +) -> Result { + Ok(v7::HibernatingRequest { + gateway_id: x.gateway_id, + request_id: x.request_id, + }) +} + +pub fn convert_command_start_actor_v8_to_v7( + x: v8::CommandStartActor, +) -> Result { + Ok(v7::CommandStartActor { + config: convert_actor_config_v8_to_v7(x.config)?, + hibernating_requests: x + .hibernating_requests + .into_iter() + .map(|v| convert_hibernating_request_v8_to_v7(v)) + .collect::>>()?, + preloaded_kv: x + .preloaded_kv + .map(|v| convert_preloaded_kv_v8_to_v7(v)) + .transpose()?, + }) +} + +pub fn convert_stop_actor_reason_v8_to_v7(x: v8::StopActorReason) -> Result { + Ok(match x { + v8::StopActorReason::SleepIntent => v7::StopActorReason::SleepIntent, + v8::StopActorReason::StopIntent => v7::StopActorReason::StopIntent, + v8::StopActorReason::Destroy => v7::StopActorReason::Destroy, + v8::StopActorReason::GoingAway => v7::StopActorReason::GoingAway, + v8::StopActorReason::Lost => v7::StopActorReason::Lost, + }) +} + +pub fn convert_command_stop_actor_v8_to_v7( + x: v8::CommandStopActor, +) -> Result { + Ok(v7::CommandStopActor { + reason: convert_stop_actor_reason_v8_to_v7(x.reason)?, + }) +} + +pub fn convert_command_v8_to_v7(x: v8::Command) -> Result { + Ok(match x { + v8::Command::CommandStartActor(v) => { + v7::Command::CommandStartActor(convert_command_start_actor_v8_to_v7(v)?) + } + v8::Command::CommandStopActor(v) => { + v7::Command::CommandStopActor(convert_command_stop_actor_v8_to_v7(v)?) + } + }) +} + +pub fn convert_command_wrapper_v8_to_v7(x: v8::CommandWrapper) -> Result { + Ok(v7::CommandWrapper { + checkpoint: convert_actor_checkpoint_v8_to_v7(x.checkpoint)?, + inner: convert_command_v8_to_v7(x.inner)?, + }) +} + +pub fn convert_actor_command_key_data_v8_to_v7( + x: v8::ActorCommandKeyData, +) -> Result { + Ok(match x { + v8::ActorCommandKeyData::CommandStartActor(v) => { + v7::ActorCommandKeyData::CommandStartActor(convert_command_start_actor_v8_to_v7(v)?) + } + v8::ActorCommandKeyData::CommandStopActor(v) => { + v7::ActorCommandKeyData::CommandStopActor(convert_command_stop_actor_v8_to_v7(v)?) + } + }) +} + +pub fn convert_message_id_v8_to_v7(x: v8::MessageId) -> Result { + Ok(v7::MessageId { + gateway_id: x.gateway_id, + request_id: x.request_id, + message_index: x.message_index, + }) +} + +pub fn convert_to_envoy_request_start_v8_to_v7( + x: v8::ToEnvoyRequestStart, +) -> Result { + Ok(v7::ToEnvoyRequestStart { + actor_id: x.actor_id, + method: x.method, + path: x.path, + headers: x.headers, + body: x.body, + stream: x.stream, + }) +} + +pub fn convert_to_envoy_request_chunk_v8_to_v7( + x: v8::ToEnvoyRequestChunk, +) -> Result { + Ok(v7::ToEnvoyRequestChunk { + body: x.body, + finish: x.finish, + }) +} + +pub fn convert_http_stream_abort_reason_kind_v8_to_v7( + x: v8::HttpStreamAbortReasonKind, +) -> Result { + Ok(match x { + v8::HttpStreamAbortReasonKind::Unknown => v7::HttpStreamAbortReasonKind::Unknown, + v8::HttpStreamAbortReasonKind::ClientDisconnect => { + v7::HttpStreamAbortReasonKind::ClientDisconnect + } + v8::HttpStreamAbortReasonKind::HandlerError => v7::HttpStreamAbortReasonKind::HandlerError, + v8::HttpStreamAbortReasonKind::IdleTimeout => v7::HttpStreamAbortReasonKind::IdleTimeout, + v8::HttpStreamAbortReasonKind::Overloaded => v7::HttpStreamAbortReasonKind::Overloaded, + v8::HttpStreamAbortReasonKind::BodyTooLarge => v7::HttpStreamAbortReasonKind::BodyTooLarge, + v8::HttpStreamAbortReasonKind::OutOfMemory => v7::HttpStreamAbortReasonKind::OutOfMemory, + v8::HttpStreamAbortReasonKind::Shutdown => v7::HttpStreamAbortReasonKind::Shutdown, + v8::HttpStreamAbortReasonKind::InternalError => { + v7::HttpStreamAbortReasonKind::InternalError + } + }) +} + +pub fn convert_http_stream_abort_reason_v8_to_v7( + x: v8::HttpStreamAbortReason, +) -> Result { + Ok(v7::HttpStreamAbortReason { + kind: convert_http_stream_abort_reason_kind_v8_to_v7(x.kind)?, + detail: x.detail, + }) +} + +pub fn convert_to_envoy_request_abort_v8_to_v7( + x: v8::ToEnvoyRequestAbort, +) -> Result { + Ok(v7::ToEnvoyRequestAbort { + reason: convert_http_stream_abort_reason_v8_to_v7(x.reason)?, + }) +} + +pub fn convert_to_rivet_response_abort_v8_to_v7( + x: v8::ToRivetResponseAbort, +) -> Result { + Ok(v7::ToRivetResponseAbort { + reason: convert_http_stream_abort_reason_v8_to_v7(x.reason)?, + }) +} + +pub fn convert_to_rivet_response_start_v8_to_v7( + x: v8::ToRivetResponseStart, +) -> Result { + Ok(v7::ToRivetResponseStart { + status: x.status, + headers: x.headers, + body: x.body, + stream: x.stream, + }) +} + +pub fn convert_to_rivet_response_chunk_v8_to_v7( + x: v8::ToRivetResponseChunk, +) -> Result { + Ok(v7::ToRivetResponseChunk { + body: x.body, + finish: x.finish, + }) +} + +pub fn convert_to_envoy_web_socket_open_v8_to_v7( + x: v8::ToEnvoyWebSocketOpen, +) -> Result { + Ok(v7::ToEnvoyWebSocketOpen { + actor_id: x.actor_id, + path: x.path, + headers: x.headers, + }) +} + +pub fn convert_to_envoy_web_socket_message_v8_to_v7( + x: v8::ToEnvoyWebSocketMessage, +) -> Result { + Ok(v7::ToEnvoyWebSocketMessage { + data: x.data, + binary: x.binary, + }) +} + +pub fn convert_to_envoy_web_socket_close_v8_to_v7( + x: v8::ToEnvoyWebSocketClose, +) -> Result { + Ok(v7::ToEnvoyWebSocketClose { + code: x.code, + reason: x.reason, + }) +} + +pub fn convert_to_rivet_web_socket_open_v8_to_v7( + x: v8::ToRivetWebSocketOpen, +) -> Result { + Ok(v7::ToRivetWebSocketOpen { + can_hibernate: x.can_hibernate, + }) +} + +pub fn convert_to_rivet_web_socket_message_v8_to_v7( + x: v8::ToRivetWebSocketMessage, +) -> Result { + Ok(v7::ToRivetWebSocketMessage { + data: x.data, + binary: x.binary, + }) +} + +pub fn convert_to_rivet_web_socket_message_ack_v8_to_v7( + x: v8::ToRivetWebSocketMessageAck, +) -> Result { + Ok(v7::ToRivetWebSocketMessageAck { index: x.index }) +} + +pub fn convert_to_rivet_web_socket_close_v8_to_v7( + x: v8::ToRivetWebSocketClose, +) -> Result { + Ok(v7::ToRivetWebSocketClose { + code: x.code, + reason: x.reason, + hibernate: x.hibernate, + }) +} + +pub fn convert_to_rivet_tunnel_message_kind_v8_to_v7( + x: v8::ToRivetTunnelMessageKind, +) -> Result { + Ok(match x { + v8::ToRivetTunnelMessageKind::ToRivetResponseStart(v) => { + v7::ToRivetTunnelMessageKind::ToRivetResponseStart( + convert_to_rivet_response_start_v8_to_v7(v)?, + ) + } + v8::ToRivetTunnelMessageKind::ToRivetResponseChunk(v) => { + v7::ToRivetTunnelMessageKind::ToRivetResponseChunk( + convert_to_rivet_response_chunk_v8_to_v7(v)?, + ) + } + v8::ToRivetTunnelMessageKind::ToRivetResponseAbort(v) => { + v7::ToRivetTunnelMessageKind::ToRivetResponseAbort( + convert_to_rivet_response_abort_v8_to_v7(v)?, + ) + } + v8::ToRivetTunnelMessageKind::ToRivetWebSocketOpen(v) => { + v7::ToRivetTunnelMessageKind::ToRivetWebSocketOpen( + convert_to_rivet_web_socket_open_v8_to_v7(v)?, + ) + } + v8::ToRivetTunnelMessageKind::ToRivetWebSocketMessage(v) => { + v7::ToRivetTunnelMessageKind::ToRivetWebSocketMessage( + convert_to_rivet_web_socket_message_v8_to_v7(v)?, + ) + } + v8::ToRivetTunnelMessageKind::ToRivetWebSocketMessageAck(v) => { + v7::ToRivetTunnelMessageKind::ToRivetWebSocketMessageAck( + convert_to_rivet_web_socket_message_ack_v8_to_v7(v)?, + ) + } + v8::ToRivetTunnelMessageKind::ToRivetWebSocketClose(v) => { + v7::ToRivetTunnelMessageKind::ToRivetWebSocketClose( + convert_to_rivet_web_socket_close_v8_to_v7(v)?, + ) + } + }) +} + +pub fn convert_to_rivet_tunnel_message_v8_to_v7( + x: v8::ToRivetTunnelMessage, +) -> Result { + Ok(v7::ToRivetTunnelMessage { + message_id: convert_message_id_v8_to_v7(x.message_id)?, + message_kind: convert_to_rivet_tunnel_message_kind_v8_to_v7(x.message_kind)?, + }) +} + +pub fn convert_to_envoy_tunnel_message_kind_v8_to_v7( + x: v8::ToEnvoyTunnelMessageKind, +) -> Result { + Ok(match x { + v8::ToEnvoyTunnelMessageKind::ToEnvoyRequestStart(v) => { + v7::ToEnvoyTunnelMessageKind::ToEnvoyRequestStart( + convert_to_envoy_request_start_v8_to_v7(v)?, + ) + } + v8::ToEnvoyTunnelMessageKind::ToEnvoyRequestChunk(v) => { + v7::ToEnvoyTunnelMessageKind::ToEnvoyRequestChunk( + convert_to_envoy_request_chunk_v8_to_v7(v)?, + ) + } + v8::ToEnvoyTunnelMessageKind::ToEnvoyRequestAbort(v) => { + v7::ToEnvoyTunnelMessageKind::ToEnvoyRequestAbort( + convert_to_envoy_request_abort_v8_to_v7(v)?, + ) + } + v8::ToEnvoyTunnelMessageKind::ToEnvoyWebSocketOpen(v) => { + v7::ToEnvoyTunnelMessageKind::ToEnvoyWebSocketOpen( + convert_to_envoy_web_socket_open_v8_to_v7(v)?, + ) + } + v8::ToEnvoyTunnelMessageKind::ToEnvoyWebSocketMessage(v) => { + v7::ToEnvoyTunnelMessageKind::ToEnvoyWebSocketMessage( + convert_to_envoy_web_socket_message_v8_to_v7(v)?, + ) + } + v8::ToEnvoyTunnelMessageKind::ToEnvoyWebSocketClose(v) => { + v7::ToEnvoyTunnelMessageKind::ToEnvoyWebSocketClose( + convert_to_envoy_web_socket_close_v8_to_v7(v)?, + ) + } + }) +} + +pub fn convert_to_envoy_tunnel_message_v8_to_v7( + x: v8::ToEnvoyTunnelMessage, +) -> Result { + Ok(v7::ToEnvoyTunnelMessage { + message_id: convert_message_id_v8_to_v7(x.message_id)?, + message_kind: convert_to_envoy_tunnel_message_kind_v8_to_v7(x.message_kind)?, + }) +} + +pub fn convert_to_envoy_ping_v8_to_v7(x: v8::ToEnvoyPing) -> Result { + Ok(v7::ToEnvoyPing { ts: x.ts }) +} + +pub fn convert_to_rivet_metadata_v8_to_v7(x: v8::ToRivetMetadata) -> Result { + Ok(v7::ToRivetMetadata { + prepopulate_actor_names: x + .prepopulate_actor_names + .map(|v| { + v.into_iter() + .map(|(k, v)| -> Result<_> { Ok((k, convert_actor_name_v8_to_v7(v)?)) }) + .collect::>() + }) + .transpose()?, + metadata: x.metadata, + }) +} + +pub fn convert_to_rivet_events_v8_to_v7(x: v8::ToRivetEvents) -> Result { + Ok(x.into_iter() + .map(|v| convert_event_wrapper_v8_to_v7(v)) + .collect::>>()?) +} + +pub fn convert_to_rivet_ack_commands_v8_to_v7( + x: v8::ToRivetAckCommands, +) -> Result { + Ok(v7::ToRivetAckCommands { + last_command_checkpoints: x + .last_command_checkpoints + .into_iter() + .map(|v| convert_actor_checkpoint_v8_to_v7(v)) + .collect::>>()?, + }) +} + +pub fn convert_to_rivet_pong_v8_to_v7(x: v8::ToRivetPong) -> Result { + Ok(v7::ToRivetPong { ts: x.ts }) +} + +pub fn convert_to_rivet_kv_request_v8_to_v7( + x: v8::ToRivetKvRequest, +) -> Result { + Ok(v7::ToRivetKvRequest { + actor_id: x.actor_id, + request_id: x.request_id, + data: convert_kv_request_data_v8_to_v7(x.data)?, + }) +} + +pub fn convert_to_rivet_sqlite_get_pages_request_v8_to_v7( + x: v8::ToRivetSqliteGetPagesRequest, +) -> Result { + Ok(v7::ToRivetSqliteGetPagesRequest { + request_id: x.request_id, + data: convert_sqlite_get_pages_request_v8_to_v7(x.data)?, + }) +} + +pub fn convert_to_rivet_sqlite_commit_request_v8_to_v7( + x: v8::ToRivetSqliteCommitRequest, +) -> Result { + Ok(v7::ToRivetSqliteCommitRequest { + request_id: x.request_id, + data: convert_sqlite_commit_request_v8_to_v7(x.data)?, + }) +} + +pub fn convert_to_rivet_sqlite_exec_request_v8_to_v7( + x: v8::ToRivetSqliteExecRequest, +) -> Result { + Ok(v7::ToRivetSqliteExecRequest { + request_id: x.request_id, + data: convert_sqlite_exec_request_v8_to_v7(x.data)?, + }) +} + +pub fn convert_to_rivet_sqlite_execute_request_v8_to_v7( + x: v8::ToRivetSqliteExecuteRequest, +) -> Result { + Ok(v7::ToRivetSqliteExecuteRequest { + request_id: x.request_id, + data: convert_sqlite_execute_request_v8_to_v7(x.data)?, + }) +} + +pub fn convert_to_rivet_sqlite_execute_batch_request_v8_to_v7( + x: v8::ToRivetSqliteExecuteBatchRequest, +) -> Result { + Ok(v7::ToRivetSqliteExecuteBatchRequest { + request_id: x.request_id, + data: convert_sqlite_execute_batch_request_v8_to_v7(x.data)?, + }) +} + +pub fn convert_to_rivet_v8_to_v7(x: v8::ToRivet) -> Result { + Ok(match x { + v8::ToRivet::ToRivetMetadata(v) => { + v7::ToRivet::ToRivetMetadata(convert_to_rivet_metadata_v8_to_v7(v)?) + } + v8::ToRivet::ToRivetEvents(v) => { + v7::ToRivet::ToRivetEvents(convert_to_rivet_events_v8_to_v7(v)?) + } + v8::ToRivet::ToRivetAckCommands(v) => { + v7::ToRivet::ToRivetAckCommands(convert_to_rivet_ack_commands_v8_to_v7(v)?) + } + v8::ToRivet::ToRivetStopping => v7::ToRivet::ToRivetStopping, + v8::ToRivet::ToRivetPong(v) => v7::ToRivet::ToRivetPong(convert_to_rivet_pong_v8_to_v7(v)?), + v8::ToRivet::ToRivetKvRequest(v) => { + v7::ToRivet::ToRivetKvRequest(convert_to_rivet_kv_request_v8_to_v7(v)?) + } + v8::ToRivet::ToRivetTunnelMessage(v) => { + v7::ToRivet::ToRivetTunnelMessage(convert_to_rivet_tunnel_message_v8_to_v7(v)?) + } + v8::ToRivet::ToRivetSqliteGetPagesRequest(v) => v7::ToRivet::ToRivetSqliteGetPagesRequest( + convert_to_rivet_sqlite_get_pages_request_v8_to_v7(v)?, + ), + v8::ToRivet::ToRivetSqliteCommitRequest(v) => v7::ToRivet::ToRivetSqliteCommitRequest( + convert_to_rivet_sqlite_commit_request_v8_to_v7(v)?, + ), + v8::ToRivet::ToRivetSqliteExecRequest(v) => { + v7::ToRivet::ToRivetSqliteExecRequest(convert_to_rivet_sqlite_exec_request_v8_to_v7(v)?) + } + v8::ToRivet::ToRivetSqliteExecuteRequest(v) => v7::ToRivet::ToRivetSqliteExecuteRequest( + convert_to_rivet_sqlite_execute_request_v8_to_v7(v)?, + ), + v8::ToRivet::ToRivetSqliteExecuteBatchRequest(v) => { + v7::ToRivet::ToRivetSqliteExecuteBatchRequest( + convert_to_rivet_sqlite_execute_batch_request_v8_to_v7(v)?, + ) + } + }) +} + +pub fn convert_protocol_metadata_v8_to_v7(x: v8::ProtocolMetadata) -> Result { + Ok(v7::ProtocolMetadata { + envoy_lost_threshold: x.envoy_lost_threshold, + actor_stop_threshold: x.actor_stop_threshold, + max_response_payload_size: x.max_response_payload_size, + }) +} + +pub fn convert_to_envoy_init_v8_to_v7(x: v8::ToEnvoyInit) -> Result { + Ok(v7::ToEnvoyInit { + metadata: convert_protocol_metadata_v8_to_v7(x.metadata)?, + }) +} + +pub fn convert_to_envoy_commands_v8_to_v7(x: v8::ToEnvoyCommands) -> Result { + Ok(x.into_iter() + .map(|v| convert_command_wrapper_v8_to_v7(v)) + .collect::>>()?) +} + +pub fn convert_to_envoy_ack_events_v8_to_v7( + x: v8::ToEnvoyAckEvents, +) -> Result { + Ok(v7::ToEnvoyAckEvents { + last_event_checkpoints: x + .last_event_checkpoints + .into_iter() + .map(|v| convert_actor_checkpoint_v8_to_v7(v)) + .collect::>>()?, + }) +} + +pub fn convert_to_envoy_kv_response_v8_to_v7( + x: v8::ToEnvoyKvResponse, +) -> Result { + Ok(v7::ToEnvoyKvResponse { + request_id: x.request_id, + data: convert_kv_response_data_v8_to_v7(x.data)?, + }) +} + +pub fn convert_to_envoy_sqlite_get_pages_response_v8_to_v7( + x: v8::ToEnvoySqliteGetPagesResponse, +) -> Result { + Ok(v7::ToEnvoySqliteGetPagesResponse { + request_id: x.request_id, + data: convert_sqlite_get_pages_response_v8_to_v7(x.data)?, + }) +} + +pub fn convert_to_envoy_sqlite_commit_response_v8_to_v7( + x: v8::ToEnvoySqliteCommitResponse, +) -> Result { + Ok(v7::ToEnvoySqliteCommitResponse { + request_id: x.request_id, + data: convert_sqlite_commit_response_v8_to_v7(x.data)?, + }) +} + +pub fn convert_to_envoy_sqlite_exec_response_v8_to_v7( + x: v8::ToEnvoySqliteExecResponse, +) -> Result { + Ok(v7::ToEnvoySqliteExecResponse { + request_id: x.request_id, + data: convert_sqlite_exec_response_v8_to_v7(x.data)?, + }) +} + +pub fn convert_to_envoy_sqlite_execute_response_v8_to_v7( + x: v8::ToEnvoySqliteExecuteResponse, +) -> Result { + Ok(v7::ToEnvoySqliteExecuteResponse { + request_id: x.request_id, + data: convert_sqlite_execute_response_v8_to_v7(x.data)?, + }) +} + +pub fn convert_to_envoy_sqlite_execute_batch_response_v8_to_v7( + x: v8::ToEnvoySqliteExecuteBatchResponse, +) -> Result { + Ok(v7::ToEnvoySqliteExecuteBatchResponse { + request_id: x.request_id, + data: convert_sqlite_execute_batch_response_v8_to_v7(x.data)?, + }) +} + +pub fn convert_to_envoy_v8_to_v7(x: v8::ToEnvoy) -> Result { + Ok(match x { + v8::ToEnvoy::ToEnvoyInit(v) => v7::ToEnvoy::ToEnvoyInit(convert_to_envoy_init_v8_to_v7(v)?), + v8::ToEnvoy::ToEnvoyCommands(v) => { + v7::ToEnvoy::ToEnvoyCommands(convert_to_envoy_commands_v8_to_v7(v)?) + } + v8::ToEnvoy::ToEnvoyAckEvents(v) => { + v7::ToEnvoy::ToEnvoyAckEvents(convert_to_envoy_ack_events_v8_to_v7(v)?) + } + v8::ToEnvoy::ToEnvoyKvResponse(v) => { + v7::ToEnvoy::ToEnvoyKvResponse(convert_to_envoy_kv_response_v8_to_v7(v)?) + } + v8::ToEnvoy::ToEnvoyTunnelMessage(v) => { + v7::ToEnvoy::ToEnvoyTunnelMessage(convert_to_envoy_tunnel_message_v8_to_v7(v)?) + } + v8::ToEnvoy::ToEnvoyPing(v) => v7::ToEnvoy::ToEnvoyPing(convert_to_envoy_ping_v8_to_v7(v)?), + v8::ToEnvoy::ToEnvoySqliteGetPagesResponse(v) => { + v7::ToEnvoy::ToEnvoySqliteGetPagesResponse( + convert_to_envoy_sqlite_get_pages_response_v8_to_v7(v)?, + ) + } + v8::ToEnvoy::ToEnvoySqliteCommitResponse(v) => v7::ToEnvoy::ToEnvoySqliteCommitResponse( + convert_to_envoy_sqlite_commit_response_v8_to_v7(v)?, + ), + v8::ToEnvoy::ToEnvoySqliteExecResponse(v) => v7::ToEnvoy::ToEnvoySqliteExecResponse( + convert_to_envoy_sqlite_exec_response_v8_to_v7(v)?, + ), + v8::ToEnvoy::ToEnvoySqliteExecuteResponse(v) => v7::ToEnvoy::ToEnvoySqliteExecuteResponse( + convert_to_envoy_sqlite_execute_response_v8_to_v7(v)?, + ), + v8::ToEnvoy::ToEnvoySqliteExecuteBatchResponse(v) => { + v7::ToEnvoy::ToEnvoySqliteExecuteBatchResponse( + convert_to_envoy_sqlite_execute_batch_response_v8_to_v7(v)?, + ) + } + }) +} + +pub fn convert_to_envoy_conn_ping_v8_to_v7(x: v8::ToEnvoyConnPing) -> Result { + Ok(v7::ToEnvoyConnPing { + gateway_id: x.gateway_id, + request_id: x.request_id, + ts: x.ts, + }) +} + +pub fn convert_to_envoy_conn_v8_to_v7(x: v8::ToEnvoyConn) -> Result { + Ok(match x { + v8::ToEnvoyConn::ToEnvoyConnPing(v) => { + v7::ToEnvoyConn::ToEnvoyConnPing(convert_to_envoy_conn_ping_v8_to_v7(v)?) + } + v8::ToEnvoyConn::ToEnvoyConnClose => v7::ToEnvoyConn::ToEnvoyConnClose, + v8::ToEnvoyConn::ToEnvoyCommands(v) => { + v7::ToEnvoyConn::ToEnvoyCommands(convert_to_envoy_commands_v8_to_v7(v)?) + } + v8::ToEnvoyConn::ToEnvoyAckEvents(v) => { + v7::ToEnvoyConn::ToEnvoyAckEvents(convert_to_envoy_ack_events_v8_to_v7(v)?) + } + v8::ToEnvoyConn::ToEnvoyTunnelMessage(v) => { + v7::ToEnvoyConn::ToEnvoyTunnelMessage(convert_to_envoy_tunnel_message_v8_to_v7(v)?) + } + }) +} + +pub fn convert_to_gateway_pong_v8_to_v7(x: v8::ToGatewayPong) -> Result { + Ok(v7::ToGatewayPong { + request_id: x.request_id, + ts: x.ts, + }) +} + +pub fn convert_to_gateway_v8_to_v7(x: v8::ToGateway) -> Result { + Ok(match x { + v8::ToGateway::ToGatewayPong(v) => { + v7::ToGateway::ToGatewayPong(convert_to_gateway_pong_v8_to_v7(v)?) + } + v8::ToGateway::ToRivetTunnelMessage(v) => { + v7::ToGateway::ToRivetTunnelMessage(convert_to_rivet_tunnel_message_v8_to_v7(v)?) + } + }) +} + +pub fn convert_to_outbound_actor_start_v8_to_v7( + x: v8::ToOutboundActorStart, +) -> Result { + Ok(v7::ToOutboundActorStart { + namespace_id: x.namespace_id, + pool_name: x.pool_name, + checkpoint: convert_actor_checkpoint_v8_to_v7(x.checkpoint)?, + actor_config: convert_actor_config_v8_to_v7(x.actor_config)?, + }) +} + +pub fn convert_to_outbound_v8_to_v7(x: v8::ToOutbound) -> Result { + Ok(match x { + v8::ToOutbound::ToOutboundActorStart(v) => { + v7::ToOutbound::ToOutboundActorStart(convert_to_outbound_actor_start_v8_to_v7(v)?) + } + }) +} diff --git a/engine/sdks/rust/envoy-protocol/tests/remote_sql_compat.rs b/engine/sdks/rust/envoy-protocol/tests/remote_sql_compat.rs index 68c2e9a744..9688788513 100644 --- a/engine/sdks/rust/envoy-protocol/tests/remote_sql_compat.rs +++ b/engine/sdks/rust/envoy-protocol/tests/remote_sql_compat.rs @@ -1,6 +1,6 @@ use anyhow::Result; use rivet_envoy_protocol::{ - generated::{v4, v7}, + generated::{v4, v8}, versioned::{ ProtocolCompatibilityDirection, ProtocolCompatibilityError, ProtocolCompatibilityFeature, ToEnvoy, ToRivet, @@ -8,10 +8,10 @@ use rivet_envoy_protocol::{ }; use vbare::OwnedVersionedData; -fn remote_sql_request_exec() -> v7::ToRivet { - v7::ToRivet::ToRivetSqliteExecRequest(v7::ToRivetSqliteExecRequest { +fn remote_sql_request_exec() -> v8::ToRivet { + v8::ToRivet::ToRivetSqliteExecRequest(v8::ToRivetSqliteExecRequest { request_id: 1, - data: v7::SqliteExecRequest { + data: v8::SqliteExecRequest { namespace_id: "namespace".into(), actor_id: "actor".into(), generation: 7, @@ -20,25 +20,25 @@ fn remote_sql_request_exec() -> v7::ToRivet { }) } -fn remote_sql_request_execute() -> v7::ToRivet { - v7::ToRivet::ToRivetSqliteExecuteRequest(v7::ToRivetSqliteExecuteRequest { +fn remote_sql_request_execute() -> v8::ToRivet { + v8::ToRivet::ToRivetSqliteExecuteRequest(v8::ToRivetSqliteExecuteRequest { request_id: 2, - data: v7::SqliteExecuteRequest { + data: v8::SqliteExecuteRequest { namespace_id: "namespace".into(), actor_id: "actor".into(), generation: 7, sql: "select ?".into(), - params: Some(vec![v7::SqliteBindParam::SqliteValueInteger( - v7::SqliteValueInteger { value: 1 }, + params: Some(vec![v8::SqliteBindParam::SqliteValueInteger( + v8::SqliteValueInteger { value: 1 }, )]), }, }) } -fn remote_sql_response_exec() -> v7::ToEnvoy { - v7::ToEnvoy::ToEnvoySqliteExecResponse(v7::ToEnvoySqliteExecResponse { +fn remote_sql_response_exec() -> v8::ToEnvoy { + v8::ToEnvoy::ToEnvoySqliteExecResponse(v8::ToEnvoySqliteExecResponse { request_id: 1, - data: v7::SqliteExecResponse::SqliteErrorResponse(v7::SqliteErrorResponse { + data: v8::SqliteExecResponse::SqliteErrorResponse(v8::SqliteErrorResponse { group: "sqlite".into(), code: "remote_unavailable".into(), message: "remote sql execution is unavailable".into(), @@ -46,10 +46,10 @@ fn remote_sql_response_exec() -> v7::ToEnvoy { }) } -fn remote_sql_response_execute() -> v7::ToEnvoy { - v7::ToEnvoy::ToEnvoySqliteExecuteResponse(v7::ToEnvoySqliteExecuteResponse { +fn remote_sql_response_execute() -> v8::ToEnvoy { + v8::ToEnvoy::ToEnvoySqliteExecuteResponse(v8::ToEnvoySqliteExecuteResponse { request_id: 2, - data: v7::SqliteExecuteResponse::SqliteErrorResponse(v7::SqliteErrorResponse { + data: v8::SqliteExecuteResponse::SqliteErrorResponse(v8::SqliteErrorResponse { group: "sqlite".into(), code: "remote_unavailable".into(), message: "remote sql execution is unavailable".into(), @@ -57,27 +57,27 @@ fn remote_sql_response_execute() -> v7::ToEnvoy { }) } -fn remote_sql_request_execute_batch() -> v7::ToRivet { - v7::ToRivet::ToRivetSqliteExecuteBatchRequest(v7::ToRivetSqliteExecuteBatchRequest { +fn remote_sql_request_execute_batch() -> v8::ToRivet { + v8::ToRivet::ToRivetSqliteExecuteBatchRequest(v8::ToRivetSqliteExecuteBatchRequest { request_id: 3, - data: v7::SqliteExecuteBatchRequest { + data: v8::SqliteExecuteBatchRequest { namespace_id: "namespace".into(), actor_id: "actor".into(), generation: 7, - statements: vec![v7::SqliteBatchStatement { + statements: vec![v8::SqliteBatchStatement { sql: "insert into t values (?)".into(), - params: Some(vec![v7::SqliteBindParam::SqliteValueInteger( - v7::SqliteValueInteger { value: 1 }, + params: Some(vec![v8::SqliteBindParam::SqliteValueInteger( + v8::SqliteValueInteger { value: 1 }, )]), }], }, }) } -fn remote_sql_response_execute_batch() -> v7::ToEnvoy { - v7::ToEnvoy::ToEnvoySqliteExecuteBatchResponse(v7::ToEnvoySqliteExecuteBatchResponse { +fn remote_sql_response_execute_batch() -> v8::ToEnvoy { + v8::ToEnvoy::ToEnvoySqliteExecuteBatchResponse(v8::ToEnvoySqliteExecuteBatchResponse { request_id: 3, - data: v7::SqliteExecuteBatchResponse::SqliteExecuteBatchOk(v7::SqliteExecuteBatchOk { + data: v8::SqliteExecuteBatchResponse::SqliteExecuteBatchOk(v8::SqliteExecuteBatchOk { results: Vec::new(), }), }) @@ -139,11 +139,11 @@ fn new_core_new_pegboard_envoy_allows_remote_sql_both_directions() -> Result<()> assert!(matches!( ToRivet::deserialize(&request, 4)?, - v7::ToRivet::ToRivetSqliteExecRequest(_) + v8::ToRivet::ToRivetSqliteExecRequest(_) )); assert!(matches!( ToEnvoy::deserialize(&response, 4)?, - v7::ToEnvoy::ToEnvoySqliteExecResponse(_) + v8::ToEnvoy::ToEnvoySqliteExecResponse(_) )); Ok(()) @@ -235,11 +235,11 @@ fn remote_sql_batch_requires_v6() -> Result<()> { let response = ToEnvoy::wrap_latest(remote_sql_response_execute_batch()).serialize(6)?; assert!(matches!( ToRivet::deserialize(&request, 6)?, - v7::ToRivet::ToRivetSqliteExecuteBatchRequest(_) + v8::ToRivet::ToRivetSqliteExecuteBatchRequest(_) )); assert!(matches!( ToEnvoy::deserialize(&response, 6)?, - v7::ToEnvoy::ToEnvoySqliteExecuteBatchResponse(_) + v8::ToEnvoy::ToEnvoySqliteExecuteBatchResponse(_) )); Ok(()) } diff --git a/engine/sdks/rust/envoy-protocol/tests/stateless_sqlite_v3.rs b/engine/sdks/rust/envoy-protocol/tests/stateless_sqlite_v3.rs index 9d7598bbb4..d001837c07 100644 --- a/engine/sdks/rust/envoy-protocol/tests/stateless_sqlite_v3.rs +++ b/engine/sdks/rust/envoy-protocol/tests/stateless_sqlite_v3.rs @@ -168,7 +168,7 @@ fn expected_generation_optional_present_and_absent() -> anyhow::Result<()> { #[test] fn protocol_version_constant_matches_schema_version() { - assert_eq!(PROTOCOL_VERSION, 7); + assert_eq!(PROTOCOL_VERSION, 8); } #[test] diff --git a/engine/sdks/rust/envoy-protocol/tests/support/versioned_http_abort.rs b/engine/sdks/rust/envoy-protocol/tests/support/versioned_http_abort.rs index a493b180df..075d54fbfc 100644 --- a/engine/sdks/rust/envoy-protocol/tests/support/versioned_http_abort.rs +++ b/engine/sdks/rust/envoy-protocol/tests/support/versioned_http_abort.rs @@ -2,7 +2,12 @@ use anyhow::Result; use vbare::OwnedVersionedData; use super::ToEnvoy; -use crate::generated::{v6, v7}; +use crate::generated::{v6, v8}; + +const REQUEST_ABORT_GOLDEN: &[u8] = &[ + 4, 1, 1, 1, 1, 7, 7, 7, 7, 1, 0, 2, 1, 1, 24, 99, 108, 105, 101, 110, 116, 32, 99, 108, 111, + 115, 101, 100, 32, 99, 111, 110, 110, 101, 99, 116, 105, 111, 110, +]; #[test] fn v6_request_abort_deserializes_with_unknown_reason() -> Result<()> { @@ -18,31 +23,31 @@ fn v6_request_abort_deserializes_with_unknown_reason() -> Result<()> { ))?; let decoded = ToEnvoy::deserialize(&payload, 6)?; - let v7::ToEnvoy::ToEnvoyTunnelMessage(msg) = decoded else { + let v8::ToEnvoy::ToEnvoyTunnelMessage(msg) = decoded else { panic!("expected tunnel message"); }; - let v7::ToEnvoyTunnelMessageKind::ToEnvoyRequestAbort(abort) = msg.message_kind else { + let v8::ToEnvoyTunnelMessageKind::ToEnvoyRequestAbort(abort) = msg.message_kind else { panic!("expected request abort"); }; - assert_eq!(abort.reason.kind, v7::HttpStreamAbortReasonKind::Unknown); + assert_eq!(abort.reason.kind, v8::HttpStreamAbortReasonKind::Unknown); assert!(abort.reason.detail.is_none()); Ok(()) } #[test] -fn v7_request_abort_serializes_to_v6_void_abort() -> Result<()> { - let encoded = ToEnvoy::wrap_latest(v7::ToEnvoy::ToEnvoyTunnelMessage( - v7::ToEnvoyTunnelMessage { - message_id: v7::MessageId { +fn v8_request_abort_serializes_to_v6_void_abort() -> Result<()> { + let encoded = ToEnvoy::wrap_latest(v8::ToEnvoy::ToEnvoyTunnelMessage( + v8::ToEnvoyTunnelMessage { + message_id: v8::MessageId { gateway_id: [1; 4], request_id: [7; 4], message_index: 1, }, - message_kind: v7::ToEnvoyTunnelMessageKind::ToEnvoyRequestAbort( - v7::ToEnvoyRequestAbort { - reason: v7::HttpStreamAbortReason { - kind: v7::HttpStreamAbortReasonKind::ClientDisconnect, + message_kind: v8::ToEnvoyTunnelMessageKind::ToEnvoyRequestAbort( + v8::ToEnvoyRequestAbort { + reason: v8::HttpStreamAbortReason { + kind: v8::HttpStreamAbortReasonKind::ClientDisconnect, detail: Some("client closed connection".into()), }, }, @@ -61,3 +66,27 @@ fn v7_request_abort_serializes_to_v6_void_abort() -> Result<()> { )); Ok(()) } + +#[test] +fn request_abort_matches_cross_language_golden_bytes() -> Result<()> { + let encoded = serde_bare::to_vec(&v8::ToEnvoy::ToEnvoyTunnelMessage( + v8::ToEnvoyTunnelMessage { + message_id: v8::MessageId { + gateway_id: [1; 4], + request_id: [7; 4], + message_index: 1, + }, + message_kind: v8::ToEnvoyTunnelMessageKind::ToEnvoyRequestAbort( + v8::ToEnvoyRequestAbort { + reason: v8::HttpStreamAbortReason { + kind: v8::HttpStreamAbortReasonKind::ClientDisconnect, + detail: Some("client closed connection".into()), + }, + }, + ), + }, + ))?; + + assert_eq!(encoded, REQUEST_ABORT_GOLDEN); + Ok(()) +} diff --git a/engine/sdks/typescript/envoy-protocol/package.json b/engine/sdks/typescript/envoy-protocol/package.json index dd16efcf4f..06d60d25e0 100644 --- a/engine/sdks/typescript/envoy-protocol/package.json +++ b/engine/sdks/typescript/envoy-protocol/package.json @@ -21,6 +21,7 @@ ], "scripts": { "build": "tsup src/index.ts", + "test": "vitest run", "clean": "rm -rf dist", "check-types": "tsc --noEmit" }, @@ -31,6 +32,7 @@ "devDependencies": { "@types/node": "^20.19.13", "tsup": "^8.5.0", - "typescript": "^5.9.2" + "typescript": "^5.9.2", + "vitest": "^3.2.4" } } diff --git a/engine/sdks/typescript/envoy-protocol/src/index.ts b/engine/sdks/typescript/envoy-protocol/src/index.ts index 7a5e15daae..fbcfa14441 100644 --- a/engine/sdks/typescript/envoy-protocol/src/index.ts +++ b/engine/sdks/typescript/envoy-protocol/src/index.ts @@ -3570,4 +3570,4 @@ function assert(condition: boolean, message?: string): asserts condition { if (!condition) throw new Error(message ?? "Assertion failed") } -export const VERSION = 7; \ No newline at end of file +export const VERSION = 8; \ No newline at end of file diff --git a/engine/sdks/typescript/envoy-protocol/tests/http-abort-golden.test.ts b/engine/sdks/typescript/envoy-protocol/tests/http-abort-golden.test.ts new file mode 100644 index 0000000000..d8efc21d2c --- /dev/null +++ b/engine/sdks/typescript/envoy-protocol/tests/http-abort-golden.test.ts @@ -0,0 +1,37 @@ +import { describe, expect, test } from "vitest"; +import { + encodeToEnvoy, + HttpStreamAbortReasonKind, +} from "../src/index"; + +const REQUEST_ABORT_GOLDEN = [ + 4, 1, 1, 1, 1, 7, 7, 7, 7, 1, 0, 2, 1, 1, 24, 99, 108, 105, 101, 110, + 116, 32, 99, 108, 111, 115, 101, 100, 32, 99, 111, 110, 110, 101, 99, 116, + 105, 111, 110, +]; + +describe("envoy HTTP abort protocol", () => { + test("matches the Rust golden bytes", () => { + const encoded = encodeToEnvoy({ + tag: "ToEnvoyTunnelMessage", + val: { + messageId: { + gatewayId: new Uint8Array([1, 1, 1, 1]).buffer, + requestId: new Uint8Array([7, 7, 7, 7]).buffer, + messageIndex: 1, + }, + messageKind: { + tag: "ToEnvoyRequestAbort", + val: { + reason: { + kind: HttpStreamAbortReasonKind.ClientDisconnect, + detail: "client closed connection", + }, + }, + }, + }, + }); + + expect([...encoded]).toEqual(REQUEST_ABORT_GOLDEN); + }); +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 59208dfcdf..60e04581b7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -139,6 +139,9 @@ importers: typescript: specifier: ^5.9.2 version: 5.9.3 + vitest: + specifier: ^3.2.4 + version: 3.2.4(@types/debug@4.1.12)(@types/node@20.19.13)(less@4.4.1)(lightningcss@1.32.0)(msw@2.14.4(@types/node@20.19.13)(typescript@5.9.3))(sass@1.93.2)(stylus@0.62.0)(terser@5.46.0) engine/sdks/typescript/test-runner: dependencies: diff --git a/rivetkit-typescript/packages/rivetkit-napi/src/napi_actor_events.rs b/rivetkit-typescript/packages/rivetkit-napi/src/napi_actor_events.rs index af5be81888..4cf3350205 100644 --- a/rivetkit-typescript/packages/rivetkit-napi/src/napi_actor_events.rs +++ b/rivetkit-typescript/packages/rivetkit-napi/src/napi_actor_events.rs @@ -429,18 +429,14 @@ pub(crate) async fn dispatch_event( let ctx = ctx.clone(); let timeout = config.on_request_timeout; spawn_reply(tasks, abort.clone(), reply, async move { - with_dispatch_cancel_token(|cancel_token| { - with_structured_timeout( - "actor", - "action_timed_out", - "Action timed out", - None, - timeout, - async move { - call_http_request(&callback, &ctx, request, Some(cancel_token)).await - }, - ) - }) + with_structured_timeout( + "actor", + "action_timed_out", + "Action timed out", + None, + timeout, + call_http_request(&callback, &ctx, request), + ) .await }); } @@ -1150,31 +1146,15 @@ async fn call_http_request( callback: &crate::actor_factory::CallbackTsfn, ctx: &ActorContext, request: rivetkit_core::Request, - cancel_token: Option, ) -> Result { let request_cancel_token = request.cancellation_token(); - let cancel_token = match cancel_token { - Some(dispatch_cancel_token) => { - let combined_cancel_token = CancellationToken::new(); - let combined_cancel_token_task = combined_cancel_token.clone(); - tokio::spawn(async move { - tokio::select! { - _ = request_cancel_token.cancelled() => {} - _ = dispatch_cancel_token.cancelled() => {} - } - combined_cancel_token_task.cancel(); - }); - Some(combined_cancel_token) - } - None => Some(request_cancel_token), - }; call_request( "onRequest", callback, HttpRequestPayload { ctx: ctx.inner().clone(), request, - cancel_token, + cancel_token: Some(request_cancel_token), response_stream: None, }, ) diff --git a/rivetkit-typescript/packages/rivetkit/src/registry/native-http.ts b/rivetkit-typescript/packages/rivetkit/src/registry/native-http.ts index 5946c058db..0de9319cd1 100644 --- a/rivetkit-typescript/packages/rivetkit/src/registry/native-http.ts +++ b/rivetkit-typescript/packages/rivetkit/src/registry/native-http.ts @@ -93,6 +93,12 @@ export function buildNativeHttpRequest(init: NativeHttpRequestInit): Request { } as RequestInit); } +export async function cancelNativeHttpRequestBody( + bodyStream?: NativeHttpRequestBodyStream, +) { + await bodyStream?.cancel(); +} + async function writeResponseChunk( stream: NativeHttpResponseBodyStream, chunk: Uint8Array, @@ -197,5 +203,6 @@ export async function convertNativeHttpResponse( export const nativeHttpTestInternals = { buildRequest: buildNativeHttpRequest, + cancelRequestBody: cancelNativeHttpRequestBody, convertRuntimeHttpResponse: convertNativeHttpResponse, }; diff --git a/rivetkit-typescript/packages/rivetkit/src/registry/native.ts b/rivetkit-typescript/packages/rivetkit/src/registry/native.ts index d32231cfcc..1354c6c88f 100644 --- a/rivetkit-typescript/packages/rivetkit/src/registry/native.ts +++ b/rivetkit-typescript/packages/rivetkit/src/registry/native.ts @@ -74,6 +74,7 @@ import { logger } from "./log"; import { loadNapiRuntime } from "./napi-runtime"; import { buildNativeHttpRequest, + cancelNativeHttpRequestBody, convertNativeHttpResponse, type NativeHttpRequestBodyStream, type NativeHttpResponseBodyStream, @@ -4656,6 +4657,7 @@ export function buildNativeFactory( const inspectorResponse = await maybeHandleNativeInspectorRequest(ctx, request); if (inspectorResponse) { + await cancelNativeHttpRequestBody(request.bodyStream); return ( await convertNativeHttpResponse( inspectorResponse, @@ -4665,6 +4667,7 @@ export function buildNativeFactory( } if (typeof config.onRequest !== "function") { + await cancelNativeHttpRequestBody(request.bodyStream); return ( await convertNativeHttpResponse( new Response(null, { status: 404 }), @@ -4762,8 +4765,16 @@ export function buildNativeFactory( } return conversion.response; } finally { - if (!cleanupDeferredToBody) { - await cleanupRequest(); + try { + // Handler completion ends upload ownership even when + // the Web Request body is locked or partly consumed. + await cancelNativeHttpRequestBody( + request.bodyStream, + ); + } finally { + if (!cleanupDeferredToBody) { + await cleanupRequest(); + } } } } catch (error) { diff --git a/rivetkit-typescript/packages/rivetkit/tests/native-http-streaming.test.ts b/rivetkit-typescript/packages/rivetkit/tests/native-http-streaming.test.ts index 377b51f55b..a87e46a673 100644 --- a/rivetkit-typescript/packages/rivetkit/tests/native-http-streaming.test.ts +++ b/rivetkit-typescript/packages/rivetkit/tests/native-http-streaming.test.ts @@ -101,6 +101,27 @@ describe("native http response streaming", () => { expect(request.signal.aborted).toBe(true); }); + test("explicitly cancels an unread native upload after an early response", async () => { + let cancelCount = 0; + const bodyStream = { + async read() { + return new Promise(() => {}); + }, + async cancel() { + cancelCount++; + }, + }; + const request = nativeHttpTestInternals.buildRequest({ + method: "POST", + uri: "/upload", + bodyStream, + }); + + expect(request.bodyUsed).toBe(false); + await nativeHttpTestInternals.cancelRequestBody(bodyStream); + expect(cancelCount).toBe(1); + }); + test("streams multi-chunk responses through the native body stream", async () => { const writes: Uint8Array[] = []; let finish!: () => void; @@ -164,6 +185,41 @@ describe("native http response streaming", () => { expect(writes[2][0]).toBe(7); }); + test("does not impose a cumulative 20 MiB response limit", async () => { + const responseSize = 20 * 1024 * 1024 + 1; + let writtenBytes = 0; + const responseBodyStream = { + async cancelled() { + return new Promise(() => {}); + }, + async write(chunk: Uint8Array) { + writtenBytes += chunk.byteLength; + }, + async end() {}, + async error(message: string) { + throw new Error(message); + }, + }; + const response = new Response( + new ReadableStream({ + start(controller) { + controller.enqueue(new Uint8Array(responseSize)); + controller.close(); + }, + }), + ); + + const conversion = + await nativeHttpTestInternals.convertRuntimeHttpResponse( + response, + responseBodyStream, + ); + await conversion.bodyCompletion; + + expect(conversion.response.stream).toBe(true); + expect(writtenBytes).toBe(responseSize); + }); + test("returns streamed response headers before the first body chunk", async () => { let bodyController!: ReadableStreamDefaultController; let finish!: () => void;