release: v1.32.0 — hardening and scalability (#580)

* release: prepare v1.32.0

* test: stabilize water capture re-entry
This commit is contained in:
Marc-André Bombeck authored and GitHub committed 2026-07-22 04:14:15 +02:00
1 parent b01822be48
commit 62eb431d66
372 files changed
+25178 -8561

No files matched your search

@@ -20,6 +20,9 @@ vi.mock("@/lib/db", () => ({
import { prisma } from "@/lib/db";
import {
DOCUMENT_DEFAULT_MAX_FILE_BYTES,
acquireDocumentUploadSlot,
DOCUMENT_UPLOAD_GLOBAL_CONCURRENCY,
DOCUMENT_UPLOAD_PER_USER_CONCURRENCY,
DOCUMENT_DEFAULT_QUOTA_BYTES,
DOCUMENT_HARD_MAX_FILE_BYTES,
detectDocumentType,
@@ -276,6 +279,36 @@ describe("servingClassFor", () => {
});
});
describe("document upload concurrency slots", () => {
it("bounds concurrent uploads per user and releases exactly once", () => {
const releases = Array.from(
{ length: DOCUMENT_UPLOAD_PER_USER_CONCURRENCY },
() => acquireDocumentUploadSlot("slot-user"),
);
expect(releases.every(Boolean)).toBe(true);
expect(acquireDocumentUploadSlot("slot-user")).toBeNull();
releases[0]!();
releases[0]!();
const replacement = acquireDocumentUploadSlot("slot-user");
expect(replacement).not.toBeNull();
replacement!();
for (const release of releases.slice(1)) release!();
});
it("bounds total concurrent uploads across different users", () => {
const releases = Array.from(
{ length: DOCUMENT_UPLOAD_GLOBAL_CONCURRENCY },
(_, index) => acquireDocumentUploadSlot(`global-slot-user-${index}`),
);
expect(releases.every(Boolean)).toBe(true);
expect(acquireDocumentUploadSlot("global-slot-overflow")).toBeNull();
for (const release of releases) release!();
});
});
describe("resolveDocumentLimits", () => {
beforeEach(() => {
vi.clearAllMocks();
+37
View File
@@ -47,6 +47,43 @@ export const DOCUMENT_HARD_MAX_FILE_BYTES = 104_857_600;
/** Default per-user quota: 1 GiB. */
export const DOCUMENT_DEFAULT_QUOTA_BYTES = 1_073_741_824;
/** In-memory admission bounds for body accumulation in one server process. */
export const DOCUMENT_UPLOAD_GLOBAL_CONCURRENCY = 4;
export const DOCUMENT_UPLOAD_PER_USER_CONCURRENCY = 2;
let activeDocumentUploads = 0;
const activeDocumentUploadsByUser = new Map<string, number>();
/**
* Reserve one process-local document upload slot. The returned release is
* idempotent so a defensive second cleanup cannot corrupt the counters.
*/
export function acquireDocumentUploadSlot(userId: string): (() => void) | null {
const activeForUser = activeDocumentUploadsByUser.get(userId) ?? 0;
if (
activeDocumentUploads >= DOCUMENT_UPLOAD_GLOBAL_CONCURRENCY ||
activeForUser >= DOCUMENT_UPLOAD_PER_USER_CONCURRENCY
) {
return null;
}
activeDocumentUploads += 1;
activeDocumentUploadsByUser.set(userId, activeForUser + 1);
let released = false;
return () => {
if (released) return;
released = true;
activeDocumentUploads -= 1;
const remainingForUser = (activeDocumentUploadsByUser.get(userId) ?? 1) - 1;
if (remainingForUser === 0) {
activeDocumentUploadsByUser.delete(userId);
} else {
activeDocumentUploadsByUser.set(userId, remainingForUser);
}
};
}
export interface DocumentLimits {
/** Per-file upload cap in bytes (admin-tunable, clamped to the ceiling). */
maxFileBytes: number;