@gscdump/engine 0.31.9 → 0.32.1

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.
@@ -1,6 +1,6 @@
1
1
  import { SCHEMAS, TABLE_METADATA, dedupeByNaturalKey } from "../_chunks/schema.mjs";
2
2
  import { parquetReadObjects } from "../_chunks/libs/hyparquet.mjs";
3
- import { ByteWriter$1 as ByteWriter, parquetWriteRows } from "../_chunks/libs/hyparquet-writer.mjs";
3
+ import { ByteWriter, parquetWriteRows } from "../_chunks/libs/hyparquet-writer.mjs";
4
4
  const ROW_GROUP_SIZE = 25e3;
5
5
  function basicTypeFor(colType) {
6
6
  if (colType === "VARCHAR") return "STRING";
@@ -123,6 +123,15 @@ interface RollupEnvelope<T = unknown> {
123
123
  interface ParquetRollupPointer {
124
124
  parquetKey: string;
125
125
  rowCount: number;
126
+ /**
127
+ * MULTI-FILE rollup: when set, the rollup is the UNION of these parquet keys
128
+ * (disjoint by the grain's partition column, e.g. `date` for the resumable
129
+ * `query_canonical_daily` build). Readers MUST union all keys; `parquetKey`
130
+ * stays populated (the first part) for single-file readers. Avoids a JS
131
+ * merge/re-encode of the whole rollup — the scaling bottleneck for a
132
+ * cross-invocation resumable build.
133
+ */
134
+ parquetKeys?: string[];
126
135
  }
127
136
  declare function rollupKey(ctx: TenantCtx, id: string, builtAt: number, searchType?: SearchType): string;
128
137
  declare function rollupParquetKey(ctx: TenantCtx, id: string, builtAt: number, searchType?: SearchType): string;
package/dist/rollups.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import "./_chunks/layout.mjs";
2
2
  import { engineErrors } from "./errors.mjs";
3
- import { decodeParquetToRows, encodeRowsToParquetFlex } from "./adapters/hyparquet.mjs";
3
+ import { encodeRowsToParquetFlex } from "./adapters/hyparquet.mjs";
4
4
  import { createIndexingMetadataStore, createQueryDimStore, createSitemapStore, inspectionParquetKey, sitemapUrlsIndexPrefix } from "./_chunks/entities.mjs";
5
5
  import { MS_PER_DAY } from "gscdump";
6
6
  function rollupPrefix(ctx, searchType) {
@@ -750,7 +750,6 @@ function mapDailyRow(r) {
750
750
  sum_position: Number(r.sum_position)
751
751
  };
752
752
  }
753
- const CANONICAL_DAILY_STAGING_STEM = "query_canonical_daily__staging";
754
753
  async function rebuildCanonicalDailyResumable(opts) {
755
754
  const { engine, ctx, dataSource, searchType, builtAt, windowOffset, deadlineMs } = opts;
756
755
  const sType = searchType !== void 0 ? { searchType } : {};
@@ -800,8 +799,8 @@ async function rebuildCanonicalDailyResumable(opts) {
800
799
  }
801
800
  }
802
801
  const nextWindowOffset = i;
803
- const stagingKey = rollupParquetKey(ctx, `${CANONICAL_DAILY_STAGING_STEM}__w${windowOffset}`, builtAt, searchType);
804
- await dataSource.write(stagingKey, encodeRowsToParquetFlex(batchRows, {
802
+ const partKey = rollupParquetKey(ctx, `${CANONICAL_DAILY_PART_STEM}__w${windowOffset}`, builtAt, searchType);
803
+ await dataSource.write(partKey, encodeRowsToParquetFlex(batchRows, {
805
804
  columns: cols,
806
805
  sortKey
807
806
  }));
@@ -812,36 +811,30 @@ async function rebuildCanonicalDailyResumable(opts) {
812
811
  windowsBuilt: nextWindowOffset - windowOffset,
813
812
  rowsWritten: batchRows.length
814
813
  };
815
- const stagingPrefix = rollupParquetKey(ctx, `${CANONICAL_DAILY_STAGING_STEM}__`, builtAt, searchType).replace(/__v\d+\.parquet$/, "");
816
- const stagingKeys = (await dataSource.list(stagingPrefix.replace(/[^/]*$/, ""))).filter((k) => k.includes(`${CANONICAL_DAILY_STAGING_STEM}__w`) && k.includes(`__v${builtAt}.parquet`));
817
- const merged = [];
818
- for (const k of stagingKeys) merged.push(...await decodeParquetToRows(await dataSource.read(k), { columns: cols.map((c) => c.name) }));
819
- const parquetKey = rollupParquetKey(ctx, CANONICAL_DAILY_ROLLUP_FINAL_ID, builtAt, searchType);
820
- await dataSource.write(parquetKey, encodeRowsToParquetFlex(merged, {
821
- columns: cols,
822
- sortKey
823
- }));
814
+ const partPrefixDir = rollupParquetKey(ctx, CANONICAL_DAILY_PART_STEM, builtAt, searchType).replace(/[^/]*$/, "");
815
+ const partKeys = (await dataSource.list(partPrefixDir)).filter((k) => k.includes(`${CANONICAL_DAILY_PART_STEM}__w`) && k.endsWith(`__v${builtAt}.parquet`)).sort();
824
816
  const envelope = {
825
817
  version: 1,
826
818
  id: CANONICAL_DAILY_ROLLUP_FINAL_ID,
827
819
  builtAt,
828
820
  windowDays: queryCanonicalDailyRollup.windowDays,
829
821
  payload: {
830
- parquetKey,
831
- rowCount: merged.length
822
+ parquetKey: partKeys[0] ?? partKey,
823
+ parquetKeys: partKeys,
824
+ rowCount: 0
832
825
  }
833
826
  };
834
827
  await dataSource.write(rollupKey(ctx, CANONICAL_DAILY_ROLLUP_FINAL_ID, builtAt, searchType), new TextEncoder().encode(JSON.stringify(envelope)));
835
- await dataSource.delete(stagingKeys);
836
828
  return {
837
829
  done: true,
838
830
  nextWindowOffset,
839
831
  windowsTotal,
840
832
  windowsBuilt: nextWindowOffset - windowOffset,
841
- rowsWritten: merged.length
833
+ rowsWritten: batchRows.length
842
834
  };
843
835
  }
844
836
  const CANONICAL_DAILY_ROLLUP_FINAL_ID = "query_canonical_daily";
837
+ const CANONICAL_DAILY_PART_STEM = "query_canonical_daily__part";
845
838
  const indexingMetadataRollup = {
846
839
  id: "indexing_metadata",
847
840
  windowDays: null,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@gscdump/engine",
3
3
  "type": "module",
4
- "version": "0.31.9",
4
+ "version": "0.32.1",
5
5
  "description": "Append-only Parquet/DuckDB storage engine + planner + adapters for the gscdump pipeline. Node + edge runtimes; opt-in heavy peers.",
6
6
  "author": {
7
7
  "name": "Harlan Wilton",
@@ -181,8 +181,8 @@
181
181
  "dependencies": {
182
182
  "drizzle-orm": "1.0.0-rc.3",
183
183
  "proper-lockfile": "^4.1.2",
184
- "gscdump": "0.31.9",
185
- "@gscdump/contracts": "0.31.9"
184
+ "gscdump": "0.32.1",
185
+ "@gscdump/contracts": "0.32.1"
186
186
  },
187
187
  "devDependencies": {
188
188
  "@duckdb/duckdb-wasm": "^1.32.0",
@@ -190,7 +190,7 @@
190
190
  "aws4fetch": "^1.0.20",
191
191
  "hyparquet": "^1.26.1",
192
192
  "hyparquet-writer": "^0.16.1",
193
- "icebird": "^0.8.10",
193
+ "icebird": "^0.8.11",
194
194
  "tsx": "^4.22.4",
195
195
  "unstorage": "^1.17.5",
196
196
  "vitest": "^4.1.9"