Skip to content

Commit 5840e73

Browse files
authored
feat: updated appId inject logic (#937)
* feat: updated appId inject logic * feat: unit test added. * fix: logs updated.
1 parent bf2cfe8 commit 5840e73

File tree

1 file changed

+99
-95
lines changed

1 file changed

+99
-95
lines changed

core/main/src/firebolt/handlers/provider_registrar.rs

Lines changed: 99 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
// SPDX-License-Identifier: Apache-2.0
1616
//
1717

18-
use std::{sync::Arc, time::Duration};
18+
use std::{collections::HashMap, sync::Arc, time::Duration};
1919

2020
use crate::{
2121
firebolt::rpc::register_aliases,
@@ -50,6 +50,33 @@ use ripple_sdk::{
5050
};
5151
use serde_json::{Map, Value};
5252

53+
// The hardcoded JSON string remains a static global variable.
54+
static APP_INJECTION_METHOD_LIST_JSON: &str = r#"
55+
{
56+
"Discovery.userInterest": "Content.onUserInterest"
57+
}
58+
"#;
59+
60+
fn load_app_injection_method_list() -> HashMap<String, String> {
61+
let parse_result: Result<HashMap<String, String>, serde_json::Error> =
62+
serde_json::from_str(APP_INJECTION_METHOD_LIST_JSON);
63+
64+
match parse_result {
65+
// If parsing is successful (Ok), return the map.
66+
Ok(map) => {
67+
info!("APP_INJECTION_METHOD_LIST JSON successfully loaded.");
68+
map
69+
}
70+
Err(e) => {
71+
error!(
72+
"ERROR: Failed to parse APP_INJECTION_METHOD_LIST JSON string: {}",
73+
e
74+
);
75+
HashMap::new() // Default value: an empty HashMap
76+
}
77+
}
78+
}
79+
5380
// TODO: Add to config
5481
const DEFAULT_PROVIDER_RESPONSE_TIMEOUT_MS: u64 = 15000;
5582

@@ -308,41 +335,42 @@ impl ProviderRegistrar {
308335

309336
let result_value = match event_data {
310337
Value::Object(ref event_data_map) => {
311-
if let Some(event_schema_map) = context
312-
.platform_state
313-
.open_rpc_state
314-
.get_openrpc_validator()
315-
.get_closest_result_properties_schema(event, event_data_map)
316-
{
317-
// Populate the event result, injecting the app ID if the field exists in the event schema
318-
319-
let mut result_map = Map::new();
320-
321-
for key in event_schema_map.keys() {
322-
if let Some(event_value) = event_data_map.get(key) {
323-
result_map.insert(key.clone(), event_value.clone());
324-
} else if key.eq("appId") {
325-
if let Some(context) = call_context.clone() {
326-
result_map.insert(key.clone(), Value::String(context.app_id));
327-
} else {
328-
error!("callback_app_event_emitter: Missing call context, could not determine app ID");
329-
result_map.insert(key.clone(), Value::Null);
338+
let method_map = load_app_injection_method_list();
339+
let search_term = context.method.clone().to_lowercase();
340+
341+
let mut result_map = Map::new();
342+
for (key, value) in event_data_map {
343+
result_map.insert(key.clone(), value.clone());
344+
}
345+
346+
if method_map.is_empty() {
347+
info!("The map is currently empty. Cannot search for method.");
348+
} else {
349+
for (method, _handler_method) in method_map.iter() {
350+
if method.to_lowercase().contains(&search_term) {
351+
info!(
352+
"callback_app_event_emitter: Injection method found: {}",
353+
method
354+
);
355+
356+
if !result_map.contains_key("appId") {
357+
if let Some(context) = call_context.clone() {
358+
result_map.insert(
359+
"appId".to_string(),
360+
Value::String(context.app_id),
361+
);
362+
} else {
363+
error!("callback_app_event_emitter: Missing call context, could not determine app ID");
364+
result_map.insert("appId".to_string(), Value::Null);
365+
}
330366
}
331-
} else {
332-
error!(
333-
"callback_app_event_emitter: Missing field in event data: field={}",
334-
key);
335-
336-
// Assume the field in the schema holds the contents of the event. This
337-
// is the fragile part that should probably be addressed by a schema change.
338-
result_map.insert(key.clone(), event_data.clone());
367+
368+
break;
339369
}
340370
}
341-
342-
Value::Object(result_map)
343-
} else {
344-
event_data.clone()
345371
}
372+
373+
Value::Object(result_map)
346374
}
347375
_ => event_data.clone(),
348376
};
@@ -529,73 +557,31 @@ impl ProviderRegistrar {
529557
}
530558
};
531559

532-
let result_properties_map = match context
533-
.platform_state
534-
.open_rpc_state
535-
.get_openrpc_validator()
536-
.get_closest_result_properties_schema(
537-
&context.method,
538-
provider_response_value_map,
539-
) {
540-
Some(result_properties_map) => result_properties_map,
541-
None => {
542-
error!("callback_provider_invoker: Result schema not found");
543-
return Err(Error::Custom(String::from("Result schema not found")));
544-
}
545-
};
546-
547-
// Inject the provider app ID if the field exists in the provided-to response schema, the other field will be
548-
// the provider response. The firebolt spec is not ideal in that the provider response data is captured
549-
// within a field of the provided-to's response object, hence the somewhat arbritrary logic here. Ideally
550-
// the provided-to response object would be identical to the provider response object aside from an optional
551-
// appId field.
560+
let method_map = load_app_injection_method_list();
561+
let search_term = context.method.clone().to_lowercase();
552562

553563
let mut response_map = Map::new();
554-
for key in result_properties_map.keys() {
555-
if let Some(field) = provider_response_value_map.get(key) {
556-
response_map.insert(key.clone(), field.clone());
557-
} else if key.eq("appId") {
558-
response_map.insert(
559-
key.clone(),
560-
Value::String(provider_app_id.clone().unwrap_or_default()),
561-
);
562-
} else if let Some(Value::Object(result_property_map)) =
563-
result_properties_map.get(key)
564-
{
565-
let reference_path = match result_property_map.get("$ref") {
566-
Some(Value::String(path)) => path,
567-
_ => {
568-
error!("callback_provider_invoker: $ref not found: key={}", key);
569-
continue;
570-
}
571-
};
572-
573-
if let Some(ref_properties_map) = context
574-
.platform_state
575-
.open_rpc_state
576-
.get_openrpc_validator()
577-
.get_result_ref_schema(reference_path)
578-
{
579-
// If any (!) of the keys match, assume the field in the schema holds the contents of the provider response. This
580-
// is the fragile part that should be addressed by a spec change, as Ripple can only guess at intention.
581-
582-
if provider_response_value_map
583-
.keys()
584-
.any(|key| ref_properties_map.contains_key(key))
585-
{
586-
response_map.insert(key.clone(), provider_response_value.clone());
587-
588-
// Just bail now, we're dumping the complete provider response into the response map
589-
// under some key in the schema, so it's either right or wrong but continuing to iterate
590-
// would be wrong-er.
591-
592-
return Ok(Value::Object(response_map));
564+
for (key, value) in provider_response_value_map {
565+
response_map.insert(key.clone(), value.clone());
566+
}
567+
568+
if method_map.is_empty() {
569+
info!("The map is currently empty. Cannot search for method.");
570+
} else {
571+
for (method, _handler_method) in method_map.iter() {
572+
if method.to_lowercase().contains(&search_term) {
573+
info!(
574+
"callback_provider_invoker: Injection method found: {}",
575+
method
576+
);
577+
578+
if !response_map.contains_key("appId") {
579+
if let Some(app_id) = provider_app_id.clone() {
580+
response_map.insert("appId".to_string(), Value::String(app_id));
581+
}
593582
}
594-
} else {
595-
error!("callback_provider_invoker: ref_properties_map not found");
583+
break;
596584
}
597-
} else {
598-
error!("callback_provider_invoker: Not an object: key={}", key);
599585
}
600586
}
601587
Ok(Value::Object(response_map))
@@ -1049,4 +1035,22 @@ mod tests {
10491035
assert!(c.message.eq("The Player with 'ipa' id does not exist"))
10501036
}
10511037
}
1038+
1039+
#[test]
1040+
fn test_load_app_injection_method_list() {
1041+
let method_map = load_app_injection_method_list();
1042+
assert!(!method_map.is_empty());
1043+
}
1044+
1045+
#[test]
1046+
fn test_load_app_injection_method_list_values() {
1047+
let method_map = load_app_injection_method_list();
1048+
for (key, value) in method_map.iter() {
1049+
if key.eq("Discovery.userInterest") {
1050+
assert!(value.eq("Content.onUserInterest"));
1051+
}
1052+
1053+
assert!(method_map.contains_key("Discovery.userInterest"));
1054+
}
1055+
}
10521056
}

0 commit comments

Comments
 (0)