widget cache
This commit is contained in:
parent
5f240717f8
commit
4a9be647ca
@ -2,6 +2,7 @@ import { NextRequest, NextResponse } from "next/server";
|
||||
import { getServerSession } from "next-auth/next";
|
||||
import { authOptions } from "@/app/api/auth/[...nextauth]/route";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { getCachedCalendarData, cacheCalendarData } from "@/lib/redis";
|
||||
|
||||
/**
|
||||
* Handles the GET request to retrieve calendars for the authenticated user.
|
||||
@ -25,6 +26,21 @@ export async function GET(req: NextRequest) {
|
||||
}
|
||||
|
||||
try {
|
||||
// Check for force refresh parameter
|
||||
const url = new URL(req.url);
|
||||
const forceRefresh = url.searchParams.get('refresh') === 'true';
|
||||
|
||||
// Try to get data from cache if not forcing refresh
|
||||
if (!forceRefresh) {
|
||||
const cachedData = await getCachedCalendarData(session.user.id);
|
||||
if (cachedData) {
|
||||
console.log(`Using cached calendar data for user ${session.user.id}`);
|
||||
return NextResponse.json(cachedData);
|
||||
}
|
||||
}
|
||||
|
||||
// If no cache or forcing refresh, fetch from database
|
||||
console.log(`Fetching calendar data from database for user ${session.user.id}`);
|
||||
const calendars = await prisma.calendar.findMany({
|
||||
where: {
|
||||
userId: session.user.id,
|
||||
@ -42,6 +58,10 @@ export async function GET(req: NextRequest) {
|
||||
});
|
||||
|
||||
console.log("Fetched calendars with events:", calendars);
|
||||
|
||||
// Cache the results
|
||||
await cacheCalendarData(session.user.id, calendars);
|
||||
|
||||
return NextResponse.json(calendars);
|
||||
} catch (error) {
|
||||
console.error("Erreur lors de la récupération des calendriers:", error);
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { getServerSession } from "next-auth/next";
|
||||
import { authOptions } from "@/app/api/auth/[...nextauth]/route";
|
||||
import { getCachedTasksData, cacheTasksData } from "@/lib/redis";
|
||||
|
||||
interface Task {
|
||||
id: string;
|
||||
@ -94,6 +95,19 @@ export async function GET(request: NextRequest) {
|
||||
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
||||
}
|
||||
|
||||
// Check for force refresh parameter
|
||||
const url = new URL(request.url);
|
||||
const forceRefresh = url.searchParams.get('refresh') === 'true';
|
||||
|
||||
// Try to get data from cache if not forcing refresh
|
||||
if (!forceRefresh) {
|
||||
const cachedTasks = await getCachedTasksData(session.user.id);
|
||||
if (cachedTasks) {
|
||||
console.log(`Using cached tasks data for user ${session.user.id}`);
|
||||
return NextResponse.json(cachedTasks);
|
||||
}
|
||||
}
|
||||
|
||||
console.log('Fetching tasks for user:', session.user.email);
|
||||
const userId = await getLeantimeUserId(session.user.email);
|
||||
|
||||
@ -195,6 +209,10 @@ export async function GET(request: NextRequest) {
|
||||
}));
|
||||
|
||||
console.log(`Found ${tasks.length} tasks assigned to user ${userId}`);
|
||||
|
||||
// Cache the results
|
||||
await cacheTasksData(session.user.id, tasks);
|
||||
|
||||
return NextResponse.json(tasks);
|
||||
} catch (error) {
|
||||
console.error('Error in tasks route:', error);
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { NextResponse } from 'next/server';
|
||||
import { env } from '@/lib/env';
|
||||
import { getCachedNewsData, cacheNewsData } from '@/lib/redis';
|
||||
|
||||
// Helper function to clean HTML content
|
||||
function cleanHtmlContent(text: string): string {
|
||||
@ -78,8 +79,21 @@ interface NewsItem {
|
||||
url: string;
|
||||
}
|
||||
|
||||
export async function GET() {
|
||||
export async function GET(request: Request) {
|
||||
try {
|
||||
// Check if we should bypass cache
|
||||
const url = new URL(request.url);
|
||||
const forceRefresh = url.searchParams.get('refresh') === 'true';
|
||||
|
||||
// Try to get data from cache if not forcing refresh
|
||||
if (!forceRefresh) {
|
||||
const cachedNews = await getCachedNewsData();
|
||||
if (cachedNews) {
|
||||
console.log('Using cached news data');
|
||||
return NextResponse.json(cachedNews);
|
||||
}
|
||||
}
|
||||
|
||||
console.log('Fetching news from FastAPI server...');
|
||||
|
||||
const response = await fetch(`${env.NEWS_API_URL}/news?limit=12`, {
|
||||
@ -129,6 +143,9 @@ export async function GET() {
|
||||
url: article.url
|
||||
}));
|
||||
|
||||
// Cache the results
|
||||
await cacheNewsData(formattedNews);
|
||||
|
||||
return NextResponse.json(formattedNews);
|
||||
} catch (error) {
|
||||
console.error('News API error:', error);
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { getServerSession } from "next-auth";
|
||||
import { authOptions } from "@/app/api/auth/[...nextauth]/route";
|
||||
import { NextResponse } from "next/server";
|
||||
import { getCachedMessagesData, cacheMessagesData } from "@/lib/redis";
|
||||
|
||||
// Helper function to get user token using admin credentials
|
||||
async function getUserToken(baseUrl: string) {
|
||||
@ -43,6 +44,19 @@ export async function GET(request: Request) {
|
||||
return NextResponse.json({ messages: [] }, { status: 200 });
|
||||
}
|
||||
|
||||
// Check for force refresh parameter
|
||||
const url = new URL(request.url);
|
||||
const forceRefresh = url.searchParams.get('refresh') === 'true';
|
||||
|
||||
// Try to get data from cache if not forcing refresh
|
||||
if (!forceRefresh) {
|
||||
const cachedMessages = await getCachedMessagesData(session.user.id);
|
||||
if (cachedMessages) {
|
||||
console.log(`Using cached messages data for user ${session.user.id}`);
|
||||
return NextResponse.json(cachedMessages);
|
||||
}
|
||||
}
|
||||
|
||||
const baseUrl = process.env.NEXT_PUBLIC_IFRAME_PAROLE_URL?.split('/channel')[0];
|
||||
if (!baseUrl) {
|
||||
console.error('Failed to get Rocket.Chat base URL');
|
||||
@ -337,14 +351,15 @@ export async function GET(request: Request) {
|
||||
})
|
||||
.slice(0, 10);
|
||||
|
||||
return NextResponse.json({
|
||||
messages: sortedMessages,
|
||||
total: Object.keys(latestMessagePerRoom).length,
|
||||
hasMore: Object.keys(latestMessagePerRoom).length > 10
|
||||
}, { status: 200 });
|
||||
const finalResponse = { messages: sortedMessages, total: Object.keys(latestMessagePerRoom).length, hasMore: Object.keys(latestMessagePerRoom).length > 10 };
|
||||
|
||||
// Cache the results
|
||||
await cacheMessagesData(session.user.id, finalResponse);
|
||||
|
||||
return NextResponse.json(finalResponse);
|
||||
} catch (error) {
|
||||
console.error('Error in messages endpoint:', error);
|
||||
return NextResponse.json({ messages: [], total: 0, hasMore: false }, { status: 200 });
|
||||
console.error('Error fetching messages:', error);
|
||||
return NextResponse.json({ error: 'Failed to fetch messages' }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -25,7 +25,7 @@ export function Calendar() {
|
||||
const fetchEvents = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const response = await fetch('/api/calendars');
|
||||
const response = await fetch('/api/calendars?refresh=true');
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to fetch events');
|
||||
}
|
||||
|
||||
@ -38,7 +38,7 @@ export function Email() {
|
||||
setError(null);
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/courrier?folder=INBOX&page=1&perPage=5');
|
||||
const response = await fetch('/api/courrier?folder=INBOX&page=1&perPage=5' + (isRefresh ? '&refresh=true' : ''));
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to fetch emails');
|
||||
}
|
||||
|
||||
@ -92,7 +92,7 @@ export function Duties() {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
try {
|
||||
const response = await fetch('/api/leantime/tasks');
|
||||
const response = await fetch('/api/leantime/tasks?refresh=true');
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to fetch tasks');
|
||||
}
|
||||
|
||||
@ -30,7 +30,7 @@ export function News() {
|
||||
if (!isRefresh) setLoading(true);
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/news');
|
||||
const response = await fetch(isRefresh ? '/api/news?refresh=true' : '/api/news');
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to fetch news');
|
||||
}
|
||||
|
||||
@ -48,7 +48,7 @@ export function Parole() {
|
||||
setRefreshing(true);
|
||||
}
|
||||
|
||||
const response = await fetch('/api/rocket-chat/messages', {
|
||||
const response = await fetch('/api/rocket-chat/messages' + (isRefresh ? '?refresh=true' : ''), {
|
||||
cache: 'no-store',
|
||||
next: { revalidate: 0 },
|
||||
});
|
||||
|
||||
237
lib/redis.ts
237
lib/redis.ts
@ -127,7 +127,12 @@ export const KEYS = {
|
||||
EMAIL_LIST: (userId: string, accountId: string, folder: string, page: number, perPage: number) =>
|
||||
`email:list:${userId}:${accountId}:${folder}:${page}:${perPage}`,
|
||||
EMAIL_CONTENT: (userId: string, accountId: string, emailId: string) =>
|
||||
`email:content:${userId}:${accountId}:${emailId}`
|
||||
`email:content:${userId}:${accountId}:${emailId}`,
|
||||
// New widget cache keys
|
||||
CALENDAR: (userId: string) => `widget:calendar:${userId}`,
|
||||
NEWS: () => `widget:news`, // Global news cache, not user-specific
|
||||
TASKS: (userId: string) => `widget:tasks:${userId}`,
|
||||
MESSAGES: (userId: string) => `widget:messages:${userId}`
|
||||
};
|
||||
|
||||
// TTL constants in seconds
|
||||
@ -135,7 +140,12 @@ export const TTL = {
|
||||
CREDENTIALS: 60 * 60 * 24, // 24 hours
|
||||
SESSION: 60 * 60 * 4, // 4 hours (increased from 30 minutes)
|
||||
EMAIL_LIST: 60 * 5, // 5 minutes
|
||||
EMAIL_CONTENT: 60 * 15 // 15 minutes
|
||||
EMAIL_CONTENT: 60 * 15, // 15 minutes
|
||||
// New widget cache TTLs
|
||||
CALENDAR: 60 * 10, // 10 minutes for calendar events
|
||||
NEWS: 60 * 15, // 15 minutes for news
|
||||
TASKS: 60 * 10, // 10 minutes for tasks
|
||||
MESSAGES: 60 * 2 // 2 minutes for messages (more frequent updates)
|
||||
};
|
||||
|
||||
interface EmailCredentials {
|
||||
@ -494,4 +504,227 @@ export async function getCachedEmailCredentials(
|
||||
accountId: string
|
||||
): Promise<EmailCredentials | null> {
|
||||
return getEmailCredentials(userId, accountId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cache calendar data for a user
|
||||
*/
|
||||
export async function cacheCalendarData(
|
||||
userId: string,
|
||||
data: any
|
||||
): Promise<void> {
|
||||
const redis = getRedisClient();
|
||||
const key = KEYS.CALENDAR(userId);
|
||||
|
||||
try {
|
||||
await redis.set(key, JSON.stringify(data), 'EX', TTL.CALENDAR);
|
||||
console.log(`Calendar data cached for user ${userId}`);
|
||||
} catch (error) {
|
||||
console.error(`Error caching calendar data for user ${userId}:`, error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cached calendar data for a user
|
||||
*/
|
||||
export async function getCachedCalendarData(
|
||||
userId: string
|
||||
): Promise<any | null> {
|
||||
const redis = getRedisClient();
|
||||
const key = KEYS.CALENDAR(userId);
|
||||
|
||||
try {
|
||||
const cachedData = await redis.get(key);
|
||||
if (!cachedData) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return JSON.parse(cachedData);
|
||||
} catch (error) {
|
||||
console.error(`Error getting cached calendar data for user ${userId}:`, error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate calendar cache for a user
|
||||
*/
|
||||
export async function invalidateCalendarCache(
|
||||
userId: string
|
||||
): Promise<void> {
|
||||
const redis = getRedisClient();
|
||||
const key = KEYS.CALENDAR(userId);
|
||||
|
||||
try {
|
||||
await redis.del(key);
|
||||
console.log(`Calendar cache invalidated for user ${userId}`);
|
||||
} catch (error) {
|
||||
console.error(`Error invalidating calendar cache for user ${userId}:`, error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cache news data (global, not user-specific)
|
||||
*/
|
||||
export async function cacheNewsData(
|
||||
data: any
|
||||
): Promise<void> {
|
||||
const redis = getRedisClient();
|
||||
const key = KEYS.NEWS();
|
||||
|
||||
try {
|
||||
await redis.set(key, JSON.stringify(data), 'EX', TTL.NEWS);
|
||||
console.log('News data cached successfully');
|
||||
} catch (error) {
|
||||
console.error('Error caching news data:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cached news data
|
||||
*/
|
||||
export async function getCachedNewsData(): Promise<any | null> {
|
||||
const redis = getRedisClient();
|
||||
const key = KEYS.NEWS();
|
||||
|
||||
try {
|
||||
const cachedData = await redis.get(key);
|
||||
if (!cachedData) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return JSON.parse(cachedData);
|
||||
} catch (error) {
|
||||
console.error('Error getting cached news data:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate news cache
|
||||
*/
|
||||
export async function invalidateNewsCache(): Promise<void> {
|
||||
const redis = getRedisClient();
|
||||
const key = KEYS.NEWS();
|
||||
|
||||
try {
|
||||
await redis.del(key);
|
||||
console.log('News cache invalidated');
|
||||
} catch (error) {
|
||||
console.error('Error invalidating news cache:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cache tasks data for a user
|
||||
*/
|
||||
export async function cacheTasksData(
|
||||
userId: string,
|
||||
data: any
|
||||
): Promise<void> {
|
||||
const redis = getRedisClient();
|
||||
const key = KEYS.TASKS(userId);
|
||||
|
||||
try {
|
||||
await redis.set(key, JSON.stringify(data), 'EX', TTL.TASKS);
|
||||
console.log(`Tasks data cached for user ${userId}`);
|
||||
} catch (error) {
|
||||
console.error(`Error caching tasks data for user ${userId}:`, error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cached tasks data for a user
|
||||
*/
|
||||
export async function getCachedTasksData(
|
||||
userId: string
|
||||
): Promise<any | null> {
|
||||
const redis = getRedisClient();
|
||||
const key = KEYS.TASKS(userId);
|
||||
|
||||
try {
|
||||
const cachedData = await redis.get(key);
|
||||
if (!cachedData) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return JSON.parse(cachedData);
|
||||
} catch (error) {
|
||||
console.error(`Error getting cached tasks data for user ${userId}:`, error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate tasks cache for a user
|
||||
*/
|
||||
export async function invalidateTasksCache(
|
||||
userId: string
|
||||
): Promise<void> {
|
||||
const redis = getRedisClient();
|
||||
const key = KEYS.TASKS(userId);
|
||||
|
||||
try {
|
||||
await redis.del(key);
|
||||
console.log(`Tasks cache invalidated for user ${userId}`);
|
||||
} catch (error) {
|
||||
console.error(`Error invalidating tasks cache for user ${userId}:`, error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cache messages data for a user
|
||||
*/
|
||||
export async function cacheMessagesData(
|
||||
userId: string,
|
||||
data: any
|
||||
): Promise<void> {
|
||||
const redis = getRedisClient();
|
||||
const key = KEYS.MESSAGES(userId);
|
||||
|
||||
try {
|
||||
await redis.set(key, JSON.stringify(data), 'EX', TTL.MESSAGES);
|
||||
console.log(`Messages data cached for user ${userId}`);
|
||||
} catch (error) {
|
||||
console.error(`Error caching messages data for user ${userId}:`, error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cached messages data for a user
|
||||
*/
|
||||
export async function getCachedMessagesData(
|
||||
userId: string
|
||||
): Promise<any | null> {
|
||||
const redis = getRedisClient();
|
||||
const key = KEYS.MESSAGES(userId);
|
||||
|
||||
try {
|
||||
const cachedData = await redis.get(key);
|
||||
if (!cachedData) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return JSON.parse(cachedData);
|
||||
} catch (error) {
|
||||
console.error(`Error getting cached messages data for user ${userId}:`, error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate messages cache for a user
|
||||
*/
|
||||
export async function invalidateMessagesCache(
|
||||
userId: string
|
||||
): Promise<void> {
|
||||
const redis = getRedisClient();
|
||||
const key = KEYS.MESSAGES(userId);
|
||||
|
||||
try {
|
||||
await redis.del(key);
|
||||
console.log(`Messages cache invalidated for user ${userId}`);
|
||||
} catch (error) {
|
||||
console.error(`Error invalidating messages cache for user ${userId}:`, error);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user