applied 10 cache
parent
5cc1dc1997
commit
7c9e18741d
|
|
@ -203,9 +203,6 @@ async def fetch_form_data(
|
|||
search: str | None = Query(None),
|
||||
processing_state: str | None = Query(None),
|
||||
is_duplicate: bool | None = Query(None),
|
||||
# Tri-valued, like is_duplicate above: omit for no filter, true for rows that
|
||||
# have the link, false for the ones missing it. Chasing the gaps is half the
|
||||
# reason these exist, so `false` has to be a real filter and not "unset".
|
||||
has_linkedin: bool | None = Query(None),
|
||||
has_resume: bool | None = Query(None),
|
||||
city: str | None = Query(None),
|
||||
|
|
@ -213,7 +210,6 @@ async def fetch_form_data(
|
|||
assigned: bool | None = Query(None),
|
||||
no_suggestions: bool | None = Query(None),
|
||||
offset: int = Query(0,ge=0),
|
||||
# Caller-chosen page size (Inbox sends 10/25/50/100). None = unpaged.
|
||||
limit: int | None = Query(None,ge=1,le=500),
|
||||
current_user: dict = Depends(_FORM_DATA_READ),
|
||||
session: AsyncSession = Depends(get_session),
|
||||
|
|
|
|||
|
|
@ -68,6 +68,43 @@ const LIST_CACHE = {
|
|||
}
|
||||
const COUNT_CACHE = { staleTime: INBOX_STALE_MS, gcTime: INBOX_GC_MS }
|
||||
|
||||
/**
|
||||
* Last 10 opened applicant details. The queue list is a light row; GET-by-id
|
||||
* is the body, suggested roles, resume text. Re-opening one of these should
|
||||
* not pay that trip again. Cap is LRU — the 11th open drops the oldest from
|
||||
* the query cache. Mutations that write THIS row still invalidate its key.
|
||||
*/
|
||||
const OPENED_DETAIL_CAP = 10
|
||||
const openedDetailLru = []
|
||||
|
||||
function detailQueryKey(kind, id) {
|
||||
return kind === 'form' ? qk.mailbox.formRow(id) : qk.mailbox.message(id)
|
||||
}
|
||||
|
||||
function rememberOpenedDetail(qc, kind, id) {
|
||||
if (!id) return
|
||||
const sig = `${kind}:${id}`
|
||||
const key = detailQueryKey(kind, id)
|
||||
const next = openedDetailLru.filter((x) => x.sig !== sig)
|
||||
next.push({ sig, kind, id, key })
|
||||
while (next.length > OPENED_DETAIL_CAP) {
|
||||
const dropped = next.shift()
|
||||
if (dropped && dropped.sig !== sig) {
|
||||
qc.removeQueries({ queryKey: dropped.key })
|
||||
}
|
||||
}
|
||||
openedDetailLru.length = 0
|
||||
openedDetailLru.push(...next)
|
||||
}
|
||||
|
||||
const DETAIL_CACHE = {
|
||||
staleTime: Infinity,
|
||||
gcTime: INBOX_GC_MS,
|
||||
refetchOnMount: false,
|
||||
refetchOnWindowFocus: false,
|
||||
refetchOnReconnect: false,
|
||||
}
|
||||
|
||||
/** Typing must not put a query key (and a skeleton) on screen per keystroke. */
|
||||
const SEARCH_DEBOUNCE_MS = 300
|
||||
|
||||
|
|
@ -1388,7 +1425,12 @@ export default function Inbox() {
|
|||
queryKey: selectedKind === 'form' ? qk.mailbox.formRow(selectedId) : qk.mailbox.message(selectedId),
|
||||
queryFn: () => (selectedKind === 'form' ? fetchFormDetail(selectedId) : fetchMessageDetail(selectedId)),
|
||||
enabled: Boolean(selectedId),
|
||||
...DETAIL_CACHE,
|
||||
})
|
||||
useEffect(() => {
|
||||
if (!selectedId || !detailQuery.isSuccess || !detailQuery.data) return
|
||||
rememberOpenedDetail(qc, selectedKind, selectedId)
|
||||
}, [qc, selectedId, selectedKind, detailQuery.isSuccess, detailQuery.data])
|
||||
// List rows paint immediately; GET-by-id is the full application. Block every
|
||||
// control in the detail pane until that fetch succeeds. The queue stays live.
|
||||
const detailLocked = Boolean(selectedId) && !detailQuery.isError && !detailQuery.isSuccess
|
||||
|
|
|
|||
Loading…
Reference in New Issue