-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add update_stats functionality to ingest API
- Introduced a new `update_stats` function to aggregate and update site statistics in the database, including monthly, yearly, and all-time views and unique visitors. - Updated the ingest API to support the new `update_stats` task, enhancing the task management structure. - Added unit tests for the `update_stats` function to ensure correct behavior and error handling.
- Loading branch information
Showing
3 changed files
with
144 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import { turso_client } from '$lib/turso'; | ||
import { describe, expect, it, vi } from 'vitest'; | ||
import { update_stats } from './update-stats'; | ||
|
||
vi.mock('$lib/turso', () => ({ | ||
turso_client: vi.fn(() => ({ | ||
execute: vi.fn().mockResolvedValue({ success: true }), | ||
close: vi.fn(), | ||
})), | ||
})); | ||
|
||
describe('update_stats', () => { | ||
it('should successfully update stats', async () => { | ||
const result = await update_stats(); | ||
expect(result).toEqual({ | ||
success: true, | ||
message: 'Stats updated successfully', | ||
}); | ||
}); | ||
|
||
it('should handle database errors', async () => { | ||
const mock_client = { | ||
execute: vi.fn().mockRejectedValue(new Error('Database error')), | ||
close: vi.fn(), | ||
}; | ||
vi.mocked(turso_client).mockReturnValue(mock_client); | ||
|
||
await expect(update_stats()).rejects.toThrow( | ||
'Failed to update stats: Database error', | ||
); | ||
expect(mock_client.close).toHaveBeenCalled(); | ||
}); | ||
|
||
it('should always close the database connection', async () => { | ||
const mock_client = { | ||
execute: vi.fn().mockRejectedValue(new Error('Test error')), | ||
close: vi.fn(), | ||
}; | ||
vi.mocked(turso_client).mockReturnValue(mock_client); | ||
|
||
try { | ||
await update_stats(); | ||
} catch { | ||
// Ignore error | ||
} | ||
expect(mock_client.close).toHaveBeenCalled(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import { turso_client } from '$lib/turso'; | ||
|
||
const update_monthly_stats = ` | ||
INSERT OR REPLACE INTO analytics_monthly (pathname, year_month, views, unique_visitors) | ||
SELECT | ||
pathname, | ||
strftime('%Y-%m', timestamp) as year_month, | ||
SUM(views) as views, | ||
SUM(uniques) as unique_visitors | ||
FROM analytics_pages | ||
WHERE pathname LIKE '/posts/%' | ||
GROUP BY pathname, year_month; | ||
`; | ||
|
||
const update_yearly_stats = ` | ||
INSERT OR REPLACE INTO analytics_yearly (pathname, year, views, unique_visitors) | ||
SELECT | ||
pathname, | ||
strftime('%Y', timestamp) as year, | ||
SUM(views) as views, | ||
SUM(uniques) as unique_visitors | ||
FROM analytics_pages | ||
WHERE pathname LIKE '/posts/%' | ||
GROUP BY pathname, year; | ||
`; | ||
|
||
const update_all_time_stats = ` | ||
INSERT OR REPLACE INTO analytics_all_time (pathname, views, unique_visitors) | ||
SELECT | ||
pathname, | ||
SUM(views) as views, | ||
SUM(uniques) as unique_visitors | ||
FROM analytics_pages | ||
WHERE pathname LIKE '/posts/%' | ||
GROUP BY pathname; | ||
`; | ||
|
||
export const update_stats = async () => { | ||
const client = turso_client(); | ||
try { | ||
await client.execute(update_monthly_stats); | ||
await client.execute(update_yearly_stats); | ||
await client.execute(update_all_time_stats); | ||
return { success: true, message: 'Stats updated successfully' }; | ||
} catch (error) { | ||
console.error('Error updating stats:', error); | ||
throw new Error( | ||
`Failed to update stats: ${error instanceof Error ? error.message : 'Unknown error'}`, | ||
); | ||
} finally { | ||
client.close(); | ||
} | ||
}; |