cache middleware
This commit is contained in:
@@ -22,6 +22,7 @@ export type WorkspaceContextProps = {
|
|||||||
subscription: Subscription | null
|
subscription: Subscription | null
|
||||||
address: Address | null
|
address: Address | null
|
||||||
test_mode: boolean
|
test_mode: boolean
|
||||||
|
blocked: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
type HttpResponse = {
|
type HttpResponse = {
|
||||||
@@ -33,18 +34,23 @@ type HttpResponse = {
|
|||||||
preferred_org_id?: string
|
preferred_org_id?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export const workspaceContext = createContext<
|
export const workspaceContext = createContext<WorkspaceContextProps>()
|
||||||
WorkspaceContextProps & { blocked: boolean }
|
|
||||||
>()
|
|
||||||
|
|
||||||
export const workspaceMiddleware = async (
|
export const workspaceMiddleware = async (
|
||||||
{ params, request, context }: LoaderFunctionArgs,
|
{ params, request, context }: LoaderFunctionArgs,
|
||||||
next: () => Promise<Response>
|
next: () => Promise<Response>
|
||||||
): Promise<Response> => {
|
): Promise<Response> => {
|
||||||
const url = new URL(request.url)
|
const orgId = params.orgid
|
||||||
const user = context.get(userContext)!
|
const user = context.get(userContext)!
|
||||||
|
|
||||||
console.debug('Hit on workspace middelware')
|
const cacheKey = buildWorkspaceCacheKey(request, user.sub, orgId)
|
||||||
|
const cached = await getFromCache(cacheKey)
|
||||||
|
|
||||||
|
if (cached) {
|
||||||
|
context.set(workspaceContext, cached)
|
||||||
|
return next()
|
||||||
|
}
|
||||||
|
|
||||||
const r = await req({
|
const r = await req({
|
||||||
url: `/users/${user.sub}/orgs?limit=25`,
|
url: `/users/${user.sub}/orgs?limit=25`,
|
||||||
request,
|
request,
|
||||||
@@ -61,9 +67,10 @@ export const workspaceMiddleware = async (
|
|||||||
return { id, name, cnpj }
|
return { id, name, cnpj }
|
||||||
})
|
})
|
||||||
|
|
||||||
const activeWorkspace = workspaces.find(({ id }) => id === params.orgid)
|
const activeWorkspace = workspaces.find(({ id }) => id === orgId)
|
||||||
|
|
||||||
if (!activeWorkspace) {
|
if (!activeWorkspace) {
|
||||||
|
const url = new URL(request.url)
|
||||||
const fallback = preferred_org_id
|
const fallback = preferred_org_id
|
||||||
? (workspaces.find(({ id }) => id === preferred_org_id) ?? workspaces[0])
|
? (workspaces.find(({ id }) => id === preferred_org_id) ?? workspaces[0])
|
||||||
: workspaces[0]
|
: workspaces[0]
|
||||||
@@ -81,14 +88,55 @@ export const workspaceMiddleware = async (
|
|||||||
context
|
context
|
||||||
}).then((r) => r.json())) as any
|
}).then((r) => r.json())) as any
|
||||||
|
|
||||||
context.set(workspaceContext, {
|
const workspace = {
|
||||||
activeWorkspace,
|
activeWorkspace,
|
||||||
workspaces,
|
workspaces,
|
||||||
subscription: org?.['subscription'] || null,
|
subscription: org?.['subscription'] || null,
|
||||||
address: org?.['address'] || null,
|
address: org?.['address'] || null,
|
||||||
test_mode: 'test_mode' in org,
|
test_mode: 'test_mode' in org,
|
||||||
blocked: 'subscription_frozen' in org
|
blocked: 'subscription_frozen' in org
|
||||||
})
|
}
|
||||||
|
context.set(workspaceContext, workspace)
|
||||||
|
saveToCache(cacheKey, workspace)
|
||||||
|
|
||||||
return await next()
|
return await next()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function buildWorkspaceCacheKey(
|
||||||
|
request: Request,
|
||||||
|
userId: string,
|
||||||
|
orgId?: string
|
||||||
|
) {
|
||||||
|
const url = new URL(request.url)
|
||||||
|
url.pathname = `/__cache/workspace/${userId}/${orgId ?? 'none'}`
|
||||||
|
url.search = ''
|
||||||
|
|
||||||
|
return new Request(url.toString(), {
|
||||||
|
method: 'GET'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getFromCache(
|
||||||
|
key: Request
|
||||||
|
): Promise<WorkspaceContextProps | null> {
|
||||||
|
const cache: Cache = await caches.open('saladeaula.digital')
|
||||||
|
const cached = await cache.match(key)
|
||||||
|
|
||||||
|
if (!cached) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return cached.json()
|
||||||
|
}
|
||||||
|
|
||||||
|
async function saveToCache(key: Request, data: WorkspaceContextProps) {
|
||||||
|
const cache: Cache = await caches.open('saladeaula.digital')
|
||||||
|
const response = new Response(JSON.stringify(data), {
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Cache-Control': `public, max-age=${60 * 10}`
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
await cache.put(key, response)
|
||||||
|
}
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ export async function loader({ context, request }: Route.ActionArgs) {
|
|||||||
return {
|
return {
|
||||||
user,
|
user,
|
||||||
sidebar_state,
|
sidebar_state,
|
||||||
...workspace
|
workspace
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,7 +59,7 @@ export function shouldRevalidate({
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function Route({ loaderData }: Route.ComponentProps) {
|
export default function Route({ loaderData }: Route.ComponentProps) {
|
||||||
const { user, sidebar_state, blocked, ...props } = loaderData
|
const { user, sidebar_state, workspace } = loaderData
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (typeof window !== 'undefined' && window.rybbit) {
|
if (typeof window !== 'undefined' && window.rybbit) {
|
||||||
@@ -73,7 +73,7 @@ export default function Route({ loaderData }: Route.ComponentProps) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{blocked ? (
|
{workspace.blocked ? (
|
||||||
<AlertDialog open={true}>
|
<AlertDialog open={true}>
|
||||||
<AlertDialogContent>
|
<AlertDialogContent>
|
||||||
<AlertDialogTitle>Serviço com acesso suspenso</AlertDialogTitle>
|
<AlertDialogTitle>Serviço com acesso suspenso</AlertDialogTitle>
|
||||||
@@ -85,10 +85,10 @@ export default function Route({ loaderData }: Route.ComponentProps) {
|
|||||||
</AlertDialog>
|
</AlertDialog>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
<WorkspaceProvider {...props}>
|
<WorkspaceProvider {...workspace}>
|
||||||
<SidebarProvider
|
<SidebarProvider
|
||||||
defaultOpen={sidebar_state === 'true'}
|
defaultOpen={sidebar_state === 'true'}
|
||||||
className={cn('flex', blocked && 'pointer-events-none')}
|
className={cn('flex', workspace.blocked && 'pointer-events-none')}
|
||||||
>
|
>
|
||||||
<AppSidebar />
|
<AppSidebar />
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user