record-daemon: refactor client.rs, dropping metadata
record-daemon / Build, check and test (push) Successful in 2m17s

This commit is contained in:
2026-03-26 11:03:24 +01:00
parent c576ac2b34
commit 2814d85b6b
6 changed files with 192 additions and 265 deletions
+79 -130
View File
@@ -56,8 +56,8 @@ struct Daemon {
event_mapper: Arc<RwLock<EventMapper>>,
/// Current recording ID (if recording).
current_recording_id: Arc<RwLock<Option<uuid::Uuid>>>,
/// Pre-game metadata (collected before game starts).
pregame_metadata: Arc<RwLock<Option<record_daemon::lqp::PreGameMetadata>>>,
/// Pre-game data (collected before game starts).
pregame_data: Arc<RwLock<Option<record_daemon::lqp::PreGameData>>>,
/// IPC server.
ipc_server: Option<IpcServer>,
/// Shutdown signal.
@@ -77,7 +77,7 @@ impl Daemon {
timeline_store: Arc::new(RwLock::new(TimelineStore::new())),
event_mapper: Arc::new(RwLock::new(EventMapper::new())),
current_recording_id: Arc::new(RwLock::new(None)),
pregame_metadata: Arc::new(RwLock::new(None)),
pregame_data: Arc::new(RwLock::new(None)),
ipc_server: None,
shutdown_tx,
}
@@ -229,17 +229,17 @@ impl Daemon {
async fn handle_game_event(&self, event: GameEvent) -> Result<()> {
info!("[EVENT_HANDLER] Game event received: {:?}", event);
// Handle pre-game metadata collection
// Handle pre-game data collection
match &event {
GameEvent::PhaseChange(info) if info.phase == "ChampSelect" => {
info!("[EVENT_HANDLER] Champion select started, fetching pre-game metadata");
match self.lqp_client.fetch_pregame_metadata().await {
Ok(metadata) => {
info!("[EVENT_HANDLER] Pre-game metadata fetched: {:?}", metadata);
*self.pregame_metadata.write() = Some(metadata);
info!("[EVENT_HANDLER] Champion select started, fetching pre-game data");
match self.lqp_client.fetch_pregame_data().await {
Ok(data) => {
info!("[EVENT_HANDLER] Pre-game data fetched: {:?}", data);
*self.pregame_data.write() = Some(data);
}
Err(e) => {
warn!("[EVENT_HANDLER] Failed to fetch pre-game metadata: {}", e);
warn!("[EVENT_HANDLER] Failed to fetch pre-game data: {}", e);
}
}
}
@@ -248,13 +248,8 @@ impl Daemon {
"[EVENT_HANDLER] Local player picked champion: {}",
pick.champion_name
);
let mut metadata = self.pregame_metadata.write();
if let Some(ref mut meta) = *metadata {
meta.champion_id = Some(pick.champion_id);
if let Some(_skin_name) = &pick.skin_name {
// Store skin name for later use
}
}
// Champion pick info is now stored in champion_select response
// No need to manually update - refetch if needed
}
GameEvent::GameStart(info) => {
info!(
@@ -262,13 +257,13 @@ impl Daemon {
info.queue_type, info.game_mode, info.map_name
);
// Update pre-game metadata with game start info
let mut pregame = self.pregame_metadata.write();
// Update pre-game data with game start info if needed
let mut pregame = self.pregame_data.write();
// Extract player-specific data from session using puuid
let (champion_id, team, summoner_name) = if let Some(ref session) = info.session {
// Get puuid from pregame metadata (fetched earlier)
let puuid = pregame.as_ref().and_then(|m| m.local_puuid.as_ref());
let (_champion_id, _team, summoner_name) = if let Some(ref session) = info.session {
// Get puuid from pregame data (fetched earlier)
let puuid = pregame.as_ref().and_then(|d| d.puuid());
if let Some(puuid) = puuid {
// Use the puuid to find the correct player's data
@@ -289,45 +284,24 @@ impl Daemon {
(None, None, None)
};
if let Some(ref mut meta) = *pregame {
// Fill in champion_id from session if not already set
if meta.champion_id.is_none() {
meta.champion_id = champion_id;
}
// Fill in team from session if not already set
if meta.team.is_none() {
meta.team = team;
}
// Fill in summoner_name from session if not already set
if meta.summoner_name.is_none() {
meta.summoner_name = summoner_name;
}
// Fill in queue info
if meta.queue_type.is_none() {
meta.queue_type = info.queue_type.clone();
}
if meta.queue_id.is_none() {
meta.queue_id = info.queue_id;
}
if meta.game_mode.is_none() {
meta.game_mode = info.game_mode.clone();
}
if meta.map_name.is_none() {
meta.map_name = info.map_name.clone();
}
} else {
// Create pre-game metadata from game start info
*pregame = Some(record_daemon::lqp::PreGameMetadata {
summoner_name,
champion_id,
skin_id: None,
rune_page_name: None,
queue_type: info.queue_type.clone(),
queue_id: info.queue_id,
game_mode: info.game_mode.clone(),
map_name: info.map_name.clone(),
team,
local_puuid: None,
// If we don't have pre-game data, create minimal from game start info
if pregame.is_none() {
use record_daemon::lqp::{GameflowSessionResponse, PreGameData};
*pregame = Some(PreGameData {
session: Some(GameflowSessionResponse {
map: info.map_name.clone(),
game_mode: info.game_mode.clone(),
queue_id: info.queue_id.map(|id| id as u64),
..Default::default()
}),
summoner: summoner_name.map(|name| {
use record_daemon::lqp::SummonerResponse;
SummonerResponse {
display_name: Some(name),
..Default::default()
}
}),
..Default::default()
});
}
}
@@ -434,7 +408,7 @@ impl Daemon {
}
// Get pre-game metadata to pass to recording
let pregame = self.pregame_metadata.read().clone();
let pregame = self.pregame_data.read().clone();
let champion_name = champion.or_else(|| {
pregame.as_ref().and({
// Try to get champion name from metadata if not provided
@@ -519,49 +493,16 @@ impl Daemon {
let fetched_final_items =
self.lqp_client.fetch_final_items().await.ok().flatten();
// Convert GameEndInfo to GameEndMetadata if available
let game_end_metadata =
game_end_info.map(|info| record_daemon::lqp::GameEndMetadata {
victory: Some(info.victory),
match_id: None,
kills: info.stats.as_ref().map(|s| s.kills).unwrap_or(0),
deaths: info.stats.as_ref().map(|s| s.deaths).unwrap_or(0),
assists: info.stats.as_ref().map(|s| s.assists).unwrap_or(0),
creep_score: info
.stats
.as_ref()
.map(|s| s.minions_killed)
.unwrap_or(0),
gold_earned: info
.stats
.as_ref()
.map(|s| s.gold_earned)
.unwrap_or(0),
damage_dealt: info
.stats
.as_ref()
.map(|s| s.damage_dealt)
.unwrap_or(0),
damage_taken: info
.stats
.as_ref()
.map(|s| s.damage_taken)
.unwrap_or(0),
vision_score: info
.stats
.as_ref()
.map(|s| s.vision_score)
.unwrap_or(0.0),
game_duration: info.duration,
});
// Fetch end-of-game stats from API
let game_end_stats = self.lqp_client.fetch_game_end_stats().await.ok();
info!(
"[EVENT_HANDLER] Game end metadata from event: {:?}",
game_end_metadata
"[EVENT_HANDLER] Game end stats from API: {:?}",
game_end_stats
);
if let Err(e) = self
.stop_recording_with_metadata(game_end_metadata, fetched_final_items)
.stop_recording_with_metadata(game_end_stats, fetched_final_items)
.await
{
error!("[EVENT_HANDLER] Failed to stop recording: {}", e);
@@ -569,8 +510,8 @@ impl Daemon {
// Don't propagate error - keep daemon running
}
// Clear pre-game metadata
*self.pregame_metadata.write() = None;
// Clear pre-game data
*self.pregame_data.write() = None;
}
_ => {}
}
@@ -656,10 +597,10 @@ impl Daemon {
self.stop_recording_with_metadata(None, None).await
}
/// Stop recording with optional game end metadata.
/// Stop recording with optional game end stats.
async fn stop_recording_with_metadata(
&self,
game_end_metadata: Option<record_daemon::lqp::GameEndMetadata>,
game_end_stats: Option<record_daemon::lqp::EndOfGameStatsResponse>,
final_items: Option<record_daemon::lqp::ItemBuild>,
) -> Result<()> {
info!("Stopping recording");
@@ -671,7 +612,7 @@ impl Daemon {
let recording_engine = self.recording_engine.clone();
let event_mapper = self.event_mapper.clone();
let timeline_store = self.timeline_store.clone();
let pregame_metadata = self.pregame_metadata.read().clone();
let pregame_data = self.pregame_data.read().clone();
// Use spawn_blocking to avoid blocking the async runtime
tokio::task::spawn_blocking(move || {
@@ -698,35 +639,43 @@ impl Daemon {
// Update metadata if we have it
let mut update = record_daemon::timeline::MetadataUpdate::default();
// Add pre-game metadata
if let Some(pregame) = pregame_metadata {
// Add pre-game data
if let Some(pregame) = pregame_data {
// Convert champion_id to name if available
if let Some(champion_id) = pregame.champion_id {
update.champion = record_daemon::lqp::champion_id_to_name(champion_id);
if let Some(champion_id) = pregame.champion_id() {
update.champion =
record_daemon::lqp::champion_id_to_name(champion_id as u32);
}
update.summoner_name = pregame.summoner_name;
update.queue_type = pregame.queue_type;
update.queue_id = pregame.queue_id;
update.game_mode = pregame.game_mode;
update.map_name = pregame.map_name;
update.team = pregame.team;
update.summoner_name = pregame.summoner_name().map(|s| s.to_string());
update.queue_id = pregame.queue_id().map(|id| id as u32);
update.game_mode = pregame.game_mode().map(|s| s.to_string());
update.map_name = pregame.map_name().map(|s| s.to_string());
update.team = pregame.team().map(|id| id as u32);
}
// Add game end metadata
if let Some(end_meta) = game_end_metadata {
update.match_id = end_meta.match_id;
update.victory = end_meta.victory;
update.final_stats = Some(record_daemon::timeline::GameFinalStats {
kills: end_meta.kills,
deaths: end_meta.deaths,
assists: end_meta.assists,
creep_score: end_meta.creep_score,
gold_earned: end_meta.gold_earned,
damage_dealt: end_meta.damage_dealt,
damage_taken: end_meta.damage_taken,
vision_score: end_meta.vision_score,
game_duration: end_meta.game_duration,
});
// Add game end stats from API response
if let Some(stats) = game_end_stats {
update.victory = Some(stats.is_victory());
update.match_id = stats.match_id.map(|id| id.to_string());
// Get local player stats
if let Some(player) = stats.get_local_player() {
if let Some(player_stats) = &player.stats {
update.final_stats = Some(record_daemon::timeline::GameFinalStats {
kills: player_stats.champions_killed.unwrap_or(0) as u32,
deaths: player_stats.num_deaths.unwrap_or(0) as u32,
assists: player_stats.assists.unwrap_or(0) as u32,
creep_score: player_stats.minions_killed.unwrap_or(0) as u32,
gold_earned: player_stats.gold_earned.unwrap_or(0) as u32,
damage_dealt: player_stats
.total_damage_dealt_to_champions
.unwrap_or(0),
damage_taken: player_stats.total_damage_taken.unwrap_or(0),
vision_score: player_stats.vision_score.unwrap_or(0.0),
game_duration: stats.game_length.unwrap_or(0.0),
});
}
}
}
// Add final items