Compare commits

...

2 Commits

Author SHA1 Message Date
d9e50a4235 chore: bump version to 1.20.1
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 1m13s
2026-03-21 13:13:39 +01:00
5f6eb5a5cb perf: add selective fetch caching for stable API endpoints
Make apiFetch support Next.js revalidate option instead of
hardcoding cache: no-store on every request. Stable endpoints
(libraries, settings, stats, series statuses) now use time-based
revalidation while dynamic data (books, search, jobs) stays uncached.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-21 13:13:28 +01:00
4 changed files with 18 additions and 16 deletions

8
Cargo.lock generated
View File

@@ -64,7 +64,7 @@ checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c"
[[package]]
name = "api"
version = "1.20.0"
version = "1.20.1"
dependencies = [
"anyhow",
"argon2",
@@ -1232,7 +1232,7 @@ dependencies = [
[[package]]
name = "indexer"
version = "1.20.0"
version = "1.20.1"
dependencies = [
"anyhow",
"axum",
@@ -1771,7 +1771,7 @@ dependencies = [
[[package]]
name = "parsers"
version = "1.20.0"
version = "1.20.1"
dependencies = [
"anyhow",
"flate2",
@@ -2906,7 +2906,7 @@ dependencies = [
[[package]]
name = "stripstream-core"
version = "1.20.0"
version = "1.20.1"
dependencies = [
"anyhow",
"serde",

View File

@@ -9,7 +9,7 @@ resolver = "2"
[workspace.package]
edition = "2021"
version = "1.20.0"
version = "1.20.1"
license = "MIT"
[workspace.dependencies]

View File

@@ -141,7 +141,7 @@ export function config() {
export async function apiFetch<T>(
path: string,
init?: RequestInit,
init?: RequestInit & { next?: { revalidate?: number; tags?: string[] } },
): Promise<T> {
const { baseUrl, token } = config();
const headers = new Headers(init?.headers || {});
@@ -150,10 +150,12 @@ export async function apiFetch<T>(
headers.set("Content-Type", "application/json");
}
const { next: nextOptions, ...restInit } = init ?? {};
const res = await fetch(`${baseUrl}${path}`, {
...init,
...restInit,
headers,
cache: "no-store",
...(nextOptions ? { next: nextOptions } : { cache: "no-store" as const }),
});
if (!res.ok) {
@@ -168,7 +170,7 @@ export async function apiFetch<T>(
}
export async function fetchLibraries() {
return apiFetch<LibraryDto[]>("/libraries");
return apiFetch<LibraryDto[]>("/libraries", { next: { revalidate: 30 } });
}
export async function createLibrary(name: string, rootPath: string) {
@@ -356,7 +358,7 @@ export async function fetchAllSeries(
}
export async function fetchSeriesStatuses(): Promise<string[]> {
return apiFetch<string[]>("/series/statuses");
return apiFetch<string[]>("/series/statuses", { next: { revalidate: 300 } });
}
export async function searchBooks(
@@ -421,7 +423,7 @@ export type ThumbnailStats = {
};
export async function getSettings() {
return apiFetch<Settings>("/settings");
return apiFetch<Settings>("/settings", { next: { revalidate: 60 } });
}
export async function updateSetting(key: string, value: unknown) {
@@ -432,7 +434,7 @@ export async function updateSetting(key: string, value: unknown) {
}
export async function getCacheStats() {
return apiFetch<CacheStats>("/settings/cache/stats");
return apiFetch<CacheStats>("/settings/cache/stats", { next: { revalidate: 30 } });
}
export async function clearCache() {
@@ -442,7 +444,7 @@ export async function clearCache() {
}
export async function getThumbnailStats() {
return apiFetch<ThumbnailStats>("/settings/thumbnail/stats");
return apiFetch<ThumbnailStats>("/settings/thumbnail/stats", { next: { revalidate: 30 } });
}
// Status mappings
@@ -453,7 +455,7 @@ export type StatusMappingDto = {
};
export async function fetchStatusMappings(): Promise<StatusMappingDto[]> {
return apiFetch<StatusMappingDto[]>("/settings/status-mappings");
return apiFetch<StatusMappingDto[]>("/settings/status-mappings", { next: { revalidate: 60 } });
}
export async function upsertStatusMapping(provider_status: string, mapped_status: string): Promise<StatusMappingDto> {
@@ -558,7 +560,7 @@ export type StatsResponse = {
};
export async function fetchStats() {
return apiFetch<StatsResponse>("/stats");
return apiFetch<StatsResponse>("/stats", { next: { revalidate: 30 } });
}
// ---------------------------------------------------------------------------

View File

@@ -1,6 +1,6 @@
{
"name": "stripstream-backoffice",
"version": "1.20.0",
"version": "1.20.1",
"private": true,
"scripts": {
"dev": "next dev -p 7082",