feat: add Redis caching to cospend API endpoints
All checks were successful
CI / update (push) Successful in 1m21s
All checks were successful
CI / update (push) Successful in 1m21s
Implement comprehensive caching for all cospend routes to improve performance: Cache Implementation: - Balance API: 30-minute TTL for user balances and global balances - Debts API: 15-minute TTL for debt breakdown calculations - Payments List: 10-minute TTL with pagination support - Individual Payment: 30-minute TTL for payment details Cache Invalidation: - Created invalidateCospendCaches() helper function - Invalidates user balances, debts, and payment lists on mutations - Applied to payment create, update, and delete operations - Applied to recurring payment execution (manual and cron)
This commit is contained in:
@@ -3,6 +3,7 @@ import { PaymentSplit } from '../../../../models/PaymentSplit';
|
||||
import { Payment } from '../../../../models/Payment'; // Need to import Payment for populate to work
|
||||
import { dbConnect } from '../../../../utils/db';
|
||||
import { error, json } from '@sveltejs/kit';
|
||||
import cache from '$lib/server/cache';
|
||||
|
||||
export const GET: RequestHandler = async ({ locals, url }) => {
|
||||
const auth = await locals.auth();
|
||||
@@ -14,9 +15,17 @@ export const GET: RequestHandler = async ({ locals, url }) => {
|
||||
const includeAll = url.searchParams.get('all') === 'true';
|
||||
|
||||
await dbConnect();
|
||||
|
||||
|
||||
try {
|
||||
if (includeAll) {
|
||||
// Try cache first for all balances
|
||||
const cacheKey = 'cospend:balance:all';
|
||||
const cached = await cache.get(cacheKey);
|
||||
|
||||
if (cached) {
|
||||
return json(JSON.parse(cached));
|
||||
}
|
||||
|
||||
const allSplits = await PaymentSplit.aggregate([
|
||||
{
|
||||
$group: {
|
||||
@@ -44,14 +53,27 @@ export const GET: RequestHandler = async ({ locals, url }) => {
|
||||
netBalance: 0
|
||||
};
|
||||
|
||||
return json({
|
||||
const result = {
|
||||
currentUser: currentUserBalance,
|
||||
allBalances: allSplits
|
||||
});
|
||||
};
|
||||
|
||||
// Cache for 30 minutes
|
||||
await cache.set(cacheKey, JSON.stringify(result), 1800);
|
||||
|
||||
return json(result);
|
||||
|
||||
} else {
|
||||
// Try cache first for individual user balance
|
||||
const cacheKey = `cospend:balance:${username}`;
|
||||
const cached = await cache.get(cacheKey);
|
||||
|
||||
if (cached) {
|
||||
return json(JSON.parse(cached));
|
||||
}
|
||||
|
||||
const userSplits = await PaymentSplit.find({ username }).lean();
|
||||
|
||||
|
||||
// Calculate net balance: negative = you are owed money, positive = you owe money
|
||||
const netBalance = userSplits.reduce((sum, split) => sum + split.amount, 0);
|
||||
|
||||
@@ -78,17 +100,22 @@ export const GET: RequestHandler = async ({ locals, url }) => {
|
||||
paymentId: split.paymentId._id,
|
||||
username: { $ne: username }
|
||||
}).lean();
|
||||
|
||||
|
||||
if (otherSplit) {
|
||||
split.otherUser = otherSplit.username;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return json({
|
||||
const result = {
|
||||
netBalance,
|
||||
recentSplits
|
||||
});
|
||||
};
|
||||
|
||||
// Cache for 30 minutes
|
||||
await cache.set(cacheKey, JSON.stringify(result), 1800);
|
||||
|
||||
return json(result);
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
|
||||
Reference in New Issue
Block a user