From e32fb85006254246c5b634f4e8cc4a2eb0da7dcd Mon Sep 17 00:00:00 2001 From: Felipe Coutinho Date: Wed, 1 Apr 2026 14:14:23 +0000 Subject: [PATCH] =?UTF-8?q?perf(cache):=20migra=C3=A7=C3=A3o=20para=20dire?= =?UTF-8?q?tiva=20`use=20cache`=20do=20Next.js?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Todas as queries cacheadas do dashboard migram de `unstable_cache` para a diretiva `use cache` com `cacheTag` e `cacheLife({ revalidate: 3 })`. Todas as páginas e o layout do dashboard passam a chamar `connection()` para garantir renderização dinâmica. O root layout envolve os filhos em ``. `next.config.ts` remove `turbopackFileSystemCacheForDev` e adota `cacheComponents: true`. Co-Authored-By: Claude Sonnet 4.6 --- next.config.ts | 4 +--- .../accounts/[accountId]/statement/page.tsx | 2 ++ src/app/(dashboard)/accounts/page.tsx | 2 ++ src/app/(dashboard)/budgets/page.tsx | 2 ++ src/app/(dashboard)/calendar/page.tsx | 2 ++ .../cards/[cardId]/invoice/page.tsx | 2 ++ src/app/(dashboard)/cards/page.tsx | 2 ++ .../categories/[categoryId]/page.tsx | 2 ++ .../(dashboard)/categories/history/page.tsx | 2 ++ src/app/(dashboard)/categories/page.tsx | 2 ++ src/app/(dashboard)/dashboard/page.tsx | 2 ++ src/app/(dashboard)/inbox/page.tsx | 2 ++ src/app/(dashboard)/insights/page.tsx | 2 ++ src/app/(dashboard)/layout.tsx | 2 ++ src/app/(dashboard)/notes/page.tsx | 2 ++ src/app/(dashboard)/payers/[payerId]/page.tsx | 2 ++ src/app/(dashboard)/payers/page.tsx | 2 ++ .../(dashboard)/reports/card-usage/page.tsx | 2 ++ .../reports/category-trends/page.tsx | 2 ++ .../reports/establishments/page.tsx | 2 ++ .../reports/installment-analysis/page.tsx | 2 ++ src/app/(dashboard)/settings/page.tsx | 16 +++++++++------- .../(dashboard)/transactions/import/page.tsx | 2 ++ src/app/(dashboard)/transactions/page.tsx | 2 ++ src/app/layout.tsx | 3 ++- src/features/dashboard/fetch-dashboard-data.ts | 18 +++++++----------- src/features/dashboard/navbar-queries.ts | 18 ++++++------------ src/features/dashboard/page-data-queries.ts | 16 ++++++---------- src/features/dashboard/preferences-queries.ts | 5 +++++ src/features/insights/actions/aggregate.ts | 16 ++++++---------- 30 files changed, 86 insertions(+), 54 deletions(-) diff --git a/next.config.ts b/next.config.ts index ca11612..d6c3206 100644 --- a/next.config.ts +++ b/next.config.ts @@ -6,9 +6,7 @@ dotenv.config(); const nextConfig: NextConfig = { output: "standalone", - experimental: { - turbopackFileSystemCacheForDev: true, - }, + cacheComponents: true, reactCompiler: true, images: { remotePatterns: [new URL("https://lh3.googleusercontent.com/**")], diff --git a/src/app/(dashboard)/accounts/[accountId]/statement/page.tsx b/src/app/(dashboard)/accounts/[accountId]/statement/page.tsx index 597b846..00e1a14 100644 --- a/src/app/(dashboard)/accounts/[accountId]/statement/page.tsx +++ b/src/app/(dashboard)/accounts/[accountId]/statement/page.tsx @@ -1,5 +1,6 @@ import { RiPencilLine } from "@remixicon/react"; import { notFound } from "next/navigation"; +import { connection } from "next/server"; import { AccountDialog } from "@/features/accounts/components/account-dialog"; import { AccountStatementCard } from "@/features/accounts/components/account-statement-card"; import type { Account } from "@/features/accounts/components/types"; @@ -42,6 +43,7 @@ const capitalize = (value: string) => value.length > 0 ? value[0]?.toUpperCase().concat(value.slice(1)) : value; export default async function Page({ params, searchParams }: PageProps) { + await connection(); const { accountId } = await params; const userId = await getUserId(); const resolvedSearchParams = searchParams ? await searchParams : undefined; diff --git a/src/app/(dashboard)/accounts/page.tsx b/src/app/(dashboard)/accounts/page.tsx index ce80001..3967a32 100644 --- a/src/app/(dashboard)/accounts/page.tsx +++ b/src/app/(dashboard)/accounts/page.tsx @@ -1,8 +1,10 @@ +import { connection } from "next/server"; import { AccountsPage } from "@/features/accounts/components/accounts-page"; import { fetchAllAccountsForUser } from "@/features/accounts/queries"; import { getUserId } from "@/shared/lib/auth/server"; export default async function Page() { + await connection(); const userId = await getUserId(); const { activeAccounts, archivedAccounts, logoOptions } = await fetchAllAccountsForUser(userId); diff --git a/src/app/(dashboard)/budgets/page.tsx b/src/app/(dashboard)/budgets/page.tsx index 85a0d4d..71ae1de 100644 --- a/src/app/(dashboard)/budgets/page.tsx +++ b/src/app/(dashboard)/budgets/page.tsx @@ -1,3 +1,4 @@ +import { connection } from "next/server"; import { BudgetsPage } from "@/features/budgets/components/budgets-page"; import { fetchBudgetsForUser } from "@/features/budgets/queries"; import MonthNavigation from "@/shared/components/month-picker/month-navigation"; @@ -23,6 +24,7 @@ const capitalize = (value: string) => value.length === 0 ? value : value[0]?.toUpperCase() + value.slice(1); export default async function Page({ searchParams }: PageProps) { + await connection(); const userId = await getUserId(); const resolvedSearchParams = searchParams ? await searchParams : undefined; const periodoParam = getSingleParam(resolvedSearchParams, "periodo"); diff --git a/src/app/(dashboard)/calendar/page.tsx b/src/app/(dashboard)/calendar/page.tsx index 42f5901..bdf5803 100644 --- a/src/app/(dashboard)/calendar/page.tsx +++ b/src/app/(dashboard)/calendar/page.tsx @@ -1,3 +1,4 @@ +import { connection } from "next/server"; import { MonthlyCalendar } from "@/features/calendar/components/monthly-calendar"; import { fetchCalendarData } from "@/features/calendar/queries"; import { @@ -16,6 +17,7 @@ type PageProps = { }; export default async function Page({ searchParams }: PageProps) { + await connection(); const userId = await getUserId(); const resolvedParams = searchParams ? await searchParams : undefined; diff --git a/src/app/(dashboard)/cards/[cardId]/invoice/page.tsx b/src/app/(dashboard)/cards/[cardId]/invoice/page.tsx index 0687991..fe75995 100644 --- a/src/app/(dashboard)/cards/[cardId]/invoice/page.tsx +++ b/src/app/(dashboard)/cards/[cardId]/invoice/page.tsx @@ -1,5 +1,6 @@ import { RiPencilLine } from "@remixicon/react"; import { notFound } from "next/navigation"; +import { connection } from "next/server"; import type { FinancialAccount } from "@/db/schema"; import { CardDialog } from "@/features/cards/components/card-dialog"; import type { Card } from "@/features/cards/components/types"; @@ -39,6 +40,7 @@ type PageProps = { }; export default async function Page({ params, searchParams }: PageProps) { + await connection(); const { cardId } = await params; const userId = await getUserId(); const resolvedSearchParams = searchParams ? await searchParams : undefined; diff --git a/src/app/(dashboard)/cards/page.tsx b/src/app/(dashboard)/cards/page.tsx index a945f15..17dad2e 100644 --- a/src/app/(dashboard)/cards/page.tsx +++ b/src/app/(dashboard)/cards/page.tsx @@ -1,8 +1,10 @@ +import { connection } from "next/server"; import { CardsPage } from "@/features/cards/components/cards-page"; import { fetchAllCardsForUser } from "@/features/cards/queries"; import { getUserId } from "@/shared/lib/auth/server"; export default async function Page() { + await connection(); const userId = await getUserId(); const { activeCards, archivedCards, accounts, logoOptions } = await fetchAllCardsForUser(userId); diff --git a/src/app/(dashboard)/categories/[categoryId]/page.tsx b/src/app/(dashboard)/categories/[categoryId]/page.tsx index fa263c2..aaf3b62 100644 --- a/src/app/(dashboard)/categories/[categoryId]/page.tsx +++ b/src/app/(dashboard)/categories/[categoryId]/page.tsx @@ -1,4 +1,5 @@ import { notFound } from "next/navigation"; +import { connection } from "next/server"; import { CategoryDetailHeader } from "@/features/categories/components/category-detail-header"; import { fetchCategoryDetails } from "@/features/dashboard/categories/category-details-queries"; import { fetchUserPreferences } from "@/features/settings/queries"; @@ -32,6 +33,7 @@ const getSingleParam = ( }; export default async function Page({ params, searchParams }: PageProps) { + await connection(); const { categoryId } = await params; const userId = await getUserId(); const resolvedSearchParams = searchParams ? await searchParams : undefined; diff --git a/src/app/(dashboard)/categories/history/page.tsx b/src/app/(dashboard)/categories/history/page.tsx index a1ba805..2d165f0 100644 --- a/src/app/(dashboard)/categories/history/page.tsx +++ b/src/app/(dashboard)/categories/history/page.tsx @@ -1,9 +1,11 @@ +import { connection } from "next/server"; import { fetchCategoryHistory } from "@/features/dashboard/categories/category-history-queries"; import { CategoryHistoryWidget } from "@/features/dashboard/components/category-history-widget"; import { getUser } from "@/shared/lib/auth/server"; import { getCurrentPeriod } from "@/shared/utils/period"; export default async function HistoricoCategoriasPage() { + await connection(); const user = await getUser(); const currentPeriod = getCurrentPeriod(); diff --git a/src/app/(dashboard)/categories/page.tsx b/src/app/(dashboard)/categories/page.tsx index f4fd745..6024e60 100644 --- a/src/app/(dashboard)/categories/page.tsx +++ b/src/app/(dashboard)/categories/page.tsx @@ -1,8 +1,10 @@ +import { connection } from "next/server"; import { CategoriesPage } from "@/features/categories/components/categories-page"; import { fetchCategoriesForUser } from "@/features/categories/queries"; import { getUserId } from "@/shared/lib/auth/server"; export default async function Page() { + await connection(); const userId = await getUserId(); const categories = await fetchCategoriesForUser(userId); diff --git a/src/app/(dashboard)/dashboard/page.tsx b/src/app/(dashboard)/dashboard/page.tsx index 21c0f7d..1ba8bfd 100644 --- a/src/app/(dashboard)/dashboard/page.tsx +++ b/src/app/(dashboard)/dashboard/page.tsx @@ -1,3 +1,4 @@ +import { connection } from "next/server"; import { DashboardGridEditable } from "@/features/dashboard/components/dashboard-grid-editable"; import { DashboardMetricsCards } from "@/features/dashboard/components/dashboard-metrics-cards"; import { DashboardWelcome } from "@/features/dashboard/components/dashboard-welcome"; @@ -14,6 +15,7 @@ type PageProps = { }; export default async function Page({ searchParams }: PageProps) { + await connection(); const user = await getUser(); const resolvedSearchParams = searchParams ? await searchParams : undefined; const periodoParam = getSingleParam(resolvedSearchParams, "periodo"); diff --git a/src/app/(dashboard)/inbox/page.tsx b/src/app/(dashboard)/inbox/page.tsx index 644c721..eab5884 100644 --- a/src/app/(dashboard)/inbox/page.tsx +++ b/src/app/(dashboard)/inbox/page.tsx @@ -1,3 +1,4 @@ +import { connection } from "next/server"; import { InboxPage } from "@/features/inbox/components/inbox-page"; import { type ResolvedInboxSearchParams, @@ -31,6 +32,7 @@ const EMPTY_DIALOG_DATA = { }; export default async function Page({ searchParams }: PageProps) { + await connection(); const userId = await getUserId(); const resolvedSearchParams = searchParams ? await searchParams : undefined; const activeStatus = resolveInboxStatus(resolvedSearchParams); diff --git a/src/app/(dashboard)/insights/page.tsx b/src/app/(dashboard)/insights/page.tsx index f0885e5..c7e3eb6 100644 --- a/src/app/(dashboard)/insights/page.tsx +++ b/src/app/(dashboard)/insights/page.tsx @@ -1,3 +1,4 @@ +import { connection } from "next/server"; import { InsightsPage } from "@/features/insights/components/insights-page"; import MonthNavigation from "@/shared/components/month-picker/month-navigation"; import { parsePeriodParam } from "@/shared/utils/period"; @@ -18,6 +19,7 @@ const getSingleParam = ( }; export default async function Page({ searchParams }: PageProps) { + await connection(); const resolvedSearchParams = searchParams ? await searchParams : undefined; const periodoParam = getSingleParam(resolvedSearchParams, "periodo"); const { period: selectedPeriod } = parsePeriodParam(periodoParam); diff --git a/src/app/(dashboard)/layout.tsx b/src/app/(dashboard)/layout.tsx index ac226f3..bb13a18 100644 --- a/src/app/(dashboard)/layout.tsx +++ b/src/app/(dashboard)/layout.tsx @@ -1,3 +1,4 @@ +import { connection } from "next/server"; import { fetchDashboardNavbarData } from "@/features/dashboard/navbar-queries"; import { AppNavbar } from "@/shared/components/navigation/navbar/app-navbar"; import { PrivacyProvider } from "@/shared/components/providers/privacy-provider"; @@ -9,6 +10,7 @@ export default async function DashboardLayout({ }: Readonly<{ children: React.ReactNode; }>) { + await connection(); const session = await getUserSession(); const navbarData = await fetchDashboardNavbarData(session.user.id); diff --git a/src/app/(dashboard)/notes/page.tsx b/src/app/(dashboard)/notes/page.tsx index 6e43899..50a192a 100644 --- a/src/app/(dashboard)/notes/page.tsx +++ b/src/app/(dashboard)/notes/page.tsx @@ -1,8 +1,10 @@ +import { connection } from "next/server"; import { NotesPage } from "@/features/notes/components/notes-page"; import { fetchAllNotesForUser } from "@/features/notes/queries"; import { getUserId } from "@/shared/lib/auth/server"; export default async function Page() { + await connection(); const userId = await getUserId(); const { activeNotes, archivedNotes } = await fetchAllNotesForUser(userId); diff --git a/src/app/(dashboard)/payers/[payerId]/page.tsx b/src/app/(dashboard)/payers/[payerId]/page.tsx index 60be28b..9e3b1f6 100644 --- a/src/app/(dashboard)/payers/[payerId]/page.tsx +++ b/src/app/(dashboard)/payers/[payerId]/page.tsx @@ -4,6 +4,7 @@ import { RiWallet3Line, } from "@remixicon/react"; import { notFound } from "next/navigation"; +import { connection } from "next/server"; import { PayerCardUsageCard } from "@/features/payers/components/details/payer-card-usage-card"; import { PayerHeaderCard } from "@/features/payers/components/details/payer-header-card"; import { PayerHistoryCard } from "@/features/payers/components/details/payer-history-card"; @@ -91,6 +92,7 @@ const createEmptySlugMaps = (): SlugMaps => ({ type OptionSet = ReturnType; export default async function Page({ params, searchParams }: PageProps) { + await connection(); const { payerId } = await params; const userId = await getUserId(); const resolvedSearchParams = searchParams ? await searchParams : undefined; diff --git a/src/app/(dashboard)/payers/page.tsx b/src/app/(dashboard)/payers/page.tsx index d759fce..a6b2b5f 100644 --- a/src/app/(dashboard)/payers/page.tsx +++ b/src/app/(dashboard)/payers/page.tsx @@ -1,8 +1,10 @@ +import { connection } from "next/server"; import { PayersPage } from "@/features/payers/components/payers-page"; import { fetchPayersForUser } from "@/features/payers/queries"; import { getUserId } from "@/shared/lib/auth/server"; export default async function Page() { + await connection(); const userId = await getUserId(); const { payers, avatarOptions } = await fetchPayersForUser(userId); diff --git a/src/app/(dashboard)/reports/card-usage/page.tsx b/src/app/(dashboard)/reports/card-usage/page.tsx index 7c8ed68..993ff27 100644 --- a/src/app/(dashboard)/reports/card-usage/page.tsx +++ b/src/app/(dashboard)/reports/card-usage/page.tsx @@ -1,4 +1,5 @@ import { RiBankCard2Line } from "@remixicon/react"; +import { connection } from "next/server"; import { fetchCartoesReportData } from "@/features/reports/cards-report-queries"; import { CardCategoryBreakdown } from "@/features/reports/components/cards/card-category-breakdown"; import { CardInvoiceStatus } from "@/features/reports/components/cards/card-invoice-status"; @@ -28,6 +29,7 @@ const getSingleParam = ( export default async function RelatorioCartoesPage({ searchParams, }: PageProps) { + await connection(); const user = await getUser(); const resolvedSearchParams = searchParams ? await searchParams : undefined; const periodoParam = getSingleParam(resolvedSearchParams, "periodo"); diff --git a/src/app/(dashboard)/reports/category-trends/page.tsx b/src/app/(dashboard)/reports/category-trends/page.tsx index b68969d..f7ed25a 100644 --- a/src/app/(dashboard)/reports/category-trends/page.tsx +++ b/src/app/(dashboard)/reports/category-trends/page.tsx @@ -1,4 +1,5 @@ import { redirect } from "next/navigation"; +import { connection } from "next/server"; import type { Category } from "@/db/schema"; import { fetchCategoryChartData } from "@/features/reports/category-chart-queries"; import { fetchCategoryReport } from "@/features/reports/category-report-queries"; @@ -29,6 +30,7 @@ const getSingleParam = ( }; export default async function Page({ searchParams }: PageProps) { + await connection(); // Get authenticated user const userId = await getUserId(); diff --git a/src/app/(dashboard)/reports/establishments/page.tsx b/src/app/(dashboard)/reports/establishments/page.tsx index 8b257bc..44c44a5 100644 --- a/src/app/(dashboard)/reports/establishments/page.tsx +++ b/src/app/(dashboard)/reports/establishments/page.tsx @@ -1,3 +1,4 @@ +import { connection } from "next/server"; import { EstablishmentsList } from "@/features/reports/components/establishments/establishments-list"; import { HighlightsCards } from "@/features/reports/components/establishments/highlights-cards"; import { PeriodFilterButtons } from "@/features/reports/components/establishments/period-filter"; @@ -36,6 +37,7 @@ const validatePeriodFilter = (value: string | null): PeriodFilter => { export default async function TopEstabelecimentosPage({ searchParams, }: PageProps) { + await connection(); const user = await getUser(); const resolvedSearchParams = searchParams ? await searchParams : undefined; const periodoParam = getSingleParam(resolvedSearchParams, "periodo"); diff --git a/src/app/(dashboard)/reports/installment-analysis/page.tsx b/src/app/(dashboard)/reports/installment-analysis/page.tsx index 278505a..6f31c7e 100644 --- a/src/app/(dashboard)/reports/installment-analysis/page.tsx +++ b/src/app/(dashboard)/reports/installment-analysis/page.tsx @@ -1,8 +1,10 @@ +import { connection } from "next/server"; import { InstallmentAnalysisPage } from "@/features/dashboard/components/installment-analysis/installment-analysis-page"; import { fetchInstallmentAnalysis } from "@/features/dashboard/expenses/installment-analysis-queries"; import { getUser } from "@/shared/lib/auth/server"; export default async function Page() { + await connection(); const user = await getUser(); const data = await fetchInstallmentAnalysis(user.id); diff --git a/src/app/(dashboard)/settings/page.tsx b/src/app/(dashboard)/settings/page.tsx index 2ce3487..4e404b4 100644 --- a/src/app/(dashboard)/settings/page.tsx +++ b/src/app/(dashboard)/settings/page.tsx @@ -1,6 +1,7 @@ import { RiAndroidLine, RiArrowRightSLine } from "@remixicon/react"; import { headers } from "next/headers"; import { redirect } from "next/navigation"; +import { connection } from "next/server"; import { CompanionTab } from "@/features/settings/components/companion-tab"; import { DeleteAccountForm } from "@/features/settings/components/delete-account-form"; @@ -21,6 +22,7 @@ import { import { auth } from "@/shared/lib/auth/config"; export default async function Page() { + await connection(); const session = await auth.api.getSession({ headers: await headers(), }); @@ -65,7 +67,7 @@ export default async function Page() {
-

Preferências

+

Preferências

Personalize sua experiência no OpenMonetis ajustando as configurações de acordo com suas necessidades. @@ -90,7 +92,7 @@ export default async function Page() {

-

OpenMonetis Companion

+

OpenMonetis Companion

Android @@ -112,7 +114,7 @@ export default async function Page() {
-

Alterar nome

+

Alterar nome

Atualize como seu nome aparece no OpenMonetis. Esse nome pode ser exibido em diferentes seções do app e em comunicações. @@ -128,7 +130,7 @@ export default async function Page() {

-

Alterar senha

+

Alterar senha

Defina uma nova senha para sua conta. Guarde-a em local seguro. @@ -144,7 +146,7 @@ export default async function Page() {

-

Passkeys

+

Passkeys

Passkeys permitem login sem senha, usando biometria (Face ID, Touch ID, Windows Hello) ou chaves de segurança. @@ -160,7 +162,7 @@ export default async function Page() {

-

Alterar e-mail

+

Alterar e-mail

Atualize o e-mail associado à sua conta. Você precisará confirmar os links enviados para o novo e também para o e-mail @@ -180,7 +182,7 @@ export default async function Page() {

-

+

Ações perigosas

diff --git a/src/app/(dashboard)/transactions/import/page.tsx b/src/app/(dashboard)/transactions/import/page.tsx index 3fae5b1..b41789b 100644 --- a/src/app/(dashboard)/transactions/import/page.tsx +++ b/src/app/(dashboard)/transactions/import/page.tsx @@ -1,3 +1,4 @@ +import { connection } from "next/server"; import { ImportPage } from "@/features/transactions/components/import/import-page"; import { buildOptionSets, @@ -7,6 +8,7 @@ import { fetchTransactionFilterSources } from "@/features/transactions/queries"; import { getUserId } from "@/shared/lib/auth/server"; export default async function Page() { + await connection(); const userId = await getUserId(); const filterSources = await fetchTransactionFilterSources(userId); const sluggedFilters = buildSluggedFilters(filterSources); diff --git a/src/app/(dashboard)/transactions/page.tsx b/src/app/(dashboard)/transactions/page.tsx index f4f922b..bd89ef6 100644 --- a/src/app/(dashboard)/transactions/page.tsx +++ b/src/app/(dashboard)/transactions/page.tsx @@ -1,3 +1,4 @@ +import { connection } from "next/server"; import { fetchUserPreferences } from "@/features/settings/queries"; import { TransactionsPage } from "@/features/transactions/components/page/transactions-page"; import { @@ -27,6 +28,7 @@ type PageProps = { }; export default async function Page({ searchParams }: PageProps) { + await connection(); const userId = await getUserId(); const resolvedSearchParams = searchParams ? await searchParams : undefined; diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 813d506..679f8de 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,4 +1,5 @@ import type { Metadata } from "next"; +import { Suspense } from "react"; import { ThemeProvider } from "@/shared/components/providers/theme-provider"; import { Toaster } from "@/shared/components/ui/sonner"; import "./globals.css"; @@ -35,7 +36,7 @@ export default function RootLayout({ - {children} + {children} diff --git a/src/features/dashboard/fetch-dashboard-data.ts b/src/features/dashboard/fetch-dashboard-data.ts index b0f0ec5..48bb84c 100644 --- a/src/features/dashboard/fetch-dashboard-data.ts +++ b/src/features/dashboard/fetch-dashboard-data.ts @@ -1,4 +1,4 @@ -import { unstable_cache } from "next/cache"; +import { cacheLife, cacheTag } from "next/cache"; import { fetchDashboardAccounts } from "./accounts-queries"; import { fetchDashboardCategoryOverview } from "./category-overview-queries"; import { fetchDashboardCurrentPeriodOverview } from "./current-period-overview-queries"; @@ -51,18 +51,14 @@ async function fetchDashboardDataInternal(userId: string, period: string) { /** * Cached dashboard data fetcher. - * Uses unstable_cache with tags for revalidation on mutations. + * Uses "use cache" with tags for revalidation on mutations. * Cache is keyed by userId + period, and invalidated via user-scoped tags. */ -export function fetchDashboardData(userId: string, period: string) { - return unstable_cache( - () => fetchDashboardDataInternal(userId, period), - [`dashboard-${userId}-${period}`], - { - tags: [`dashboard-${userId}`], - revalidate: 60, - }, - )(); +export async function fetchDashboardData(userId: string, period: string) { + "use cache"; + cacheTag(`dashboard-${userId}`); + cacheLife({ revalidate: 3 }); + return fetchDashboardDataInternal(userId, period); } export type DashboardData = Awaited>; diff --git a/src/features/dashboard/navbar-queries.ts b/src/features/dashboard/navbar-queries.ts index dd914cd..0296c38 100644 --- a/src/features/dashboard/navbar-queries.ts +++ b/src/features/dashboard/navbar-queries.ts @@ -1,5 +1,5 @@ import { eq } from "drizzle-orm"; -import { unstable_cache } from "next/cache"; +import { cacheLife, cacheTag } from "next/cache"; import { payers } from "@/db/schema"; import { fetchPendingInboxCount } from "@/features/inbox/queries"; import { db } from "@/shared/lib/db"; @@ -53,15 +53,9 @@ async function fetchDashboardNavbarDataInternal( }; } -export function fetchDashboardNavbarData(userId: string) { - const currentPeriod = getBusinessDateString().slice(0, 7); - - return unstable_cache( - () => fetchDashboardNavbarDataInternal(userId), - [`dashboard-navbar-${userId}-${currentPeriod}`], - { - tags: [`dashboard-${userId}`], - revalidate: 60, - }, - )(); +export async function fetchDashboardNavbarData(userId: string) { + "use cache"; + cacheTag(`dashboard-${userId}`); + cacheLife({ revalidate: 3 }); + return fetchDashboardNavbarDataInternal(userId); } diff --git a/src/features/dashboard/page-data-queries.ts b/src/features/dashboard/page-data-queries.ts index 883db8e..c82a205 100644 --- a/src/features/dashboard/page-data-queries.ts +++ b/src/features/dashboard/page-data-queries.ts @@ -1,4 +1,4 @@ -import { unstable_cache } from "next/cache"; +import { cacheLife, cacheTag } from "next/cache"; import { fetchDashboardData } from "@/features/dashboard/fetch-dashboard-data"; import { fetchUserDashboardPreferences } from "@/features/dashboard/preferences-queries"; import { @@ -52,15 +52,11 @@ async function fetchDashboardQuickActionOptionsInternal( }; } -export function fetchDashboardQuickActionOptions(userId: string) { - return unstable_cache( - () => fetchDashboardQuickActionOptionsInternal(userId), - [`dashboard-quick-actions-${userId}`], - { - tags: [`dashboard-${userId}`], - revalidate: 60, - }, - )(); +export async function fetchDashboardQuickActionOptions(userId: string) { + "use cache"; + cacheTag(`dashboard-${userId}`); + cacheLife({ revalidate: 3 }); + return fetchDashboardQuickActionOptionsInternal(userId); } export async function fetchDashboardPageData(userId: string, period: string) { diff --git a/src/features/dashboard/preferences-queries.ts b/src/features/dashboard/preferences-queries.ts index 0c0b550..2c8ae84 100644 --- a/src/features/dashboard/preferences-queries.ts +++ b/src/features/dashboard/preferences-queries.ts @@ -1,4 +1,5 @@ import { eq } from "drizzle-orm"; +import { cacheLife, cacheTag } from "next/cache"; import type { WidgetPreferences } from "@/features/dashboard/widgets/actions"; import { db, schema } from "@/shared/lib/db"; @@ -9,6 +10,10 @@ export interface UserDashboardPreferences { export async function fetchUserDashboardPreferences( userId: string, ): Promise { + "use cache"; + cacheTag(`dashboard-${userId}`); + cacheLife({ revalidate: 3 }); + const result = await db .select({ dashboardWidgets: schema.userPreferences.dashboardWidgets, diff --git a/src/features/insights/actions/aggregate.ts b/src/features/insights/actions/aggregate.ts index 1282e9e..195fe60 100644 --- a/src/features/insights/actions/aggregate.ts +++ b/src/features/insights/actions/aggregate.ts @@ -1,6 +1,6 @@ import { getDay } from "date-fns"; import { and, eq, inArray, isNull, ne, or, sql } from "drizzle-orm"; -import { unstable_cache } from "next/cache"; +import { cacheLife, cacheTag } from "next/cache"; import { budgets, cards, @@ -481,13 +481,9 @@ async function aggregateMonthDataInternal(userId: string, period: string) { }; } -export function aggregateMonthData(userId: string, period: string) { - return unstable_cache( - () => aggregateMonthDataInternal(userId, period), - [`insights-aggregate-${userId}-${period}`], - { - tags: [`dashboard-${userId}`], - revalidate: 60, - }, - )(); +export async function aggregateMonthData(userId: string, period: string) { + "use cache"; + cacheTag(`dashboard-${userId}`); + cacheLife({ revalidate: 3 }); + return aggregateMonthDataInternal(userId, period); }