diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_get_property.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_get_property.c index 5faf33951c..40a8809d37 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_get_property.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_get_property.c @@ -318,17 +318,12 @@ PyObject *ten_py_ten_env_is_property_exist(PyObject *self, PyObject *args) { "Failed to parse argument when ten_env.is_property_exist."); } - ten_error_t err; - ten_error_init(&err); - - bool is_exist = ten_env_is_property_exist(py_ten_env->c_ten_env, path, &err); - if (!ten_error_is_success(&err)) { - ten_error_deinit(&err); - - return ten_py_raise_py_value_error_exception( - "Failed to check if property exists."); + ten_value_t *value = + ten_py_ten_property_get_and_check_if_exists(py_ten_env, path); + if (!value) { + return PyBool_FromLong(false); } - ten_error_deinit(&err); - return PyBool_FromLong(is_exist); + ten_value_destroy(value); + return PyBool_FromLong(true); } diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_is_cmd_connected.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_is_cmd_connected.c index 4475741ef9..babc6887d8 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_is_cmd_connected.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_is_cmd_connected.c @@ -6,6 +6,57 @@ // #include "include_internal/ten_runtime/binding/python/common/error.h" #include "include_internal/ten_runtime/binding/python/ten_env/ten_env.h" +#include "ten_runtime/ten_env_proxy/ten_env_proxy.h" +#include "ten_utils/macro/memory.h" + +typedef struct ten_env_notify_is_cmd_connected_info_t { + bool result; + ten_string_t name; + ten_event_t *completed; +} ten_env_notify_is_cmd_connected_info_t; + +static ten_env_notify_is_cmd_connected_info_t * +ten_env_notify_is_cmd_connected_info_create(const char *name) { + ten_env_notify_is_cmd_connected_info_t *info = + TEN_MALLOC(sizeof(ten_env_notify_is_cmd_connected_info_t)); + TEN_ASSERT(info, "Failed to allocate memory."); + + info->result = true; + ten_string_init_formatted(&info->name, "%s", name); + info->completed = ten_event_create(0, 1); + + return info; +} + +static void ten_env_notify_is_cmd_connected_info_destroy( + ten_env_notify_is_cmd_connected_info_t *info) { + TEN_ASSERT(info, "Invalid argument."); + + ten_string_deinit(&info->name); + ten_event_destroy(info->completed); + + TEN_FREE(info); +} + +static void ten_env_proxy_notify_is_cmd_connected(ten_env_t *ten_env, + void *user_data) { + TEN_ASSERT(user_data, "Invalid argument."); + TEN_ASSERT(ten_env && ten_env_check_integrity(ten_env, true), + "Should not happen."); + + ten_env_notify_is_cmd_connected_info_t *info = user_data; + TEN_ASSERT(info, "Should not happen."); + + ten_error_t err; + ten_error_init(&err); + + info->result = ten_env_is_cmd_connected( + ten_env, ten_string_get_raw_str(&info->name), &err); + + ten_event_set(info->completed); + + ten_error_deinit(&err); +} PyObject *ten_py_ten_env_is_cmd_connected(PyObject *self, PyObject *args) { ten_py_ten_env_t *py_ten_env = (ten_py_ten_env_t *)self; @@ -26,8 +77,27 @@ PyObject *ten_py_ten_env_is_cmd_connected(PyObject *self, PyObject *args) { ten_error_t err; ten_error_init(&err); - bool is_connected = - ten_env_is_cmd_connected(py_ten_env->c_ten_env, cmd_name, &err); + ten_env_notify_is_cmd_connected_info_t *info = + ten_env_notify_is_cmd_connected_info_create(cmd_name); + + if (!ten_env_proxy_notify(py_ten_env->c_ten_env_proxy, + ten_env_proxy_notify_is_cmd_connected, info, false, + &err)) { + ten_error_deinit(&err); + ten_env_notify_is_cmd_connected_info_destroy(info); + + return ten_py_raise_py_value_error_exception( + "Failed to notify is command connected."); + } + + PyThreadState *saved_py_thread_state = PyEval_SaveThread(); + ten_event_wait(info->completed, -1); + PyEval_RestoreThread(saved_py_thread_state); + + bool is_connected = info->result; + + ten_env_notify_is_cmd_connected_info_destroy(info); + if (!ten_error_is_success(&err)) { ten_error_deinit(&err); diff --git a/tests/ten_runtime/integration/python/async_extension_basic_python/async_extension_basic_python_app/ten_packages/extension/default_async_extension_python/extension.py b/tests/ten_runtime/integration/python/async_extension_basic_python/async_extension_basic_python_app/ten_packages/extension/default_async_extension_python/extension.py index c0fcc84202..f92307d34e 100644 --- a/tests/ten_runtime/integration/python/async_extension_basic_python/async_extension_basic_python_app/ten_packages/extension/default_async_extension_python/extension.py +++ b/tests/ten_runtime/integration/python/async_extension_basic_python/async_extension_basic_python_app/ten_packages/extension/default_async_extension_python/extension.py @@ -28,6 +28,12 @@ async def on_init(self, ten_env: AsyncTenEnv) -> None: async def on_start(self, ten_env: AsyncTenEnv) -> None: await asyncio.sleep(0.5) ten_env.log_debug("on_start") + + assert ten_env.is_property_exist("unknown_field") is False + + ten_env.set_property_string("string_field", "hello") + assert ten_env.is_property_exist("string_field") is True + ten_env.on_start_done() async def on_deinit(self, ten_env: AsyncTenEnv) -> None: @@ -41,6 +47,9 @@ async def on_cmd(self, ten_env: AsyncTenEnv, cmd: Cmd) -> None: # Mock async operation, e.g. network, file I/O. await asyncio.sleep(0.5) + assert ten_env.is_cmd_connected("hello") is True + assert ten_env.is_cmd_connected("unknown_cmd") is False + # Send a new command to other extensions and wait for the result. The # result will be returned to the original sender. new_cmd = Cmd.create("hello") diff --git a/tests/ten_runtime/smoke/extension_test/outer_thread/128_threads_attempt_to_suspend_1.cc b/tests/ten_runtime/smoke/extension_test/outer_thread/128_threads_attempt_to_suspend_1.cc index 59cf3acffe..0860c0277f 100644 --- a/tests/ten_runtime/smoke/extension_test/outer_thread/128_threads_attempt_to_suspend_1.cc +++ b/tests/ten_runtime/smoke/extension_test/outer_thread/128_threads_attempt_to_suspend_1.cc @@ -47,10 +47,16 @@ class test_extension_1 : public ten::extension_t { explicit test_extension_1(const std::string &name) : ten::extension_t(name) {} void on_configure(ten::ten_env_t &ten_env) override { + // We have increased the path timeout to 20 minutes because, under limited + // computing resources, it is easy to exceed the path timeout without + // completing the data transmission. This can lead to the path being + // discarded, causing the test case to hang indefinitely. Therefore, we have + // extended the path timeout to avoid this situation. + // clang-format off bool rc = ten_env.init_property_from_json( R"({ "_ten": { - "path_timeout": 600000000 + "path_timeout": 1200000000 } })"); // clang-format on @@ -831,9 +837,15 @@ class test_extension_2 : public ten::extension_t { OUTER_THREAD_FOR_LOOP_CNT + 1) {} void on_configure(ten::ten_env_t &ten_env) override { + // We have increased the path timeout to 20 minutes because, under limited + // computing resources, it is easy to exceed the path timeout without + // completing the data transmission. This can lead to the path being + // discarded, causing the test case to hang indefinitely. Therefore, we have + // extended the path timeout to avoid this situation. + ten_env.init_property_from_json(R"({ "_ten": { - "path_timeout": 600000000 + "path_timeout": 1200000000 } })"); ten_env.on_configure_done();