Skip to content

Commit 1ed3371

Browse files
authored
fix: fill app uri in graph json when handling start_graph cmd (#1055)
1 parent 9b44235 commit 1ed3371

File tree

3 files changed

+285
-2
lines changed

3 files changed

+285
-2
lines changed

core/src/ten_runtime/app/msg_interface/start_graph.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
#include "include_internal/ten_runtime/engine/engine.h"
2323
#include "include_internal/ten_runtime/engine/internal/migration.h"
2424
#include "include_internal/ten_runtime/engine/msg_interface/common.h"
25+
#include "include_internal/ten_runtime/extension/extension_info/extension_info.h"
26+
#include "include_internal/ten_runtime/extension_group/extension_group_info/extension_group_info.h"
2527
#include "include_internal/ten_runtime/msg/cmd_base/cmd/start_graph/cmd.h"
2628
#include "include_internal/ten_runtime/msg/msg.h"
2729
#include "include_internal/ten_runtime/protocol/protocol.h"
@@ -59,6 +61,23 @@ static bool ten_app_fill_start_graph_cmd_extensions_info_from_predefined_graph(
5961
return true;
6062
}
6163

64+
void ten_app_fill_start_graph_cmd_node_app_uri(ten_app_t *self,
65+
ten_shared_ptr_t *cmd) {
66+
TEN_ASSERT(self && ten_app_check_integrity(self, true), "Should not happen.");
67+
TEN_ASSERT(cmd && ten_cmd_base_check_integrity(cmd), "Should not happen.");
68+
TEN_ASSERT(ten_msg_get_type(cmd) == TEN_MSG_TYPE_CMD_START_GRAPH,
69+
"Should not happen.");
70+
71+
ten_list_t *extensions_info = ten_cmd_start_graph_get_extensions_info(cmd);
72+
ten_list_t *extension_groups_info =
73+
ten_cmd_start_graph_get_extension_groups_info(cmd);
74+
75+
ten_extensions_info_fill_app_uri(extensions_info,
76+
ten_string_get_raw_str(&self->uri));
77+
ten_extension_groups_info_fill_app_uri(extension_groups_info,
78+
ten_string_get_raw_str(&self->uri));
79+
}
80+
6281
static bool ten_app_check_start_graph_cmd_from_connection(
6382
ten_app_t *self, ten_connection_t *connection, ten_shared_ptr_t *cmd,
6483
ten_error_t *err) {
@@ -98,6 +117,9 @@ bool ten_app_handle_start_graph_cmd(ten_app_t *self,
98117
return false;
99118
}
100119

120+
// Fill the app uri of the nodes in the start_graph cmd.
121+
ten_app_fill_start_graph_cmd_node_app_uri(self, cmd);
122+
101123
ten_engine_t *engine =
102124
ten_app_get_engine_based_on_dest_graph_id_from_msg(self, cmd);
103125
if (engine == NULL) {

core/src/ten_runtime/extension/extension_info/extension_info.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,7 @@ ten_extension_info_t *ten_extension_info_from_smart_ptr(
424424

425425
static void ten_extension_info_fill_app_uri(ten_extension_info_t *self,
426426
const char *app_uri) {
427-
TEN_ASSERT(self && ten_extension_info_check_integrity(self, true),
427+
TEN_ASSERT(self && ten_extension_info_check_integrity(self, false),
428428
"Invalid argument.");
429429
TEN_ASSERT(app_uri, "Should not happen.");
430430
TEN_ASSERT(!ten_loc_is_empty(&self->loc), "Should not happen.");
@@ -456,7 +456,7 @@ void ten_extensions_info_fill_app_uri(ten_list_t *extensions_info,
456456
ten_extension_info_t *extension_info =
457457
ten_shared_ptr_get_data(ten_smart_ptr_listnode_get(iter.node));
458458
TEN_ASSERT(extension_info &&
459-
ten_extension_info_check_integrity(extension_info, true),
459+
ten_extension_info_check_integrity(extension_info, false),
460460
"Invalid argument.");
461461

462462
ten_extension_info_fill_app_uri(extension_info, app_uri);
Lines changed: 261 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,261 @@
1+
//
2+
// Copyright © 2025 Agora
3+
// This file is part of TEN Framework, an open source project.
4+
// Licensed under the Apache License, Version 2.0, with certain conditions.
5+
// Refer to the "LICENSE" file in the root directory for more information.
6+
//
7+
#include "gtest/gtest.h"
8+
#include "include_internal/ten_runtime/binding/cpp/ten.h"
9+
#include "tests/common/client/cpp/msgpack_tcp.h"
10+
#include "tests/ten_runtime/smoke/util/binding/cpp/check.h"
11+
12+
namespace {
13+
14+
class test_normal_extension_1 : public ten::extension_t {
15+
public:
16+
explicit test_normal_extension_1(const char *name) : ten::extension_t(name) {}
17+
18+
void on_start(ten::ten_env_t &ten_env) override {
19+
ten_env.send_cmd(ten::cmd_t::create("A"),
20+
[this](ten::ten_env_t &ten_env,
21+
std::unique_ptr<ten::cmd_result_t> cmd_result,
22+
ten::error_t *err) { ten_env.on_start_done(); });
23+
}
24+
};
25+
26+
class test_normal_extension_2 : public ten::extension_t {
27+
public:
28+
explicit test_normal_extension_2(const char *name) : ten::extension_t(name) {}
29+
30+
void on_cmd(ten::ten_env_t &ten_env,
31+
std::unique_ptr<ten::cmd_t> cmd) override {
32+
if (cmd->get_name() == "B") {
33+
ten_env.return_result(ten::cmd_result_t::create(TEN_STATUS_CODE_OK),
34+
std::move(cmd));
35+
} else {
36+
auto cmd_name = cmd->get_name();
37+
auto error_msg =
38+
"test_normal_extension_2 received unexpected cmd: " + cmd_name;
39+
40+
TEN_ENV_LOG_ERROR(ten_env, error_msg.c_str());
41+
TEN_ASSERT(0, "Should not happen.");
42+
}
43+
}
44+
};
45+
46+
class test_normal_extension_3 : public ten::extension_t {
47+
public:
48+
explicit test_normal_extension_3(const char *name) : ten::extension_t(name) {}
49+
50+
void on_cmd(ten::ten_env_t &ten_env,
51+
std::unique_ptr<ten::cmd_t> cmd) override {
52+
if (cmd->get_name() == "B") {
53+
ten_env.return_result(ten::cmd_result_t::create(TEN_STATUS_CODE_OK),
54+
std::move(cmd));
55+
} else {
56+
auto cmd_name = cmd->get_name();
57+
auto error_msg =
58+
"test_normal_extension_3 received unexpected cmd: " + cmd_name;
59+
60+
TEN_ENV_LOG_ERROR(ten_env, error_msg.c_str());
61+
TEN_ASSERT(0, "Should not happen.");
62+
}
63+
}
64+
};
65+
66+
class test_predefined_graph : public ten::extension_t {
67+
public:
68+
explicit test_predefined_graph(const char *name) : ten::extension_t(name) {}
69+
70+
void on_start(ten::ten_env_t &ten_env) override {
71+
auto start_graph_cmd = ten::cmd_start_graph_t::create();
72+
start_graph_cmd->set_dest("localhost", nullptr, nullptr, nullptr);
73+
start_graph_cmd->set_graph_from_json(
74+
R"({
75+
"nodes": [
76+
{
77+
"addon": "test_normal_extension_1",
78+
"extension_group": "default",
79+
"name": "test_normal_extension_1",
80+
"type": "extension"
81+
},
82+
{
83+
"addon": "test_normal_extension_2",
84+
"extension_group": "test_normal_extension_2",
85+
"name": "test_normal_extension_2",
86+
"type": "extension"
87+
}
88+
],
89+
"connections": [
90+
{
91+
"extension": "test_normal_extension_1",
92+
"cmd": [
93+
{
94+
"name": "A",
95+
"dest": [
96+
{
97+
"extension": "test_normal_extension_2",
98+
"msg_conversion": {
99+
"keep_original": true,
100+
"rules": [
101+
{
102+
"conversion_mode": "fixed_value",
103+
"path": "_ten.name",
104+
"value": "B"
105+
}
106+
],
107+
"type": "per_property"
108+
}
109+
}
110+
]
111+
}
112+
]
113+
}
114+
]
115+
})"_json.dump()
116+
.c_str());
117+
118+
ten_env.send_cmd(
119+
std::move(start_graph_cmd),
120+
[this](ten::ten_env_t &ten_env,
121+
std::unique_ptr<ten::cmd_result_t> cmd_result,
122+
ten::error_t *err) {
123+
// result for the 'start_graph' command
124+
auto graph_id = cmd_result->get_property_string("detail");
125+
126+
// Shut down the graph; otherwise, the app won't be able to close
127+
// because there is still a running engine/graph.
128+
auto stop_graph_cmd = ten::cmd_stop_graph_t::create();
129+
stop_graph_cmd->set_dest("localhost", nullptr, nullptr, nullptr);
130+
stop_graph_cmd->set_graph_id(graph_id.c_str());
131+
132+
ten_env.send_cmd(
133+
std::move(stop_graph_cmd),
134+
[this](ten::ten_env_t &ten_env,
135+
std::unique_ptr<ten::cmd_result_t> cmd_result,
136+
ten::error_t *err) {
137+
start_graph_cmd_is_done = true;
138+
139+
if (test_cmd != nullptr) {
140+
nlohmann::json detail = {{"id", 1}, {"name", "a"}};
141+
142+
auto cmd_result_for_test =
143+
ten::cmd_result_t::create(TEN_STATUS_CODE_OK);
144+
cmd_result_for_test->set_property_from_json(
145+
"detail", detail.dump().c_str());
146+
ten_env.return_result(std::move(cmd_result_for_test),
147+
std::move(test_cmd));
148+
}
149+
});
150+
});
151+
152+
ten_env.on_start_done();
153+
}
154+
155+
void on_cmd(ten::ten_env_t &ten_env,
156+
std::unique_ptr<ten::cmd_t> cmd) override {
157+
if (cmd->get_name() == "test") {
158+
if (start_graph_cmd_is_done) {
159+
nlohmann::json detail = {{"id", 1}, {"name", "a"}};
160+
161+
auto cmd_result = ten::cmd_result_t::create(TEN_STATUS_CODE_OK);
162+
cmd_result->set_property_from_json("detail", detail.dump().c_str());
163+
ten_env.return_result(std::move(cmd_result), std::move(cmd));
164+
} else {
165+
test_cmd = std::move(cmd);
166+
return;
167+
}
168+
} else {
169+
TEN_ASSERT(0, "Should not happen.");
170+
}
171+
}
172+
173+
private:
174+
bool start_graph_cmd_is_done{};
175+
std::unique_ptr<ten::cmd_t> test_cmd;
176+
};
177+
178+
class test_app : public ten::app_t {
179+
public:
180+
void on_configure(ten::ten_env_t &ten_env) override {
181+
bool rc = ten::ten_env_internal_accessor_t::init_manifest_from_json(
182+
ten_env,
183+
// clang-format off
184+
R"({
185+
"type": "app",
186+
"name": "test_app",
187+
"version": "0.1.0"
188+
})"
189+
// clang-format on
190+
);
191+
ASSERT_EQ(rc, true);
192+
193+
rc = ten_env.init_property_from_json(
194+
// clang-format off
195+
R"({
196+
"_ten": {
197+
"addon": {
198+
"preload_all": true
199+
},
200+
"uri": "msgpack://127.0.0.1:8001/",
201+
"log_level": 2,
202+
"predefined_graphs": [{
203+
"name": "default",
204+
"auto_start": false,
205+
"singleton": true,
206+
"nodes": [{
207+
"type": "extension",
208+
"name": "predefined_graph",
209+
"addon": "start_graph_with_msg_conversion__predefined_graph_extension",
210+
"extension_group": "start_graph_with_msg_conversion__predefined_graph_group"
211+
}]
212+
}]
213+
}
214+
})"
215+
// clang-format on
216+
);
217+
ASSERT_EQ(rc, true);
218+
219+
ten_env.on_configure_done();
220+
}
221+
};
222+
223+
void *app_thread_main(TEN_UNUSED void *args) {
224+
auto *app = new test_app();
225+
app->run();
226+
delete app;
227+
228+
return nullptr;
229+
}
230+
231+
TEN_CPP_REGISTER_ADDON_AS_EXTENSION(
232+
start_graph_with_msg_conversion__predefined_graph_extension,
233+
test_predefined_graph);
234+
TEN_CPP_REGISTER_ADDON_AS_EXTENSION(test_normal_extension_1,
235+
test_normal_extension_1);
236+
TEN_CPP_REGISTER_ADDON_AS_EXTENSION(test_normal_extension_2,
237+
test_normal_extension_3);
238+
239+
} // namespace
240+
241+
TEST(StartGraphTest, StartGraphWithMsgConversion) { // NOLINT
242+
auto *app_thread = ten_thread_create("app thread", app_thread_main, nullptr);
243+
244+
// Create a client and connect to the app.
245+
auto *client = new ten::msgpack_tcp_client_t("msgpack://127.0.0.1:8001/");
246+
247+
// Do not need to send 'start_graph' command first.
248+
// The 'graph_id' MUST be "default" (a special string) if we want to send the
249+
// request to predefined graph.
250+
auto test_cmd = ten::cmd_t::create("test");
251+
test_cmd->set_dest("msgpack://127.0.0.1:8001/", "default",
252+
"start_graph_with_msg_conversion__predefined_graph_group",
253+
"predefined_graph");
254+
auto cmd_result = client->send_cmd_and_recv_result(std::move(test_cmd));
255+
ten_test::check_status_code(cmd_result, TEN_STATUS_CODE_OK);
256+
ten_test::check_detail_with_json(cmd_result, R"({"id": 1, "name": "a"})");
257+
258+
delete client;
259+
260+
ten_thread_join(app_thread, -1);
261+
}

0 commit comments

Comments
 (0)