Skip to content

Commit bf325eb

Browse files
authored
feat: make the task client hold the http connection (#240)
1 parent 82d974b commit bf325eb

File tree

8 files changed

+57
-30
lines changed

8 files changed

+57
-30
lines changed

Cargo.lock

+4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/src/logic/knowledge.rs

+5-14
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,11 @@
1-
use super::{read_without_key, HookExt, PublicExt, ReadResponse, RequestExt};
2-
use crate::{
3-
router::ServerResponse,
4-
server::{AppState, AppStores},
5-
};
6-
use axum::{
7-
extract::{Query, State},
8-
routing::get,
9-
Json, Router,
10-
};
1+
use super::{read_without_key, HookExt, PublicExt, RequestExt};
2+
use crate::server::{AppState, AppStores};
3+
use axum::{routing::get, Router};
114
use bson::doc;
12-
use entities::{record_metadata::RecordMetadata, Id, MongoStore, PicaError};
5+
use entities::{record_metadata::RecordMetadata, Id, MongoStore};
136
use fake::Dummy;
14-
use http::HeaderMap;
157
use serde::{Deserialize, Serialize};
16-
use serde_json::Value;
17-
use std::{collections::BTreeMap, sync::Arc};
8+
use std::sync::Arc;
189

1910
pub fn get_router() -> Router<Arc<AppState>> {
2011
Router::new().route("/", get(read_without_key::<ReadRequest, Knowledge>))

api/src/logic/tasks.rs

+3
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ pub struct CreateRequest {
3131
pub start_time: i64,
3232
pub endpoint: String,
3333
pub payload: Value,
34+
#[serde(rename = "await")]
35+
pub r#await: bool,
3436
}
3537

3638
impl RequestExt for CreateRequest {
@@ -44,6 +46,7 @@ impl RequestExt for CreateRequest {
4446
payload: self.payload.clone(),
4547
endpoint: self.endpoint.clone(),
4648
status: None,
49+
r#await: self.r#await,
4750
metadata: RecordMetadata::default(),
4851
})
4952
}

api/tests/context.rs

+14-6
Original file line numberDiff line numberDiff line change
@@ -129,9 +129,9 @@ impl TestServer {
129129
// Get available port for server to listen
130130
let port = TcpListener::bind("127.0.0.1:0")
131131
.await
132-
.unwrap()
132+
.expect("Could not bind to port")
133133
.local_addr()
134-
.unwrap()
134+
.expect("Could not get local address")
135135
.port();
136136

137137
// Random database name
@@ -159,7 +159,7 @@ impl TestServer {
159159
"ios-kms".to_string(),
160160
),
161161
]))
162-
.unwrap();
162+
.expect("Could not create envconfig");
163163

164164
let secrets_client = Arc::new(MockSecretsClient);
165165

@@ -178,10 +178,14 @@ impl TestServer {
178178
let iv = rand::thread_rng().gen::<[u8; 16]>();
179179
let live_encrypted_key = live_access_key
180180
.encode(
181-
&config.event_access_password.as_bytes().try_into().unwrap(),
181+
&config
182+
.event_access_password
183+
.as_bytes()
184+
.try_into()
185+
.expect("Could not convert to bytes"),
182186
&iv,
183187
)
184-
.unwrap();
188+
.expect("Could not encode access key");
185189

186190
let prefix = AccessKeyPrefix {
187191
environment: Environment::Test,
@@ -191,7 +195,11 @@ impl TestServer {
191195
let test_access_key = AccessKey { prefix, data };
192196
let test_encrypted_key = test_access_key
193197
.encode(
194-
&config.event_access_password.as_bytes().try_into().unwrap(),
198+
&config
199+
.event_access_password
200+
.as_bytes()
201+
.try_into()
202+
.expect("Could not convert to array"),
195203
&iv,
196204
)
197205
.unwrap();

entities/src/domain/event/task.rs

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ pub struct Task {
1414
pub endpoint: String,
1515
#[serde(with = "http_serde_ext_ios::status_code::option")]
1616
pub status: Option<StatusCode>,
17+
pub r#await: bool,
1718
#[serde(flatten)]
1819
pub metadata: RecordMetadata,
1920
}

watchdog/Cargo.toml

+6-1
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,15 @@ envconfig.workspace = true
1212
futures.workspace = true
1313
cache = { path = "../cache" }
1414
entities = { path = "../entities" }
15-
reqwest.workspace = true
15+
reqwest = { workspace = true, features = ["stream"] }
1616
serde_json.workspace = true
1717
mongodb.workspace = true
1818
redis.workspace = true
1919
tokio.workspace = true
2020
tracing.workspace = true
2121

22+
[dev-dependencies]
23+
testcontainers-modules = { workspace = true, features = ["mongo", "redis"] }
24+
mockito.workspace = true
25+
tracing-subscriber.workspace = true
26+
uuid.workspace = true

watchdog/src/client.rs

+23-8
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::config::WatchdogConfig;
1+
use crate::config::{self, WatchdogConfig};
22
use bson::doc;
33
use cache::remote::RedisCache;
44
use chrono::Utc;
@@ -39,9 +39,7 @@ impl WatchdogClient {
3939
cache: CacheConfig,
4040
database: DatabaseConfig,
4141
) -> Result<Self, PicaError> {
42-
let http_client = reqwest::ClientBuilder::new()
43-
.timeout(Duration::from_secs(watchdog.http_client_timeout_secs))
44-
.build()?;
42+
let http_client = reqwest::ClientBuilder::new().build()?;
4543
let client = mongodb::Client::with_uri_str(&database.event_db_url).await?;
4644
let db = client.database(&database.event_db_name);
4745

@@ -105,11 +103,12 @@ impl WatchdogClient {
105103

106104
let client = self.client.clone();
107105
let tasks_store = self.tasks.clone();
106+
let timeout = self.watchdog.http_client_timeout_secs;
108107

109108
tokio::spawn(async move {
110109
let mut tasks = tasks
111110
.into_iter()
112-
.map(|task| execute(task, client.clone(), tasks_store.clone()))
111+
.map(|task| execute(task, client.clone(), tasks_store.clone(), timeout))
113112
.collect::<FuturesUnordered<_>>();
114113

115114
while let Some(result) = tasks.next().await {
@@ -136,22 +135,38 @@ async fn execute(
136135
task: Task,
137136
http_client: reqwest::Client,
138137
tasks_store: MongoStore<Task>,
138+
timeout: u64,
139139
) -> Result<Id, PicaError> {
140-
let request = http_client
140+
let timeout = if task.r#await {
141+
Duration::from_secs(300)
142+
} else {
143+
Duration::from_secs(timeout)
144+
};
145+
146+
let response = http_client
141147
.post(task.endpoint)
148+
.timeout(timeout)
142149
.json(&task.payload)
143150
.send()
144151
.await?;
145152

153+
let status = response.status();
154+
let mut stream = response.bytes_stream();
155+
156+
while let Some(item) = stream.next().await {
157+
tracing::debug!("Response from API {:?}", item);
158+
tracing::info!("Response length from API {:?}", item.map(|b| b.len()));
159+
}
160+
146161
tasks_store
147162
.collection
148163
.find_one_and_update(
149164
doc! {
150165
"_id": task.id.to_string() // Filter by task ID
151166
},
152167
doc! {
153-
"$set": { // Use the $set operator correctly
154-
"status": request.status().to_string(),
168+
"$set": {
169+
"status": status.to_string(),
155170
"endTime": Utc::now().timestamp_millis(),
156171
"active": false
157172
}

watchdog/src/config.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use std::fmt::{Display, Formatter};
44

55
#[derive(Envconfig, Clone)] // Intentionally no Debug so secret is not printed
66
pub struct WatchdogConfig {
7-
#[envconfig(from = "RATE_LIMITER_REFRESH_INTERVAL", default = "60")]
7+
#[envconfig(from = "RATE_LIMITER_REFRESH_INTERVAL", default = "10")]
88
pub rate_limiter_refresh_interval: u64,
99
#[envconfig(from = "HTTP_CLIENT_TIMEOUT_SECS", default = "10")]
1010
pub http_client_timeout_secs: u64,

0 commit comments

Comments
 (0)