Spaces:
Paused
Paused
Download server/utils/streamUtils.ts from Nymbo/MiniSearch: direct link, hf CLI and curl.
- Browser
- Download file 2.35 kB
-
https://huggingface.co/spaces/Nymbo/MiniSearch/resolve/main/server/utils/streamUtils.ts
- Command line
-
hf download hf://spaces/Nymbo/MiniSearch/server/utils/streamUtils.ts
-
curl -L -o streamUtils.ts https://huggingface.co/spaces/Nymbo/MiniSearch/resolve/main/server/utils/streamUtils.ts
2.35 kB
| import type { ServerResponse } from "node:http"; | |
| /** | |
| * Reads at most `maxBytes` of a fetch response body. A hostile or merely huge | |
| * upstream must not be able to pin the server's memory, and callers that only | |
| * need the head of a document (page text, thumbnails) gain nothing from the | |
| * tail anyway. | |
| */ | |
| export async function readCappedBytes( | |
| response: Response, | |
| maxBytes: number, | |
| ): Promise<{ bytes: Uint8Array; truncated: boolean }> { | |
| const reader = response.body?.getReader(); | |
| if (!reader) return { bytes: new Uint8Array(), truncated: false }; | |
| const chunks: Uint8Array[] = []; | |
| let bytesRead = 0; | |
| let reachedEnd = false; | |
| while (bytesRead < maxBytes) { | |
| const { done, value } = await reader.read(); | |
| if (done) { | |
| reachedEnd = true; | |
| break; | |
| } | |
| const remaining = maxBytes - bytesRead; | |
| const chunk = | |
| value.byteLength > remaining ? value.subarray(0, remaining) : value; | |
| bytesRead += chunk.byteLength; | |
| chunks.push(chunk); | |
| if (chunk.byteLength < value.byteLength) break; | |
| } | |
| await reader.cancel().catch(() => {}); | |
| const bytes = new Uint8Array(bytesRead); | |
| let offset = 0; | |
| for (const chunk of chunks) { | |
| bytes.set(chunk, offset); | |
| offset += chunk.byteLength; | |
| } | |
| return { bytes, truncated: !reachedEnd }; | |
| } | |
| /** Calculates the backoff delay for a retry attempt, with jitter. */ | |
| export function calculateBackoffTime( | |
| attempt: number, | |
| baseDelayMs = 100, | |
| maxDelayMs = 5000, | |
| ): number { | |
| const delay = Math.min(baseDelayMs * 2 ** (attempt - 1), maxDelayMs); | |
| return delay * (0.7 + Math.random() * 0.3); | |
| } | |
| export function isResponseWritable(response: ServerResponse): boolean { | |
| return !response.writableEnded && !response.destroyed; | |
| } | |
| export function safeWriteResponse( | |
| response: ServerResponse, | |
| data: string, | |
| ): boolean { | |
| if (!isResponseWritable(response)) return false; | |
| try { | |
| return response.write(data); | |
| } catch (error) { | |
| console.error("Failed to write to response:", error); | |
| return false; | |
| } | |
| } | |
| export function safeEndResponse(response: ServerResponse, data?: string): void { | |
| if (response.writableEnded || response.destroyed) return; | |
| try { | |
| if (data) { | |
| response.end(data); | |
| } else { | |
| response.end(); | |
| } | |
| } catch (error) { | |
| console.error("Failed to end response:", error); | |
| response.destroy(); | |
| } | |
| } | |