diff --git a/.jules/bolt.md b/.jules/bolt.md new file mode 100644 index 0000000..e97cc6b --- /dev/null +++ b/.jules/bolt.md @@ -0,0 +1,3 @@ +## 2024-05-24 - [Avoid React cache key fragmentation] +**Learning:** When avoiding redundant database queries for service methods wrapped in Reacts cache() (e.g., getWorkspaceExperienceBySlug), do not add optional pre-fetched objects to the function signature, as Reacts cache keys off all arguments and this will fragment the cache. Instead, bypass the cached data-fetching method and directly call the internal synchronous compiler (e.g., compileWorkspaceExperience) from the application layer when the data is already available. +**Action:** Replace `getWorkspaceExperienceBySlug(organization.slug)` calls with `compileWorkspaceExperience({slug: organization.slug, organization})` when `organization` is already loaded. diff --git a/lib/application/auth/tenant-access.ts b/lib/application/auth/tenant-access.ts index 09f0d27..06eac25 100644 --- a/lib/application/auth/tenant-access.ts +++ b/lib/application/auth/tenant-access.ts @@ -12,6 +12,7 @@ import { } from "@/lib/application/auth/tenant-routing"; import { selectMembershipOrganization } from "@/lib/application/auth/tenant-access-selection"; import { getWorkspaceExperienceBySlug } from "@/lib/application/workspace/workspace-service"; +import { compileWorkspaceExperience } from "@/lib/platform/workspace/compiler"; import { OrganizationMemberRepository } from "@/lib/infrastructure/supabase/organization-member-repository"; import { OrganizationRepository } from "@/lib/infrastructure/supabase/organization-repository"; import { resolveWorkspaceTemplateForEmailDomain } from "@/lib/platform/workspace/registry"; @@ -110,7 +111,11 @@ export async function resolveTenantAccess( }); if (organization) { - const workspace = await getWorkspaceExperienceBySlug(organization.slug); + const fullOrganization = organizationsById.get(organization.id); + const workspace = fullOrganization + ? compileWorkspaceExperience({ slug: fullOrganization.slug, organization: fullOrganization }) + : await getWorkspaceExperienceBySlug(organization.slug); + return existingWorkspaceAccess({ slug: organization.slug, name: organization.name, @@ -124,7 +129,7 @@ export async function resolveTenantAccess( if (emailDomain) { const workspaceOrganization = await organizations.findFirstByWorkspaceEmailDomain(emailDomain); if (workspaceOrganization && (!requestedSlug || workspaceOrganization.slug === requestedSlug)) { - const workspace = await getWorkspaceExperienceBySlug(workspaceOrganization.slug); + const workspace = compileWorkspaceExperience({ slug: workspaceOrganization.slug, organization: workspaceOrganization }); return existingWorkspaceAccess({ slug: workspaceOrganization.slug, name: workspaceOrganization.name, @@ -143,7 +148,7 @@ export async function resolveTenantAccess( if (guessed.slug) { const existingOrganization = await organizations.findBySlug(guessed.slug).catch(() => null); if (existingOrganization) { - const workspace = await getWorkspaceExperienceBySlug(existingOrganization.slug); + const workspace = compileWorkspaceExperience({ slug: existingOrganization.slug, organization: existingOrganization }); return existingWorkspaceAccess({ slug: existingOrganization.slug, name: existingOrganization.name, diff --git a/lib/application/runtime/geocode-accounts-service.ts b/lib/application/runtime/geocode-accounts-service.ts index 8c98d13..fd8bea8 100644 --- a/lib/application/runtime/geocode-accounts-service.ts +++ b/lib/application/runtime/geocode-accounts-service.ts @@ -5,7 +5,7 @@ import { hasUsableWorkspaceAddress, resolveSuppressedGeocodingAddress, } from "@/lib/application/runtime/geocoding-policy"; -import { getWorkspaceExperienceBySlug } from "@/lib/application/workspace/workspace-service"; +import { compileWorkspaceExperience } from "@/lib/platform/workspace/compiler"; import { geocodeAccountCandidate, resolveGeocodingPlan, type GeocodeCandidate } from "@/lib/infrastructure/adapters/geocoding/geocoding"; import { getSupabaseAdminClient } from "@/lib/supabase/admin"; @@ -49,7 +49,7 @@ export async function geocodeMissingRuntimeAccounts(input: { organizationSlug: s organizationId: organization.id, organizationSlug: organization.slug, }); - const workspace = await getWorkspaceExperienceBySlug(organization.slug); + const workspace = compileWorkspaceExperience({ slug: organization.slug, organization }); const geocodingConfig = workspace.workspace.geocoding ?? null; const limit = readLimit(input.limit, plan.maxPerSync, plan.maxPerSync); const supabase = getSupabaseAdminClient() as any;