klg-asutk-app/docs/CACHING_AND_PAGINATION.md
Yuriy 0150aba4f5 Consolidation: KLG ASUTK + PAPA integration
- 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>
2026-02-08 17:18:31 +03:00

9.0 KiB
Raw Permalink Blame History

Кэширование и пагинация

Реализованные функции

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 - конфигурация SWR
  • hooks/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, // Попытки при ошибке
};

Производительность

Преимущества кэширования

  1. Снижение нагрузки на БД - запросы к Redis быстрее чем к PostgreSQL
  2. Быстрая отдача данных - кэшированные данные возвращаются мгновенно
  3. Масштабируемость - Redis может обслуживать множество запросов параллельно

Преимущества SWR

  1. Автоматическое обновление - данные обновляются в фоне
  2. Дедупликация - одинаковые запросы выполняются один раз
  3. Кэширование на клиенте - данные доступны сразу при повторном визите
  4. Оптимистичные обновления - можно обновлять UI до получения ответа

Преимущества пагинации

  1. Меньше данных - загружаются только нужные записи
  2. Быстрее загрузка - меньше данных = быстрее ответ
  3. Меньше памяти - не нужно хранить все данные в памяти

Мониторинг

Метрики кэша

  • Hit rate (процент попаданий в кэш)
  • Miss rate (процент промахов)
  • TTL для разных типов данных
  • Размер кэша

Метрики SWR

  • Количество запросов
  • Время ответа
  • Количество ошибок
  • Частота обновлений

Рекомендации

  1. Используйте server-side пагинацию для больших списков (>100 записей)
  2. Настройте TTL в зависимости от частоты обновления данных
  3. Инвалидируйте кэш при изменении данных
  4. Мониторьте hit rate кэша для оптимизации TTL
  5. Используйте SWR для данных, которые часто обновляются
  6. Применяйте ISR для статических страниц с редкими обновлениями