mirror of
https://github.com/jlengrand/Maestro.git
synced 2026-03-10 08:31:19 +00:00
## CHANGES
- Added IPC/API to fetch earliest recorded stats timestamp instantly 🧭 - Stats DB now computes earliest date across key tracking tables accurately 🧠 - Settings modal displays “since YYYY-MM-DD” alongside stats database size 📅
This commit is contained in:
@@ -244,6 +244,15 @@ export function registerStatsHandlers(deps: StatsHandlerDependencies): void {
|
||||
})
|
||||
);
|
||||
|
||||
// Get earliest stat timestamp (for UI display)
|
||||
ipcMain.handle(
|
||||
'stats:get-earliest-timestamp',
|
||||
withIpcErrorLogging(handlerOpts('getEarliestTimestamp'), async () => {
|
||||
const db = getStatsDB();
|
||||
return db.getEarliestStatTimestamp();
|
||||
})
|
||||
);
|
||||
|
||||
// Record session creation (launched)
|
||||
ipcMain.handle(
|
||||
'stats:record-session-created',
|
||||
|
||||
@@ -178,6 +178,10 @@ export function createStatsApi() {
|
||||
// Get database size in bytes
|
||||
getDatabaseSize: (): Promise<number> => ipcRenderer.invoke('stats:get-database-size'),
|
||||
|
||||
// Get earliest stat timestamp (null if no entries)
|
||||
getEarliestTimestamp: (): Promise<number | null> =>
|
||||
ipcRenderer.invoke('stats:get-earliest-timestamp'),
|
||||
|
||||
// Record session creation (for lifecycle tracking)
|
||||
recordSessionCreated: (event: SessionCreatedEvent): Promise<string | null> =>
|
||||
ipcRenderer.invoke('stats:record-session-created', event),
|
||||
|
||||
@@ -666,6 +666,40 @@ export class StatsDB {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the timestamp of the earliest stat entry in the database.
|
||||
* Checks query_events, auto_run_sessions, and session_lifecycle tables.
|
||||
* Returns null if no entries exist.
|
||||
*/
|
||||
getEarliestStatTimestamp(): number | null {
|
||||
if (!this.db) throw new Error('Database not initialized');
|
||||
|
||||
// Query minimum start_time from each table and find the overall minimum
|
||||
const queryEventsMin = this.db
|
||||
.prepare('SELECT MIN(start_time) as min_time FROM query_events')
|
||||
.get() as { min_time: number | null } | undefined;
|
||||
|
||||
const autoRunMin = this.db
|
||||
.prepare('SELECT MIN(start_time) as min_time FROM auto_run_sessions')
|
||||
.get() as { min_time: number | null } | undefined;
|
||||
|
||||
const lifecycleMin = this.db
|
||||
.prepare('SELECT MIN(created_at) as min_time FROM session_lifecycle')
|
||||
.get() as { min_time: number | null } | undefined;
|
||||
|
||||
const timestamps = [
|
||||
queryEventsMin?.min_time,
|
||||
autoRunMin?.min_time,
|
||||
lifecycleMin?.min_time,
|
||||
].filter((t): t is number => t !== null && t !== undefined);
|
||||
|
||||
if (timestamps.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Math.min(...timestamps);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run VACUUM on the database to reclaim unused space and optimize structure.
|
||||
*
|
||||
|
||||
@@ -339,6 +339,7 @@ export const SettingsModal = memo(function SettingsModal(props: SettingsModalPro
|
||||
|
||||
// Stats data management state
|
||||
const [statsDbSize, setStatsDbSize] = useState<number | null>(null);
|
||||
const [statsEarliestDate, setStatsEarliestDate] = useState<string | null>(null);
|
||||
const [statsClearing, setStatsClearing] = useState(false);
|
||||
const [statsClearResult, setStatsClearResult] = useState<{
|
||||
success: boolean;
|
||||
@@ -379,7 +380,7 @@ export const SettingsModal = memo(function SettingsModal(props: SettingsModalPro
|
||||
setSyncError('Failed to load storage settings');
|
||||
});
|
||||
|
||||
// Load stats database size
|
||||
// Load stats database size and earliest timestamp
|
||||
window.maestro.stats
|
||||
.getDatabaseSize()
|
||||
.then((size) => {
|
||||
@@ -389,6 +390,21 @@ export const SettingsModal = memo(function SettingsModal(props: SettingsModalPro
|
||||
console.error('Failed to load stats database size:', err);
|
||||
});
|
||||
|
||||
window.maestro.stats
|
||||
.getEarliestTimestamp()
|
||||
.then((timestamp) => {
|
||||
if (timestamp) {
|
||||
const date = new Date(timestamp);
|
||||
const formatted = date.toISOString().split('T')[0]; // YYYY-MM-DD
|
||||
setStatsEarliestDate(formatted);
|
||||
} else {
|
||||
setStatsEarliestDate(null);
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('Failed to load earliest stats timestamp:', err);
|
||||
});
|
||||
|
||||
// Reset stats clear state
|
||||
setStatsClearResult(null);
|
||||
}
|
||||
@@ -1894,6 +1910,9 @@ export const SettingsModal = memo(function SettingsModal(props: SettingsModalPro
|
||||
{statsDbSize !== null
|
||||
? (statsDbSize / 1024 / 1024).toFixed(2) + ' MB'
|
||||
: 'Loading...'}
|
||||
{statsEarliestDate && (
|
||||
<span style={{ color: theme.colors.textDim }}> (since {statsEarliestDate})</span>
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
|
||||
2
src/renderer/global.d.ts
vendored
2
src/renderer/global.d.ts
vendored
@@ -2211,6 +2211,8 @@ interface MaestroAPI {
|
||||
}>;
|
||||
// Get database size in bytes
|
||||
getDatabaseSize: () => Promise<number>;
|
||||
// Get earliest stat timestamp (null if no entries exist)
|
||||
getEarliestTimestamp: () => Promise<number | null>;
|
||||
// Record session creation (launched)
|
||||
recordSessionCreated: (event: {
|
||||
sessionId: string;
|
||||
|
||||
Reference in New Issue
Block a user