| import { replicationCache } from "@midday/cache/replication-cache"; |
| import { teamPermissionsCache } from "@midday/cache/team-permissions-cache"; |
| import type { DatabaseWithPrimary } from "@midday/db/client"; |
| import { getUserTeamId } from "@midday/db/queries"; |
| import { logger } from "@midday/logger"; |
| import type { MiddlewareHandler } from "hono"; |
|
|
| |
| |
| |
| |
| |
| export const withPrimaryReadAfterWrite: MiddlewareHandler = async (c, next) => { |
| |
| const session = c.get("session"); |
| const db = c.get("db"); |
|
|
| |
| const method = c.req.method; |
| const operationType = ["POST", "PUT", "PATCH", "DELETE"].includes(method) |
| ? "mutation" |
| : "query"; |
|
|
| let teamId: string | null = null; |
|
|
| |
| if (session?.oauth) { |
| teamId = session.teamId || null; |
| } |
| |
| else if (session?.user?.id) { |
| const cacheKey = `user:${session.user.id}:team`; |
| teamId = (await teamPermissionsCache.get(cacheKey)) || null; |
|
|
| if (!teamId && session.user.id) { |
| try { |
| |
| const userTeamId = await getUserTeamId(db, session.user.id); |
|
|
| if (userTeamId) { |
| teamId = userTeamId; |
| await teamPermissionsCache.set(cacheKey, userTeamId); |
| } |
| } catch (error) { |
| logger.warn("Failed to fetch user team", { |
| userId: session.user.id, |
| error: error instanceof Error ? error.message : "Unknown error", |
| }); |
| } |
| } |
| } |
|
|
| let finalDb = db; |
|
|
| if (teamId) { |
| |
| if (operationType === "mutation") { |
| await replicationCache.set(teamId); |
|
|
| |
| const dbWithPrimary = db as DatabaseWithPrimary; |
| if (dbWithPrimary.usePrimaryOnly) { |
| finalDb = dbWithPrimary.usePrimaryOnly(); |
| } |
| |
| } |
| |
| else { |
| const timestamp = await replicationCache.get(teamId); |
| const now = Date.now(); |
|
|
| |
| if (timestamp && now < timestamp) { |
| |
| const dbWithPrimary = db as DatabaseWithPrimary; |
| if (dbWithPrimary.usePrimaryOnly) { |
| finalDb = dbWithPrimary.usePrimaryOnly(); |
| } |
| } |
| } |
| } |
|
|
| |
| c.set("db", finalDb); |
| c.set("session", session); |
| c.set("teamId", teamId); |
|
|
| await next(); |
| }; |
|
|