From dbb3fc30b300c2da7db6f68f660f6f0f17041412 Mon Sep 17 00:00:00 2001 From: slinkydeveloper Date: Mon, 22 Sep 2025 12:27:20 +0200 Subject: [PATCH] Add better closed error --- Cargo.lock | 3 +-- Cargo.toml | 2 +- src/lib.rs | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ea91552..1f77727 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -516,8 +516,7 @@ dependencies = [ [[package]] name = "restate-sdk-shared-core" version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c538c3af8f41229e3dd5aba4a31acdd84909c6653a3cc6b8ea64fd7fb54abb21" +source = "git+https://github.com/restatedev/sdk-shared-core.git?rev=eafbe4729a4ae7fa74fd0fb32e29121b240e1e5e#eafbe4729a4ae7fa74fd0fb32e29121b240e1e5e" dependencies = [ "base64 0.22.1", "bs58", diff --git a/Cargo.toml b/Cargo.toml index f6d2b57..537007f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,4 +14,4 @@ doc = false [dependencies] pyo3 = { version = "0.25.1", features = ["extension-module"] } tracing-subscriber = { version = "0.3", features = ["fmt", "env-filter"] } -restate-sdk-shared-core = { version = "=0.6.0", features = ["request_identity", "sha2_random_seed"] } +restate-sdk-shared-core = { git = "https://github.com/restatedev/sdk-shared-core.git", rev = "eafbe4729a4ae7fa74fd0fb32e29121b240e1e5e", features = ["request_identity", "sha2_random_seed"] } diff --git a/src/lib.rs b/src/lib.rs index ba7f555..45eef66 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,4 @@ +use std::fmt; use pyo3::create_exception; use pyo3::prelude::*; use pyo3::types::{PyBytes, PyNone, PyString}; @@ -7,6 +8,7 @@ use restate_sdk_shared_core::{ TerminalFailure, VMOptions, Value, CANCEL_NOTIFICATION_HANDLE, VM, }; use std::time::{Duration, SystemTime}; +use restate_sdk_shared_core::fmt::{set_error_formatter, ErrorFormatter}; // Current crate version const CURRENT_VERSION: &str = env!("CARGO_PKG_VERSION"); @@ -158,6 +160,7 @@ impl From for TerminalFailure { TerminalFailure { code: value.code, message: value.message, + metadata: vec![], } } } @@ -751,6 +754,31 @@ impl PyIdentityVerifier { } } +#[derive(Debug)] +struct PythonErrorFormatter; + +impl ErrorFormatter for PythonErrorFormatter { + fn display_closed_error(&self, f: &mut fmt::Formatter<'_>, event: &str) -> fmt::Result { + write!(f, "Execution is suspended, but the handler is still attempting to make progress (calling '{event}'). This can happen: + +* If the SuspendedException is caught. Make sure you NEVER catch the SuspendedException, e.g. avoid: +try: + # Code +except: + # This catches all exceptions, including the SuspendedException! + +And use instead: +try: + # Code +except TerminalException: + # In Restate handlers you typically want to catch TerminalException + +Check https://docs.restate.dev/develop/python/durable-steps#run for more details on run error handling. + +* If you use the context after the handler completed, e.g. moving the context to another thread. Check https://docs.restate.dev/develop/python/concurrent-tasks for more details on how to create durable concurrent tasks in Python.") + } +} + #[pymodule] fn _internal(m: &Bound<'_, PyModule>) -> PyResult<()> { use tracing_subscriber::EnvFilter; @@ -790,5 +818,9 @@ fn _internal(m: &Bound<'_, PyModule>) -> PyResult<()> { "CANCEL_NOTIFICATION_HANDLE", PyNotificationHandle::from(CANCEL_NOTIFICATION_HANDLE), )?; + + // Set customized error formatter + set_error_formatter(PythonErrorFormatter); + Ok(()) }