Skip to content

Commit b7a5d1e

Browse files
authored
Merge pull request #19 from MickeyPvX/fix/caching
fix: caching logic not working properly
2 parents 2daacf6 + a0aa7d2 commit b7a5d1e

9 files changed

Lines changed: 116 additions & 188 deletions

File tree

Cargo.lock

Lines changed: 6 additions & 80 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "espn-ffl"
3-
version = "2.1.1"
3+
version = "2.1.2"
44
edition = "2021"
55

66
[dependencies]

src/cli/types/filters.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use std::fmt;
1212
///
1313
/// - **Server-side** (efficient): `Active`, `Injured`
1414
/// - **Client-side** (less efficient): Specific statuses like `Out`, `Doubtful`, etc.
15-
#[derive(Debug, Clone, clap::ValueEnum)]
15+
#[derive(Debug, Clone, PartialEq, Eq, Hash, clap::ValueEnum)]
1616
pub enum InjuryStatusFilter {
1717
/// Players who are active/healthy
1818
Active,
@@ -52,7 +52,7 @@ impl fmt::Display for InjuryStatusFilter {
5252
///
5353
/// Allows filtering players by whether they are currently rostered
5454
/// on a fantasy team in your league.
55-
#[derive(Debug, Clone, clap::ValueEnum)]
55+
#[derive(Debug, Clone, PartialEq, Eq, Hash, clap::ValueEnum)]
5656
pub enum RosterStatusFilter {
5757
/// Players currently rostered on any team
5858
Rostered,
@@ -74,7 +74,7 @@ impl fmt::Display for RosterStatusFilter {
7474
///
7575
/// Allows filtering players by the fantasy team they are currently on.
7676
/// Supports both team name (partial matching) and exact team ID matching.
77-
#[derive(Debug, Clone)]
77+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
7878
pub enum FantasyTeamFilter {
7979
/// Filter by team name (supports partial matching)
8080
Name(String),

src/commands/player_data.rs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -163,13 +163,7 @@ pub async fn handle_player_data(params: PlayerDataParams) -> Result<()> {
163163
);
164164

165165
// Get cached data directly from database
166-
let cached_data = db.get_cached_player_data(
167-
params.base.season,
168-
params.base.week,
169-
params.base.player_names.as_ref(),
170-
params.base.positions.as_ref(),
171-
params.projected,
172-
)?;
166+
let cached_data = db.get_cached_player_data(&params.base, params.projected)?;
173167

174168
// Convert cached data to PlayerPoints format with status info in parallel
175169
let cached_player_points: Vec<PlayerPoints> = cached_data

src/commands/projection_analysis.rs

Lines changed: 12 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -104,44 +104,18 @@ pub async fn handle_projection_analysis(params: ProjectionAnalysisParams) -> Res
104104
}
105105
};
106106

107-
// Check if we already have projected data for this week (without filters)
108-
let skip_api_call = !params.base.refresh
109-
&& params.base.player_names.is_none()
110-
&& params.base.positions.is_none()
111-
&& db.has_data_for_week(
112-
params.base.season,
113-
params.base.week,
114-
params.base.player_names.as_ref(),
115-
None,
116-
Some(true),
117-
)?; // Check for projected data
118-
119-
// Fetch ESPN projections for the target week
120-
let players_val = if skip_api_call {
121-
if !params.base.as_json {
122-
println!("Using cached projection data for analysis...");
123-
}
124-
// Return empty JSON array to skip processing new data but continue with cached analysis
125-
serde_json::Value::Array(vec![])
126-
} else {
127-
if !params.base.as_json {
128-
println!(
129-
"Fetching fresh ESPN projections for Week {}...",
130-
params.base.week.as_u16()
131-
);
132-
}
133-
get_player_data(PlayerDataRequest {
134-
debug: false,
135-
league_id,
136-
player_names: params.base.player_names.clone(),
137-
positions: params.base.positions.clone(),
138-
season: params.base.season,
139-
week: params.base.week,
140-
injury_status_filter: params.base.injury_status.clone(),
141-
roster_status_filter: params.base.roster_status.clone(),
142-
})
143-
.await?
144-
};
107+
// Fetch ESPN projections for the target week (get_player_data handles caching internally)
108+
let players_val = get_player_data(PlayerDataRequest {
109+
debug: false,
110+
league_id,
111+
player_names: params.base.player_names.clone(),
112+
positions: params.base.positions.clone(),
113+
season: params.base.season,
114+
week: params.base.week,
115+
injury_status_filter: params.base.injury_status.clone(),
116+
roster_status_filter: params.base.roster_status.clone(),
117+
})
118+
.await?;
145119

146120
let players: Vec<crate::espn::types::Player> = serde_json::from_value(players_val)?;
147121

src/core/cache.rs

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use std::{
2121
sync::{Arc, Mutex},
2222
};
2323

24+
use crate::cli::types::filters::{FantasyTeamFilter, InjuryStatusFilter, RosterStatusFilter};
2425
use crate::{LeagueId, PlayerId, Position, Season, Week};
2526

2627
/// Path: ~/.cache/league_settings-{season}-{league_id}.json
@@ -79,6 +80,9 @@ pub struct PlayerDataCacheKey {
7980
pub player_names: Option<Vec<String>>,
8081
pub positions: Option<Vec<Position>>,
8182
pub projected: bool,
83+
pub injury_status: Option<InjuryStatusFilter>,
84+
pub roster_status: Option<RosterStatusFilter>,
85+
pub fantasy_team_filter: Option<FantasyTeamFilter>,
8286
}
8387

8488
impl CacheKey for PlayerDataCacheKey {
@@ -104,12 +108,38 @@ impl CacheKey for PlayerDataCacheKey {
104108
})
105109
.unwrap_or_else(|| "all_pos".to_string());
106110

111+
let injury_hash = self
112+
.injury_status
113+
.as_ref()
114+
.map(|status| format!("inj_{}", status.to_string().to_lowercase()))
115+
.unwrap_or_else(|| "all_inj".to_string());
116+
117+
let roster_hash = self
118+
.roster_status
119+
.as_ref()
120+
.map(|status| format!("ros_{}", status.to_string().to_lowercase()))
121+
.unwrap_or_else(|| "all_ros".to_string());
122+
123+
let team_hash = self
124+
.fantasy_team_filter
125+
.as_ref()
126+
.map(|filter| match filter {
127+
FantasyTeamFilter::Id(id) => format!("team_id_{}", id),
128+
FantasyTeamFilter::Name(name) => {
129+
format!("team_name_{}", name.to_lowercase().replace(' ', "_"))
130+
}
131+
})
132+
.unwrap_or_else(|| "all_teams".to_string());
133+
107134
format!(
108-
"player_data_s{}_w{}_{}_{}_{}",
135+
"player_data_s{}_w{}_{}_{}_{}_{}_{}_{}",
109136
self.season.as_u16(),
110137
self.week.as_u16(),
111138
names_hash,
112139
positions_hash,
140+
injury_hash,
141+
roster_hash,
142+
team_hash,
113143
if self.projected { "proj" } else { "actual" }
114144
)
115145
}
@@ -448,6 +478,9 @@ mod tests {
448478
player_names: Some(vec!["Josh Allen".to_string()]),
449479
positions: None,
450480
projected: false,
481+
injury_status: None,
482+
roster_status: None,
483+
fantasy_team_filter: None,
451484
};
452485

453486
let file_key = key.to_file_key();

0 commit comments

Comments
 (0)