@gscdump/cloudflare 0.19.3 → 0.19.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.mjs +23 -2
  2. package/package.json +3 -3
package/dist/index.mjs CHANGED
@@ -22,6 +22,25 @@ function resolveSvc(env) {
22
22
  if (!svc) throw new Error("DUCKDB_SVC service binding is not configured");
23
23
  return svc;
24
24
  }
25
+ const DUCKDB_RPC_TIMEOUT_MS = 22e3;
26
+ var DuckDBServiceTimeoutError = class extends Error {
27
+ name = "DuckDBServiceTimeoutError";
28
+ constructor(timeoutMs) {
29
+ super(`DUCKDB_SVC.runSQL exceeded ${timeoutMs}ms deadline`);
30
+ }
31
+ };
32
+ function withDuckDBDeadline(op, timeoutMs, signal) {
33
+ if (signal?.aborted) return Promise.reject(signal.reason ?? new DOMException("Aborted", "AbortError"));
34
+ return new Promise((resolve, reject) => {
35
+ const timer = setTimeout(() => reject(new DuckDBServiceTimeoutError(timeoutMs)), timeoutMs);
36
+ const onAbort = () => reject(signal.reason ?? new DOMException("Aborted", "AbortError"));
37
+ signal?.addEventListener("abort", onAbort, { once: true });
38
+ op.then(resolve, reject).finally(() => {
39
+ clearTimeout(timer);
40
+ signal?.removeEventListener("abort", onAbort);
41
+ });
42
+ });
43
+ }
25
44
  function createDucklingsCodec(_env) {
26
45
  return createHyparquetCodec();
27
46
  }
@@ -77,6 +96,8 @@ function createDucklingsExecutor(env) {
77
96
  }));
78
97
  const merged = [];
79
98
  for (const rows of perFile) merged.push(...rows);
99
+ const mergedBytes = estimateRowsBytes(merged);
100
+ if (mergedBytes > 28 * 1024 * 1024) throw new Error(`createDucklingsExecutor: placeholder {{${placeholder}}} decoded to ~${mergedBytes} bytes (${merged.length} rows), exceeding the 28MiB service-binding RPC budget. The rollup builder must window this query (chunk partitions) instead of scanning all files at once.`);
80
101
  const tmp = tmpTableName(placeholder);
81
102
  tempNames[placeholder] = tmp;
82
103
  tables[tmp] = {
@@ -90,10 +111,10 @@ function createDucklingsExecutor(env) {
90
111
  if (!tmp) throw new Error(`createDucklingsExecutor: SQL references {{${placeholder}}} but no fileKeys entry provided`);
91
112
  return tmp;
92
113
  }), params);
93
- const result = await svc.runSQL({
114
+ const result = await withDuckDBDeadline(svc.runSQL({
94
115
  sql: finalSql,
95
116
  tables
96
- });
117
+ }), DUCKDB_RPC_TIMEOUT_MS, signal);
97
118
  return {
98
119
  rows: result.rows.map(coerceRow),
99
120
  sql: result.sql
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@gscdump/cloudflare",
3
3
  "type": "module",
4
- "version": "0.19.3",
4
+ "version": "0.19.6",
5
5
  "description": "Cloudflare-Workers-flavored helpers for the gscdump analytics stack: AnalyticsEnv binding contract, R2 SigV4 presigner, size-hint HMAC, DuckDB Workers shims, engine factory.",
6
6
  "author": {
7
7
  "name": "Harlan Wilton",
@@ -40,8 +40,8 @@
40
40
  },
41
41
  "dependencies": {
42
42
  "aws4fetch": "^1.0.20",
43
- "@gscdump/engine": "0.19.3",
44
- "@gscdump/engine-sqlite": "0.19.3"
43
+ "@gscdump/engine": "0.19.6",
44
+ "@gscdump/engine-sqlite": "0.19.6"
45
45
  },
46
46
  "devDependencies": {
47
47
  "@cloudflare/workers-types": "^4.20260519.1",