- Unify API: lib/api.ts uses /api/v1, inbox uses /api/inbox (rewrites) - Remove localhost refs: openapi, inbox page - Add rewrites: /api/inbox|tmc -> inbox-server, /api/v1 -> FastAPI - Add stub routes: knowledge/insights, recommendations, search, log-error - Transfer from PAPA: prompts (inspection, tmc), scripts, supabase, data/tmc-requests - Fix inbox-server: ORDER BY created_at, package.json - Remove redundant app/api/inbox/files route (rewrites handle it) - knowledge/ in gitignore (large PDFs) Co-authored-by: Cursor <cursoragent@cursor.com>
9.0 KiB
9.0 KiB
Кэширование и пагинация
Реализованные функции
1. Кэширование на уровне API (Redis)
Файлы:
lib/cache/redis.ts- базовые функции кэшированияlib/api/cached-api.ts- API с интегрированным кэшированием
Функции:
- ✅
getCachedAircraft()- кэширование списка ВС (TTL: 1 час) - ✅
getCachedRisks()- кэширование рисков (TTL: 30 минут) - ✅
getCachedAudits()- кэширование аудитов (TTL: 30 минут) - ✅
getCachedOrganizations()- кэширование организаций (TTL: 2 часа) - ✅
getCachedStats()- кэширование статистики (TTL: 5 минут) - ✅
invalidateCache()- инвалидация кэша при изменении данных
Использование в API routes:
import { getCachedAircraft } from '@/lib/api/cached-api';
export async function GET() {
const aircraft = await getCachedAircraft();
return NextResponse.json(aircraft, {
headers: {
'Cache-Control': 'public, s-maxage=300, stale-while-revalidate=600',
},
});
}
TTL для разных типов данных:
- Aircraft: 1 час
- Risks: 30 минут
- Audits: 30 минут
- Organizations: 2 часа
- Documents: 1 час
- Regulations: 24 часа
- Stats: 5 минут
2. Next.js ISR (Incremental Static Regeneration)
Реализовано:
- ✅ Экспорт
revalidateв страницах для ISR - ✅ Автоматическое пересоздание страниц по расписанию
Пример:
// app/regulations/page.tsx
export const revalidate = 3600; // Пересоздавать каждый час
Преимущества:
- Статические страницы загружаются мгновенно
- Автоматическое обновление без пересборки всего сайта
- Меньше нагрузка на сервер
3. SWR для кэширования на клиенте
Файлы:
lib/swr-config.ts- конфигурация SWRhooks/useSWRData.ts- хуки для использования SWR
Хуки:
- ✅
useAircraftData()- данные о ВС с автоматическим обновлением - ✅
useRisksData()- данные о рисках - ✅
useAuditsData()- данные об аудитах - ✅
useStatsData()- статистика - ✅
useOrganizationsData()- данные об организациях
Использование:
import { useAircraftData } from '@/hooks/useSWRData';
function AircraftList() {
const { data, error, isLoading, mutate } = useAircraftData({
page: 1,
limit: 50,
paginate: true,
});
if (isLoading) return <div>Загрузка...</div>;
if (error) return <div>Ошибка: {error.message}</div>;
return (
<div>
{data?.data.map(aircraft => (
<div key={aircraft.id}>{aircraft.registrationNumber}</div>
))}
<button onClick={() => mutate()}>Обновить</button>
</div>
);
}
Настройки SWR:
revalidateOnFocus: false- не обновлять при фокусеrevalidateOnReconnect: true- обновлять при восстановлении соединенияrefreshInterval- автоматическое обновление (настраивается для каждого хука)dedupingInterval: 2000- дедупликация запросовerrorRetryCount: 3- количество попыток при ошибке
4. Пагинация
Server-side пагинация
Реализовано:
- ✅
paginatedQuery()вlib/database/query-optimizer.ts - ✅ Поддержка пагинации в API routes
- ✅ Оптимизированные запросы с LIMIT/OFFSET
Использование:
// API route
const result = await paginatedQuery(
'SELECT * FROM aircraft WHERE status = $1',
page,
limit,
['Активен'],
'created_at DESC'
);
// Возвращает:
// {
// data: [...],
// total: 1000,
// page: 1,
// pageSize: 50,
// totalPages: 20
// }
Запрос с пагинацией:
GET /api/aircraft?page=1&limit=50&paginate=true
Client-side пагинация
Компоненты:
- ✅
Pagination- компонент пагинации - ✅
usePagination- хук для пагинации данных - ✅
useInfiniteScroll- хук для бесконечной прокрутки
Использование:
import Pagination from '@/components/Pagination';
import { usePagination } from '@/hooks/usePagination';
function DataList({ data }) {
const { data: paginatedData, pagination } = usePagination(data, {
page: 1,
limit: 20,
total: data.length,
});
return (
<>
{paginatedData.map(item => <div key={item.id}>{item.name}</div>)}
<Pagination
total={pagination.total}
limit={pagination.limit}
currentPage={pagination.page}
/>
</>
);
}
Интеграция
API Routes с кэшированием
Все API routes используют кэширование через Redis:
/api/aircraft- кэширование списка ВС/api/risks- кэширование рисков с фильтрацией/api/audits- кэширование аудитов с фильтрацией/api/stats- кэширование статистики/api/organizations- кэширование организаций
Инвалидация кэша
При изменении данных необходимо инвалидировать кэш:
import { invalidateCache } from '@/lib/api/cached-api';
// После создания/обновления/удаления
await invalidateCache('aircraft', aircraftId);
Настройка
Redis
Добавьте в .env.local:
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD=
REDIS_DB=0
REDIS_ENABLED=true
TTL кэша
Настройка TTL в lib/api/cached-api.ts:
const CACHE_TTL = {
aircraft: 3600, // 1 час
risks: 1800, // 30 минут
// ...
};
SWR настройки
Настройка в lib/swr-config.ts:
export const swrConfig: SWRConfiguration = {
refreshInterval: 0, // Отключить автоматическое обновление
dedupingInterval: 2000, // Дедупликация
errorRetryCount: 3, // Попытки при ошибке
};
Производительность
Преимущества кэширования
- Снижение нагрузки на БД - запросы к Redis быстрее чем к PostgreSQL
- Быстрая отдача данных - кэшированные данные возвращаются мгновенно
- Масштабируемость - Redis может обслуживать множество запросов параллельно
Преимущества SWR
- Автоматическое обновление - данные обновляются в фоне
- Дедупликация - одинаковые запросы выполняются один раз
- Кэширование на клиенте - данные доступны сразу при повторном визите
- Оптимистичные обновления - можно обновлять UI до получения ответа
Преимущества пагинации
- Меньше данных - загружаются только нужные записи
- Быстрее загрузка - меньше данных = быстрее ответ
- Меньше памяти - не нужно хранить все данные в памяти
Мониторинг
Метрики кэша
- Hit rate (процент попаданий в кэш)
- Miss rate (процент промахов)
- TTL для разных типов данных
- Размер кэша
Метрики SWR
- Количество запросов
- Время ответа
- Количество ошибок
- Частота обновлений
Рекомендации
- Используйте server-side пагинацию для больших списков (>100 записей)
- Настройте TTL в зависимости от частоты обновления данных
- Инвалидируйте кэш при изменении данных
- Мониторьте hit rate кэша для оптимизации TTL
- Используйте SWR для данных, которые часто обновляются
- Применяйте ISR для статических страниц с редкими обновлениями