UNPKG

reduct-js

Version:

ReductStore Client SDK for Javascript/NodeJS/Typescript

76 lines (75 loc) 2.67 kB
const require_APIError = require("../APIError.js"); const require_Record = require("../Record.js"); const require_Common = require("./Common.js"); //#region src/batch/BatchV1.ts async function* fetchAndParseBatchV1(bucket, entry, id, continueQuery, poolInterval, head, httpClient) { while (true) try { for await (const record of readBatchedRecords(bucket, entry, head, id, httpClient)) { yield record; if (record.last) return; } } catch (e) { if (e instanceof require_APIError.APIError && e.status === 204) { if (continueQuery) { await new Promise((resolve) => setTimeout(resolve, poolInterval * 1e3)); continue; } return; } throw e; } } async function* readBatchedRecords(bucket, entry, head, id, httpClient) { const url = `/b/${bucket}/${entry}/batch?q=${id}`; const resp = head ? await httpClient.head(url) : await httpClient.get(url); if (resp.status === 204) throw new require_APIError.APIError(resp.headers.get("x-reduct-error") ?? "No content", 204); const { headers, data: body } = resp; const { createStream } = require_Common.createBatchStreamReader(head, body); const timeHeaders = [...headers.keys()].filter((k) => k.startsWith("x-reduct-time-")).sort((a, b) => { const tsA = BigInt(a.slice(14)); const tsB = BigInt(b.slice(14)); return tsA < tsB ? -1 : tsA > tsB ? 1 : 0; }); const total = timeHeaders.length; let index = 0; for (const h of timeHeaders) { const tsStr = h.slice(14); const value = headers.get(h); if (!value) throw new ErrorEvent(`Invalid header ${h} with value ${value}`); const { size, contentType, labels } = parseCsvRow(value); const byteLen = Number(size); index += 1; const isLastInBatch = index === total; const isLastInQuery = headers.get("x-reduct-last") === "true" && isLastInBatch; const stream = await createStream(byteLen, isLastInBatch); yield new require_Record.ReadableRecord(entry, BigInt(tsStr), BigInt(byteLen), isLastInQuery, head, stream, labels, contentType); } } function parseCsvRow(row) { const items = []; let escaped = ""; for (const item of row.split(",")) { if (item.startsWith("\"") && !escaped) escaped = item.substring(1); if (escaped) if (item.endsWith("\"")) { escaped = escaped.slice(0, -1); items.push(escaped); escaped = ""; } else escaped += item; else items.push(item); } const size = BigInt(items[0]); const contentType = items[1]; const labels = {}; for (const item of items.slice(2)) { if (!item.includes("=")) continue; const [key, value] = item.split("=", 2); labels[key] = value; } return { size, contentType, labels }; } //#endregion exports.fetchAndParseBatchV1 = fetchAndParseBatchV1;