reactive_graph_net_http/behaviour/component/
json_rpc.rs1use reactive_graph_behaviour_model_api::behaviour_validator;
2use reactive_graph_behaviour_model_api::prelude::*;
3use reactive_graph_behaviour_model_impl::entity_behaviour;
4use reactive_graph_graph::prelude::*;
5use reactive_graph_reactive_model_impl::ReactiveEntity;
6use serde_json::Value;
7use serde_json::json;
8use uuid::Uuid;
9
10use log::error;
11
12use reactive_graph_net_http_model::JsonRpcProperties::ERROR;
13use reactive_graph_net_http_model::JsonRpcProperties::JSON_RPC_VERSION;
14use reactive_graph_net_http_model::JsonRpcProperties::METHOD;
15use reactive_graph_net_http_model::JsonRpcProperties::PARAMS;
16use reactive_graph_net_http_model::UrlProperties::URL;
17use reactive_graph_runtime_model::ActionProperties::TRIGGER;
18use reactive_graph_std_result_model::ResultObjectProperties::RESULT;
19
20entity_behaviour!(JsonRpc, JsonRpcFactory, JsonRpcFsm, JsonRpcBehaviourTransitions, JsonRpcValidator);
21
22behaviour_validator!(
23 JsonRpcValidator,
24 Uuid,
25 ReactiveEntity,
26 METHOD.as_ref(),
27 JSON_RPC_VERSION.as_ref(),
28 PARAMS.as_ref(),
29 ERROR.as_ref(),
30 RESULT.as_ref(),
31 URL.as_ref()
32);
33
34impl BehaviourInit<Uuid, ReactiveEntity> for JsonRpcBehaviourTransitions {}
35
36impl BehaviourConnect<Uuid, ReactiveEntity> for JsonRpcBehaviourTransitions {
37 fn connect(&self) -> Result<(), BehaviourConnectFailed> {
38 let reactive_instance = self.reactive_instance.clone();
39 self.property_observers.observe_with_handle(TRIGGER.as_ref(), move |trigger: &Value| {
40 if !trigger.as_bool().unwrap_or(false) {
41 return;
42 }
43 let Some(method) = reactive_instance.as_string(METHOD) else {
44 return;
45 };
46 let Some(url) = reactive_instance.as_string(URL) else {
47 return;
48 };
49 let Some(params) = reactive_instance.get(PARAMS) else {
50 return;
51 };
52 if !params.is_object() && !params.is_array() {
53 return;
55 }
56 let json_rpc_version = reactive_instance
57 .as_string(JSON_RPC_VERSION)
58 .unwrap_or_else(|| JSON_RPC_VERSION.default_value().to_string());
59
60 let payload = json!({
62 "jsonrpc": json_rpc_version,
63 "method": method,
64 "params": params,
65 "id": 1_u32
66 });
67
68 let request = ureq::post(url.as_str()).set("content-type", "application/json");
69
70 let result = request.send_json(payload);
71 match result {
72 Ok(response) => match response.into_json() {
73 Ok(response_payload) => {
74 let json_rpc_response: Value = response_payload;
75 match json_rpc_response.get(RESULT.as_ref()) {
76 Some(result) => {
77 reactive_instance.set(RESULT, result.clone());
78 reactive_instance.set(ERROR, json!({}));
79 }
80 None => {
81 if let Some(error) = json_rpc_response.get(ERROR.as_ref()) {
82 reactive_instance.set(ERROR, error.clone());
83 reactive_instance.set(RESULT, json!({}));
84 }
85 }
86 }
87 }
88 Err(e) => error!("Failed to parse response as JSON: {}", e.to_string()),
89 },
90 Err(e) => {
91 error!("Failed to send request: {}", e.to_string());
92 }
93 }
94 });
95 Ok(())
96 }
97}
98
99impl BehaviourShutdown<Uuid, ReactiveEntity> for JsonRpcBehaviourTransitions {}
100impl BehaviourTransitions<Uuid, ReactiveEntity> for JsonRpcBehaviourTransitions {}