feat(cache): add stale get caching for report filters and summaries

This commit is contained in:
2026-04-30 16:13:35 +03:30
parent 0e8d43f1ea
commit a5a7a01da0
8 changed files with 356 additions and 131 deletions

View File

@@ -1,4 +1,5 @@
import { authFetch } from "./client";
import { authFetch } from "./client";
import { cachedGetJson, invalidateApiCache } from "./cache";
export interface Workspace {
id: string;
@@ -52,13 +53,10 @@ const toQueryString = (params?: Record<string, QueryValue>) => {
export const fetchWorkspaces = async (params?: Record<string, QueryValue>): Promise<PaginatedResponse<Workspace>> => {
const query = toQueryString(params);
const url = `/api/workspaces/${query ? `?${query}` : ''}`;
const response = await authFetch(url);
if (!response.ok) {
throw new Error("Failed to fetch workspaces");
}
const data = await response.json();
const data = await cachedGetJson<any>(url, {
ttlMs: 60 * 1000,
namespaces: ["workspaces"],
});
if (Array.isArray(data)) {
return { count: data.length, next: null, previous: null, results: data };
@@ -109,12 +107,14 @@ export const createWorkspace = async (data: {
body,
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.error || JSON.stringify(errorData) || 'Failed to create workspace');
}
return await response.json();
};
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.error || JSON.stringify(errorData) || 'Failed to create workspace');
}
const payload = await response.json();
invalidateApiCache(["workspaces", "workspace-memberships", "reports"]);
return payload;
};
export const updateWorkspace = async (
id: string,
@@ -144,30 +144,32 @@ export const updateWorkspace = async (
body,
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.error || JSON.stringify(errorData) || 'Failed to update workspace');
}
return await response.json();
};
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.error || JSON.stringify(errorData) || 'Failed to update workspace');
}
const payload = await response.json();
invalidateApiCache(["workspaces"]);
return payload;
};
export const deleteWorkspace = async (id: string): Promise<void> => {
const response = await authFetch(`/api/workspaces/${id}/`, {
method: 'DELETE',
});
if (!response.ok) {
throw new Error('Failed to delete workspace');
}
};
if (!response.ok) {
throw new Error('Failed to delete workspace');
}
invalidateApiCache(["workspaces", "workspace-memberships", "workspace-rates", "reports"]);
};
export const fetchWorkspaceMemberships = async (params?: Record<string, QueryValue>): Promise<PaginatedResponse<WorkspaceMembership>> => {
const queryParams = toQueryString(params);
const response = await authFetch(`/api/workspace-memberships/?${queryParams.toString()}`);
if (!response.ok) throw new Error("Failed to fetch workspace memberships");
const data = await response.json();
const data = await cachedGetJson<any>(`/api/workspace-memberships/?${queryParams.toString()}`, {
ttlMs: 5 * 60 * 1000,
namespaces: ["workspace-memberships"],
});
if (Array.isArray(data)) {
return { count: data.length, next: null, previous: null, results: data };
@@ -187,23 +189,26 @@ export const addWorkspaceMembership = async (data: { workspace: string; user: st
body: JSON.stringify(data),
});
if (!response.ok) {
const errorData = await response.json().catch(() => ({}));
throw new Error(errorData.error || JSON.stringify(errorData) || 'Failed to add workspace membership');
}
return await response.json();
};
if (!response.ok) {
const errorData = await response.json().catch(() => ({}));
throw new Error(errorData.error || JSON.stringify(errorData) || 'Failed to add workspace membership');
}
const payload = await response.json();
invalidateApiCache(["workspace-memberships", "reports"]);
return payload;
};
export const removeWorkspaceMembership = async (membershipId: string): Promise<void> => {
const response = await authFetch(`/api/workspace-memberships/${membershipId}/`, {
method: 'DELETE',
});
if (!response.ok) {
throw new Error('Failed to remove workspace membership');
}
};
if (!response.ok) {
throw new Error('Failed to remove workspace membership');
}
invalidateApiCache(["workspace-memberships", "reports"]);
};
export const updateWorkspaceMembership = async (membershipId: string | number, data: { role: string }) => {
const response = await authFetch(`/api/workspace-memberships/${membershipId}/`, {
@@ -211,10 +216,12 @@ export const updateWorkspaceMembership = async (membershipId: string | number, d
body: JSON.stringify(data),
});
if (!response.ok) {
const errorData = await response.json().catch(() => ({}));
throw new Error(errorData.error || JSON.stringify(errorData) || 'Failed to update membership');
}
return await response.json();
};
if (!response.ok) {
const errorData = await response.json().catch(() => ({}));
throw new Error(errorData.error || JSON.stringify(errorData) || 'Failed to update membership');
}
const payload = await response.json();
invalidateApiCache(["workspace-memberships", "reports"]);
return payload;
};