diff --git a/front/src/app/embalse-cuenca/[cuenca]/page.tsx b/front/src/app/embalse-cuenca/[cuenca]/page.tsx index 42c6c08..196d177 100644 --- a/front/src/app/embalse-cuenca/[cuenca]/page.tsx +++ b/front/src/app/embalse-cuenca/[cuenca]/page.tsx @@ -1,7 +1,9 @@ import { EmbalsesCuencaPod, getEmbalsesPorCuenca } from "@/pods/embalse-cuenca"; import { cuencas } from "@/core/constants"; -import { Metadata } from "next"; import { mapLookupListFromApiToViewModel } from "@/common/mappers"; +import { Metadata } from "next"; + +export const revalidate = 300; // ISR: regenerar cada 5 minutos interface Props { params: Promise<{ cuenca: string }>; diff --git a/front/src/app/embalse-cuenca/page.tsx b/front/src/app/embalse-cuenca/page.tsx index ea7ff72..b433971 100644 --- a/front/src/app/embalse-cuenca/page.tsx +++ b/front/src/app/embalse-cuenca/page.tsx @@ -3,6 +3,8 @@ import { EmbalseCuencaListPod } from "@/pods/embalse-cuenca-list"; import { getRiverBasins } from "@/pods/embalse-cuenca-list/embalse-cuenca-list.repository"; import { Metadata } from "next"; +export const revalidate = 300; // ISR: regenerar cada 5 minutos + export const metadata: Metadata = { title: "Embalses por cuencas", }; diff --git a/front/src/app/embalse-provincia/[provincia]/page.tsx b/front/src/app/embalse-provincia/[provincia]/page.tsx index 88f8f30..5bd2be1 100644 --- a/front/src/app/embalse-provincia/[provincia]/page.tsx +++ b/front/src/app/embalse-provincia/[provincia]/page.tsx @@ -1,9 +1,13 @@ import { PROVINCIAS } from "@/core/constants"; -import { EmbalseProvinciaPod } from "@/pods/embalse-provincia"; +import { + EmbalseProvinciaPod, + getEmbalsesByProvince, +} from "@/pods/embalse-provincia"; import { mapEmbalseListFromApiToLookup } from "@/pods/embalse-provincia/embalse-provincia.mapper"; -import { getEmbalsesByProvince } from "@/pods/embalse-provincia/embalse-provincia.repository"; import { Metadata } from "next"; +export const revalidate = 300; // ISR: regenerar cada 5 minutos + interface Props { params: Promise<{ provincia: string }>; } diff --git a/front/src/app/embalse/[embalse]/page.tsx b/front/src/app/embalse/[embalse]/page.tsx index a502fe4..361c200 100644 --- a/front/src/app/embalse/[embalse]/page.tsx +++ b/front/src/app/embalse/[embalse]/page.tsx @@ -1,14 +1,17 @@ import type { Metadata } from "next"; import { notFound } from "next/navigation"; -import { EmbalsePod, getReservoirInfoBySlugCached } from "@/pods/embalse"; -import { getEmbalseBySlug } from "@/pods/embalse/embalse.repository"; +import { + EmbalsePod, + getReservoirInfoBySlugCached, + getEmbalseBySlugCached, +} from "@/pods/embalse"; import { mapEmbalseToReservoirData } from "@/pods/embalse/embalse.mapper"; export const revalidate = 300; // ISR: regenerar cada 5 minutos export async function generateMetadata({ params }: Props): Promise { const { embalse } = await params; - const embalseSlug = await getEmbalseBySlug(embalse); + const embalseSlug = await getEmbalseBySlugCached(embalse); return { title: embalseSlug.nombre, @@ -25,7 +28,7 @@ export default async function EmbalseDetallePage({ params }: Props) { Si no se encuentra el embalse, llamamos a notFound() que muestra la pagina 404 de Next.js */ const { embalse } = await params; - const embalseDoc = await getEmbalseBySlug(embalse); + const embalseDoc = await getEmbalseBySlugCached(embalse); const embalseInfo = await getReservoirInfoBySlugCached(embalse); if (!embalseDoc) { diff --git a/front/src/pods/embalse-cuenca-list/embalse-cuenca-list.repository.ts b/front/src/pods/embalse-cuenca-list/embalse-cuenca-list.repository.ts index 335ef57..f2568dc 100644 --- a/front/src/pods/embalse-cuenca-list/embalse-cuenca-list.repository.ts +++ b/front/src/pods/embalse-cuenca-list/embalse-cuenca-list.repository.ts @@ -2,19 +2,33 @@ import { LookupApi } from "@/common/models"; import { getDb } from "@/lib/mongodb"; +import { unstable_cache } from "next/cache"; -export async function getRiverBasins(): Promise { - try { +const getCachedRiverBasins = unstable_cache( + async (): Promise => { const db = await getDb(); - return await db + const result = await db .collection("cuencas") .find({}, { projection: { _id: 1, nombre: 1 } }) .toArray(); + if (result.length === 0) { + throw new Error("Empty cuencas - skip cache"); + } + return result; + }, + ["cuencas-collection"], + { revalidate: 300 }, +); + +export async function getRiverBasins(): Promise { + try { + return await getCachedRiverBasins(); } catch (error) { console.warn( - "getEmbalsesByRiverBasin: MongoDB not available (build time?), returning empty array.", + "getRiverBasins: MongoDB not available or empty, returning empty array.", "Error:", error instanceof Error ? error.message : error, ); + return []; } } diff --git a/front/src/pods/embalse-cuenca/api/embalse-cuenca.api.ts b/front/src/pods/embalse-cuenca/api/embalse-cuenca.api.ts new file mode 100644 index 0000000..896aea7 --- /dev/null +++ b/front/src/pods/embalse-cuenca/api/embalse-cuenca.api.ts @@ -0,0 +1,30 @@ +import "server-only"; +import { unstable_cache } from "next/cache"; +import type { LookupApi } from "@/common/models"; +import { getEmbalsesPorCuenca as getEmbalsesPorCuencaFromDb } from "../embalse-cuenca.repository"; + +/** + * Cached version of getEmbalsesPorCuenca. + * Revalidates every 5 minutes. + */ +const getCachedEmbalsesPorCuenca = unstable_cache( + async (nombre: string): Promise => { + const embalses = await getEmbalsesPorCuencaFromDb(nombre); + if (!embalses || embalses.length === 0) { + throw new Error("Empty embalses por cuenca - skip cache"); + } + return embalses; + }, + ["embalses-por-cuenca"], + { revalidate: 300 }, +); + +export const getEmbalsesPorCuenca = async ( + nombre: string, +): Promise => { + try { + return await getCachedEmbalsesPorCuenca(nombre); + } catch { + return []; + } +}; diff --git a/front/src/pods/embalse-cuenca/embalse-cuenca.repository.ts b/front/src/pods/embalse-cuenca/embalse-cuenca.repository.ts index cf2c531..8434ef0 100644 --- a/front/src/pods/embalse-cuenca/embalse-cuenca.repository.ts +++ b/front/src/pods/embalse-cuenca/embalse-cuenca.repository.ts @@ -19,5 +19,6 @@ export const getEmbalsesPorCuenca = async ( "Error:", error instanceof Error ? error.message : error, ); + return []; } }; diff --git a/front/src/pods/embalse-cuenca/index.ts b/front/src/pods/embalse-cuenca/index.ts index 25806f0..42e3043 100644 --- a/front/src/pods/embalse-cuenca/index.ts +++ b/front/src/pods/embalse-cuenca/index.ts @@ -1,2 +1,2 @@ export * from "./embalse-cuenca.pod"; -export * from "./embalse-cuenca.repository"; +export * from "./api/embalse-cuenca.api"; diff --git a/front/src/pods/embalse-provincia/api/embalse-provincia.api.ts b/front/src/pods/embalse-provincia/api/embalse-provincia.api.ts new file mode 100644 index 0000000..39ff25a --- /dev/null +++ b/front/src/pods/embalse-provincia/api/embalse-provincia.api.ts @@ -0,0 +1,30 @@ +import "server-only"; +import { unstable_cache } from "next/cache"; +import type { EmbalseApi } from "../embalse-provincia.api-model"; +import { getEmbalsesByProvince as getEmbalsesByProvinceFromDb } from "../embalse-provincia.repository"; + +/** + * Cached version of getEmbalsesByProvince. + * Revalidates every 5 minutes. + */ +const getCachedEmbalsesByProvince = unstable_cache( + async (provincia: string): Promise => { + const embalses = await getEmbalsesByProvinceFromDb(provincia); + if (!embalses || embalses.length === 0) { + throw new Error("Empty embalses por provincia - skip cache"); + } + return embalses; + }, + ["embalses-por-provincia"], + { revalidate: 300 }, +); + +export const getEmbalsesByProvince = async ( + provincia: string, +): Promise => { + try { + return await getCachedEmbalsesByProvince(provincia); + } catch { + return []; + } +}; diff --git a/front/src/pods/embalse-provincia/embalse-provincia.repository.ts b/front/src/pods/embalse-provincia/embalse-provincia.repository.ts index 64d8304..8ffbd45 100644 --- a/front/src/pods/embalse-provincia/embalse-provincia.repository.ts +++ b/front/src/pods/embalse-provincia/embalse-provincia.repository.ts @@ -22,7 +22,6 @@ export async function getEmbalsesByProvince( ) .toArray(); - console.log(docs); return docs.map((doc) => ({ _id: doc.slug ?? String(doc._id), name: doc.nombre ?? "", diff --git a/front/src/pods/embalse-provincia/index.ts b/front/src/pods/embalse-provincia/index.ts index 18a8abd..b87a708 100644 --- a/front/src/pods/embalse-provincia/index.ts +++ b/front/src/pods/embalse-provincia/index.ts @@ -1 +1,2 @@ export * from "./embalse-provincia.pod"; +export * from "./api/embalse-provincia.api"; diff --git a/front/src/pods/embalse/api/embalse.api.ts b/front/src/pods/embalse/api/embalse.api.ts index 39fbfbe..4b9e539 100644 --- a/front/src/pods/embalse/api/embalse.api.ts +++ b/front/src/pods/embalse/api/embalse.api.ts @@ -2,6 +2,8 @@ import "server-only"; import { unstable_cache } from "next/cache"; import type { ReservoirInfo } from "./embalse.api-model"; import { contentIslandClient } from "@/lib"; +import { getEmbalseBySlug } from "../embalse.repository"; +import type { Embalse } from "db-model"; /** * Cached version of getReservoirInfoBySlug. @@ -24,11 +26,23 @@ export const getReservoirInfoBySlugCached = unstable_cache( } catch (error) { console.warn( `Warning reservoir info for slug not available: ${slug}`, - error + error, ); return null; } }, ["reservoir-by-slug"], - { revalidate: 60 } + { revalidate: 60 }, +); + +/** + * Cached version of getEmbalseBySlug. + * Revalidates every 60 seconds. + */ +export const getEmbalseBySlugCached = unstable_cache( + async (slug: string): Promise => { + return getEmbalseBySlug(slug); + }, + ["embalse-by-slug"], + { revalidate: 60 }, );