feat(api-server): add container loadtest observability
This commit is contained in:
@@ -3,8 +3,8 @@ use std::{
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
use axum::Json;
|
||||
use serde_json::Value;
|
||||
use axum::response::Response;
|
||||
use bytes::Bytes;
|
||||
use shared_contracts::{
|
||||
puzzle_gallery::{PuzzleGalleryResponse, PuzzleGalleryWorkRefResponse},
|
||||
puzzle_works::PuzzleWorkSummaryResponse,
|
||||
@@ -14,7 +14,7 @@ use tokio::{
|
||||
time,
|
||||
};
|
||||
|
||||
use crate::{api_response::json_success_body, request_context::RequestContext};
|
||||
use crate::{api_response::json_success_data_bytes_response, request_context::RequestContext};
|
||||
|
||||
const PUZZLE_GALLERY_PRIMARY_ITEM_COUNT: usize = 10;
|
||||
const PUZZLE_GALLERY_PREVIEW_REF_COUNT: usize = 10;
|
||||
@@ -30,10 +30,21 @@ pub struct PuzzleGalleryCache {
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct PuzzleGalleryCacheEntry {
|
||||
response: PuzzleGalleryResponse,
|
||||
data_json: Bytes,
|
||||
built_at: Instant,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct PuzzleGalleryCachedResponse {
|
||||
data_json: Bytes,
|
||||
}
|
||||
|
||||
impl PuzzleGalleryCachedResponse {
|
||||
pub fn data_json_len(&self) -> usize {
|
||||
self.data_json.len()
|
||||
}
|
||||
}
|
||||
|
||||
impl PuzzleGalleryCache {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
@@ -46,22 +57,31 @@ impl PuzzleGalleryCache {
|
||||
self.rebuild_lock.lock().await
|
||||
}
|
||||
|
||||
pub async fn read_fresh_response(&self) -> Option<PuzzleGalleryResponse> {
|
||||
pub async fn read_fresh_response(&self) -> Option<PuzzleGalleryCachedResponse> {
|
||||
let guard = self.inner.read().await;
|
||||
let entry = guard.as_ref()?;
|
||||
let now = Instant::now();
|
||||
if now.duration_since(entry.built_at) > PUZZLE_GALLERY_CACHE_TTL {
|
||||
return None;
|
||||
}
|
||||
Some(entry.response.clone())
|
||||
Some(PuzzleGalleryCachedResponse {
|
||||
data_json: entry.data_json.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn store_response(&self, response: PuzzleGalleryResponse) {
|
||||
pub async fn store_response(
|
||||
&self,
|
||||
response: PuzzleGalleryResponse,
|
||||
) -> Result<PuzzleGalleryCachedResponse, serde_json::Error> {
|
||||
let now = Instant::now();
|
||||
let cached = PuzzleGalleryCachedResponse {
|
||||
data_json: Bytes::from(serde_json::to_vec(&response)?),
|
||||
};
|
||||
*self.inner.write().await = Some(PuzzleGalleryCacheEntry {
|
||||
response,
|
||||
data_json: cached.data_json.clone(),
|
||||
built_at: now,
|
||||
});
|
||||
Ok(cached)
|
||||
}
|
||||
|
||||
pub fn spawn_cleanup_task(&self) {
|
||||
@@ -118,9 +138,9 @@ pub fn build_puzzle_gallery_window_response(
|
||||
|
||||
pub fn puzzle_gallery_cached_json(
|
||||
request_context: &RequestContext,
|
||||
response: PuzzleGalleryResponse,
|
||||
) -> Json<Value> {
|
||||
json_success_body(Some(request_context), response)
|
||||
response: PuzzleGalleryCachedResponse,
|
||||
) -> Response {
|
||||
json_success_data_bytes_response(Some(request_context), response.data_json)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
Reference in New Issue
Block a user