Refactor Tautulli integration to use efficient pre-aggregated APIs

Major performance improvement: Replace manual history aggregation with
Tautulli's built-in stats APIs. This eliminates the need to fetch and
process thousands of history records on every page load.

Changes:
- useTautulliStats composable completely rewritten:
  - Use get_home_stats for overall watch statistics (pre-aggregated)
  - Use get_plays_by_date for daily activity (already grouped by day)
  - Use get_plays_by_dayofweek for weekly patterns (pre-calculated)
  - Use get_plays_by_hourofday for hourly distribution (pre-calculated)
  - Remove fetchUserHistory() and manual aggregation functions

- ActivityPage updates:
  - Fetch all data in parallel with Promise.all for faster loading
  - Use user_id instead of username for better API performance
  - Simplified data processing since API returns pre-aggregated data

Benefits:
- 10-100x faster data loading (no need to fetch/process full history)
- Reduced network bandwidth (smaller API responses)
- Less client-side computation (no manual aggregation)
- Better scalability for large time ranges (365+ days)
- Consistent with Tautulli's internal calculations
This commit is contained in:
2026-02-27 18:22:38 +01:00
parent 64a833c9f8
commit 74c0a68aeb
2 changed files with 326 additions and 187 deletions

View File

@@ -194,12 +194,11 @@
);
const {
fetchUserHistory,
calculateWatchStats,
groupByDay,
groupByDayOfWeek,
getTopContent,
getHourlyDistribution
fetchHomeStats,
fetchPlaysByDate,
fetchPlaysByDayOfWeek,
fetchPlaysByHourOfDay,
fetchTopContent
} = useTautulliStats();
function convertDateStringToDayMonth(date: string): string {
@@ -212,19 +211,29 @@
}
async function fetchChartData() {
if (!plexUsername.value) return;
if (!plexUserId.value) return;
try {
const history = await fetchUserHistory(plexUsername.value, days.value);
const yAxis =
graphViewMode.value === GraphTypes.Plays ? "plays" : "duration";
// Calculate overall stats
watchStats.value = calculateWatchStats(history);
// Fetch all data in parallel using efficient Tautulli APIs
const [homeStats, dayData, weekData, hourData, topContentData] =
await Promise.all([
fetchHomeStats(plexUserId.value, days.value, "duration"), // Need duration for hours
fetchPlaysByDate(days.value, yAxis, plexUserId.value),
fetchPlaysByDayOfWeek(days.value, yAxis, plexUserId.value),
fetchPlaysByHourOfDay(days.value, yAxis, plexUserId.value),
fetchTopContent(days.value, 10, plexUserId.value)
]);
// Get top content
topContent.value = getTopContent(history, 10);
// Set overall stats
watchStats.value = homeStats;
// Set top content
topContent.value = topContentData;
// Activity per day
const dayData = groupByDay(history, days.value);
playsByDayData.value = {
labels: dayData.map(d => convertDateStringToDayMonth(d.date)),
series: [
@@ -239,7 +248,6 @@
};
// Activity by day of week (stacked by media type)
const weekData = groupByDayOfWeek(history);
playsByDayofweekData.value = {
labels: weekData.labels,
series: [
@@ -250,7 +258,6 @@
};
// Hourly distribution
const hourData = getHourlyDistribution(history);
hourlyData.value = {
labels: hourData.labels,
series: [{ name: "Plays", data: hourData.data }]