Skip to content

Commit 8cb7519

Browse files
committed
Iteration
1 parent 018dba9 commit 8cb7519

File tree

2 files changed

+53
-74
lines changed

2 files changed

+53
-74
lines changed

lib/executor/src/plugins/response_cache.rs

Lines changed: 38 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
11
use dashmap::DashMap;
22
use ntex::web::HttpResponse;
33
use redis::Commands;
4-
use sonic_rs::json;
54

65
use crate::{
7-
plugins::traits::{
8-
ControlFlow, OnExecuteEnd, OnExecuteEndPayload, OnExecuteStart, OnExecuteStartPayload,
9-
OnSchemaReload, OnSchemaReloadPayload,
10-
},
6+
plugins::traits::{ControlFlow, OnExecuteControlFlow, OnExecutePayload, OnSchemaReloadPayload, RouterPlugin},
117
utils::consts::TYPENAME_FIELD_NAME,
128
};
139

@@ -26,20 +22,15 @@ impl ResponseCachePlugin {
2622
}
2723
}
2824

29-
pub struct ResponseCacheContext {
30-
key: String,
31-
}
32-
33-
impl OnExecuteStart for ResponseCachePlugin {
34-
fn on_execute_start(&self, payload: OnExecuteStartPayload) -> ControlFlow {
25+
impl RouterPlugin for ResponseCachePlugin {
26+
fn on_execute<'exec>(
27+
&'static self,
28+
payload: OnExecutePayload<'exec>,
29+
) -> OnExecuteControlFlow<'exec> {
3530
let key = format!(
3631
"response_cache:{}:{:?}",
3732
payload.query_plan, payload.variable_values
3833
);
39-
payload
40-
.router_http_request
41-
.extensions_mut()
42-
.insert(ResponseCacheContext { key: key.clone() });
4334
if let Ok(mut conn) = self.redis_client.get_connection() {
4435
let cached_response: Option<Vec<u8>> = conn.get(&key).ok();
4536
if let Some(cached_response) = cached_response {
@@ -50,61 +41,47 @@ impl OnExecuteStart for ResponseCachePlugin {
5041
);
5142
}
5243
}
53-
ControlFlow::Continue
54-
}
55-
}
44+
return ControlFlow::OnEnd(Box::new(move |payload| {
45+
// Do not cache if there are errors
46+
if !payload.errors.is_empty() {
47+
return ();
48+
}
5649

57-
impl OnExecuteEnd for ResponseCachePlugin {
58-
fn on_execute_end(&self, payload: OnExecuteEndPayload) -> ControlFlow {
59-
// Do not cache if there are errors
60-
if !payload.errors.is_empty() {
61-
return ControlFlow::Continue;
62-
}
63-
if let Some(key) = payload
64-
.router_http_request
65-
.extensions()
66-
.get::<ResponseCacheContext>()
67-
.map(|ctx| &ctx.key)
68-
{
69-
if let Ok(mut conn) = self.redis_client.get_connection() {
70-
if let Ok(serialized) = sonic_rs::to_vec(&payload.data) {
71-
// Decide on the ttl somehow
72-
// Get the type names
73-
let mut max_ttl = 0;
50+
if let Ok(mut conn) = self.redis_client.get_connection() {
51+
if let Ok(serialized) = sonic_rs::to_vec(&payload.data) {
52+
// Decide on the ttl somehow
53+
// Get the type names
54+
let mut max_ttl = 0;
7455

75-
// Imagine this code is traversing the response data to find type names
76-
if let Some(obj) = payload.data.as_object() {
77-
if let Some(typename) = obj
78-
.iter()
79-
.position(|(k, _)| k == &TYPENAME_FIELD_NAME)
80-
.and_then(|idx| obj[idx].1.as_str())
81-
{
82-
if let Some(ttl) = self.ttl_per_type.get(typename).map(|v| *v) {
83-
max_ttl = max_ttl.max(ttl);
56+
// Imagine this code is traversing the response data to find type names
57+
if let Some(obj) = payload.data.as_object() {
58+
if let Some(typename) = obj
59+
.iter()
60+
.position(|(k, _)| k == &TYPENAME_FIELD_NAME)
61+
.and_then(|idx| obj[idx].1.as_str())
62+
{
63+
if let Some(ttl) = self.ttl_per_type.get(typename).map(|v| *v) {
64+
max_ttl = max_ttl.max(ttl);
65+
}
8466
}
8567
}
86-
}
8768

88-
// If no ttl found, default to 60 seconds
89-
if max_ttl == 0 {
90-
max_ttl = 60;
91-
}
69+
// If no ttl found, default to 60 seconds
70+
if max_ttl == 0 {
71+
max_ttl = 60;
72+
}
9273

93-
// Insert the ttl into extensions for client awareness
94-
payload
95-
.extensions
96-
.insert("response_cache_ttl".to_string(), json!(max_ttl));
74+
// Insert the ttl into extensions for client awareness
75+
payload
76+
.extensions
77+
.insert("response_cache_ttl".to_string(), sonic_rs::json!(max_ttl));
9778

98-
// Set the cache with the decided ttl
99-
let _: () = conn.set_ex(key, serialized, max_ttl).unwrap_or(());
79+
// Set the cache with the decided ttl
80+
let _: () = conn.set_ex(key, serialized, max_ttl).unwrap_or(());
81+
}
10082
}
101-
}
102-
}
103-
ControlFlow::Continue
83+
}));
10484
}
105-
}
106-
107-
impl OnSchemaReload for ResponseCachePlugin {
10885
fn on_schema_reload(&self, payload: OnSchemaReloadPayload) {
10986
// Visit the schema and update ttl_per_type based on some directive
11087
payload

lib/executor/src/plugins/traits.rs

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::hash::Hash;
12
use std::{collections::HashMap, sync::Arc};
23

34
use hive_router_query_planner::consumer_schema::ConsumerSchema;
@@ -8,8 +9,9 @@ use ntex::web::HttpResponse;
89
use crate::response::graphql_error::GraphQLError;
910
use crate::response::value::Value;
1011

11-
pub enum ControlFlow {
12+
pub enum ControlFlow<TEndPayload> {
1213
Continue,
14+
OnEnd(Box<dyn FnOnce(TEndPayload) -> ()>),
1315
Break(HttpResponse),
1416
}
1517

@@ -19,21 +21,29 @@ pub struct ExecutionResult<'exec> {
1921
pub extensions: &'exec mut Option<HashMap<String, Value<'exec>>>,
2022
}
2123

22-
pub struct OnExecuteStartPayload<'exec> {
24+
pub struct OnExecutePayload<'exec> {
2325
pub router_http_request: &'exec HttpRequest,
2426
pub query_plan: Arc<QueryPlan>,
2527

2628
pub data: &'exec mut Value<'exec>,
2729
pub errors: &'exec mut Vec<GraphQLError>,
28-
pub extensions: Option<&'exec mut sonic_rs::Value>,
30+
pub extensions: &'exec mut HashMap<String, sonic_rs::Value>,
2931

3032
pub skip_execution: bool,
3133

3234
pub variable_values: &'exec Option<HashMap<String, sonic_rs::Value>>,
3335
}
3436

35-
pub trait OnExecuteStart {
36-
fn on_execute_start(&self, payload: OnExecuteStartPayload) -> ControlFlow;
37+
pub type OnExecuteControlFlow<'exec> = ControlFlow<OnExecutePayload<'exec>>;
38+
39+
pub trait RouterPlugin {
40+
fn on_execute<'exec>(
41+
&'static self,
42+
_payload: OnExecutePayload<'exec>,
43+
) -> ControlFlow<OnExecutePayload<'exec>> {
44+
ControlFlow::Continue
45+
}
46+
fn on_schema_reload(&self, _payload: OnSchemaReloadPayload) {}
3747
}
3848

3949
pub struct OnExecuteEndPayload<'exec> {
@@ -47,15 +57,7 @@ pub struct OnExecuteEndPayload<'exec> {
4757
pub variable_values: &'exec Option<HashMap<String, sonic_rs::Value>>,
4858
}
4959

50-
pub trait OnExecuteEnd {
51-
fn on_execute_end(&self, payload: OnExecuteEndPayload) -> ControlFlow;
52-
}
53-
5460
pub struct OnSchemaReloadPayload {
5561
pub old_schema: &'static ConsumerSchema,
5662
pub new_schema: &'static mut ConsumerSchema,
5763
}
58-
59-
pub trait OnSchemaReload {
60-
fn on_schema_reload(&self, payload: OnSchemaReloadPayload);
61-
}

0 commit comments

Comments
 (0)