sliftutils 1.4.60 → 1.4.61

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sliftutils",
3
- "version": "1.4.60",
3
+ "version": "1.4.61",
4
4
  "main": "index.js",
5
5
  "license": "MIT",
6
6
  "files": [
@@ -658,17 +658,22 @@ export class BulkDatabaseBase<T extends { key: string }> {
658
658
  // expanded console.group so a merge takes one collapsible block, not a
659
659
  // screenful (and never the per-file name dump it used to spew).
660
660
  const steps: string[] = [];
661
- steps.push(`read ${inputs.length} input file(s), ${fmtBytes(inTotal)}`);
661
+ // Each step records the time spent since the previous step in blue at the front, so callers can
662
+ // just describe what they did and not bother measuring/formatting elapsed times themselves.
663
+ let lastStepMs = mergeStartMs;
664
+ const log = (line: string) => {
665
+ const now = Date.now();
666
+ steps.push(`${blue(formatTime(now - lastStepMs))} ${line}`);
667
+ lastStepMs = now;
668
+ };
669
+ log(`${magenta("read")}: ${inputs.length} input file(s), ${fmtBytes(inTotal)}`);
662
670
 
663
671
  const newNames: string[] = [];
664
672
  const mergeResult = await runPlannedMerge({
665
673
  sources: readers,
666
674
  sourceNames: readerNames,
667
675
  collectionName: this.name,
668
- log: line => {
669
- console.log(line);
670
- steps.push(line);
671
- },
676
+ log,
672
677
  writeFile: async (data) => {
673
678
  const fname = newFileName(timestamp);
674
679
  await storage.set(fname, encodeCompressedBlocks(data));
@@ -688,7 +693,7 @@ export class BulkDatabaseBase<T extends { key: string }> {
688
693
 
689
694
  const outputs = await Promise.all(outNames.map(async n => ({ name: n, size: (await storage.getInfo(n).catch(() => undefined))?.size ?? 0 })));
690
695
  const outTotal = outputs.reduce((a, f) => a + f.size, 0);
691
- steps.push(`wrote ${outputs.length} output file(s), ${fmtBytes(outTotal)}${carriedDeletes ? `, ${carriedDeletes} tombstones carried` : ""}`);
696
+ log(`${magenta("wrote")}: ${outputs.length} output file(s), ${fmtBytes(outTotal)}${carriedDeletes ? `, ${carriedDeletes} tombstones carried` : ""}`);
692
697
 
693
698
  console.group(`${blue(this.name)} ${magenta("merge")}: ${fmtBytes(inTotal)} → ${fmtBytes(outTotal)} (${inputs.length}→${outputs.length} files) in ${formatTime(Date.now() - mergeStartMs)}`);
694
699
  for (const line of steps) console.log(line);
@@ -1,5 +1,5 @@
1
- import { formatNumber, formatTime } from "socket-function/src/formatting/format";
2
- import { blue, red } from "socket-function/src/formatting/logColors";
1
+ import { formatNumber } from "socket-function/src/formatting/format";
2
+ import { blue, magenta } from "socket-function/src/formatting/logColors";
3
3
  import {
4
4
  BaseBulkDatabaseReader,
5
5
  ColumnIndex,
@@ -98,8 +98,6 @@ export async function runPlannedMerge(config: {
98
98
  const log = config.log ?? (line => console.log(`${blue(config.collectionName)} ${line}`));
99
99
 
100
100
  // ─────────────────────────────────────────── Phase 1: plan ───────────────────────────────────────────
101
- const planStart = Date.now();
102
-
103
101
  // Aggregate keyTimes + deleteTimes across all sources (max per key).
104
102
  const deleteTime = new Map<string, number>();
105
103
  const keyTime = new Map<string, number>();
@@ -222,8 +220,7 @@ export async function runPlannedMerge(config: {
222
220
  // Build per-file plans: offsets/types/copy-runs per column.
223
221
  const plans = fileKeyRanges.map(range => buildOutputPlan(range, liveKeys, cellsPerKey, allColumns, keyTime));
224
222
 
225
- const planTime = Date.now() - planStart;
226
- log(`mapping done — ${formatNumber(liveKeys.length)} live keys, ${plans.length} output file(s), ${formatNumber(carriedDeletes.size)} tombstones carried, in ${red(formatTime(planTime))}`);
223
+ log(`${magenta("plan")}: ${formatNumber(liveKeys.length)} live keys, ${plans.length} output file(s), ${formatNumber(carriedDeletes.size)} tombstones carried`);
227
224
 
228
225
  // ───────────────────────────────────────── Phase 2: execute ──────────────────────────────────────────
229
226
  // Group output files into batches that fit within targetBatchBytes so we read inputs once per batch
@@ -244,17 +241,15 @@ export async function runPlannedMerge(config: {
244
241
  }
245
242
 
246
243
  const outputs: PlannedMergeOutput[] = [];
247
- const execStart = Date.now();
248
244
  for (let bi = 0; bi < batches.length; bi++) {
249
245
  const batch = batches[bi];
250
246
  const batchBytes = batch.reduce((a, p) => a + p.estimatedFileBytes, 0);
251
- log(`batch ${bi + 1}/${batches.length}: ${batch.length} output file(s), ~${fmtBytes(batchBytes)} budget`);
247
+ log(`${magenta("batch")} ${bi + 1}/${batches.length}: ${batch.length} output file(s), ~${fmtBytes(batchBytes)} budget`);
252
248
  const batchOutputs = await executeBatch(batch, indexesPerSource, config.sources, config.sourceNames, config.writeFile, log);
253
249
  outputs.push(...batchOutputs);
254
250
  }
255
- const execTime = Date.now() - execStart;
256
251
  const writtenBytes = outputs.reduce((a, o) => a + o.size, 0);
257
- log(`execute done — ${outputs.length} file(s), ${fmtBytes(writtenBytes)} written, in ${red(formatTime(execTime))} (plan + execute: ${red(formatTime(Date.now() - planStart))})`);
252
+ log(`${magenta("execute")}: ${outputs.length} file(s), ${fmtBytes(writtenBytes)} written`);
258
253
 
259
254
  return { outputs, carriedDeletes };
260
255
  }
@@ -387,14 +382,12 @@ async function executeBatch(
387
382
  const outputs: PlannedMergeOutput[] = [];
388
383
  for (let fi = 0; fi < plans.length; fi++) {
389
384
  const plan = plans[fi];
390
- const start = Date.now();
391
385
  const valueColumns = blobsPerFile[fi].map(b => ({ name: b.name, blob: b.blob }));
392
386
  const fileBuf = assemblePlannedFile({ valueColumns, keys: plan.keys, times: plan.times });
393
387
  const { name, size } = await writeFile(fileBuf);
394
- const elapsed = Date.now() - start;
395
388
  const sourcesNamed = new Map<string, number>();
396
389
  for (const [si, n] of plan.sourceCounts) sourcesNamed.set(sourceNames[si], n);
397
- log(`output: ${formatNumber(plan.keys.length)} rows from ${plan.sourceCounts.size} input(s), ${fmtBytes(size)} in ${formatTime(elapsed)}`);
390
+ log(`${magenta("output")}: ${formatNumber(plan.keys.length)} rows from ${plan.sourceCounts.size} input(s), ${fmtBytes(size)}`);
398
391
  outputs.push({ name, minKey: plan.minKey, maxKey: plan.maxKey, rowCount: plan.keys.length, size, sources: sourcesNamed });
399
392
  }
400
393
  return outputs;