@naturalcycles/nodejs-lib 15.103.0 → 15.105.0

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 (39) hide show
  1. package/dist/stream/pipeline.js +3 -3
  2. package/dist/stream/progressLogger.d.ts +0 -22
  3. package/dist/stream/progressLogger.js +0 -17
  4. package/dist/stream/transform/transformChunk.js +1 -0
  5. package/dist/stream/transform/transformFilter.js +1 -0
  6. package/dist/stream/transform/transformFlatten.js +2 -0
  7. package/dist/stream/transform/transformFork.js +1 -1
  8. package/dist/stream/transform/transformLimit.js +1 -1
  9. package/dist/stream/transform/transformMapSimple.js +1 -1
  10. package/dist/stream/transform/transformMapSync.js +1 -0
  11. package/dist/stream/transform/transformNoOp.js +1 -0
  12. package/dist/stream/transform/transformOffset.js +1 -0
  13. package/dist/stream/transform/transformThrottle.js +1 -1
  14. package/dist/stream/transform/transformThrottleByRSS.js +1 -1
  15. package/dist/stream/transform/transformWarmup.js +1 -1
  16. package/dist/zip/zip2.d.ts +51 -0
  17. package/dist/zip/zip2.js +123 -0
  18. package/package.json +2 -2
  19. package/src/stream/pipeline.ts +3 -3
  20. package/src/stream/progressLogger.ts +0 -43
  21. package/src/stream/transform/transformChunk.ts +1 -0
  22. package/src/stream/transform/transformFilter.ts +1 -0
  23. package/src/stream/transform/transformFlatten.ts +2 -0
  24. package/src/stream/transform/transformFork.ts +1 -1
  25. package/src/stream/transform/transformLimit.ts +1 -1
  26. package/src/stream/transform/transformMapSimple.ts +1 -1
  27. package/src/stream/transform/transformMapSync.ts +1 -0
  28. package/src/stream/transform/transformNoOp.ts +1 -0
  29. package/src/stream/transform/transformOffset.ts +1 -0
  30. package/src/stream/transform/transformThrottle.ts +1 -1
  31. package/src/stream/transform/transformThrottleByRSS.ts +1 -1
  32. package/src/stream/transform/transformWarmup.ts +1 -1
  33. package/src/zip/zip2.ts +159 -0
  34. package/dist/stream/sizeStack.d.ts +0 -10
  35. package/dist/stream/sizeStack.js +0 -46
  36. package/dist/zip/zip.util.d.ts +0 -41
  37. package/dist/zip/zip.util.js +0 -99
  38. package/src/stream/sizeStack.ts +0 -61
  39. package/src/zip/zip.util.ts +0 -149
@@ -4,7 +4,7 @@ import { createGzip, createUnzip, createZstdCompress, createZstdDecompress } fro
4
4
  import { createAbortableSignal } from '@naturalcycles/js-lib';
5
5
  import { _passthroughPredicate } from '@naturalcycles/js-lib/types';
6
6
  import { fs2 } from '../fs/fs2.js';
7
- import { zstdLevelToOptions } from '../zip/zip.util.js';
7
+ import { zip2 } from '../zip/zip2.js';
8
8
  import { createReadStreamAsNDJson } from './ndjson/createReadStreamAsNDJson.js';
9
9
  import { transformJsonParse } from './ndjson/transformJsonParse.js';
10
10
  import { transformToNDJson } from './ndjson/transformToNDJson.js';
@@ -262,7 +262,7 @@ export class Pipeline {
262
262
  }
263
263
  zstdCompress(level, // defaults to 3
264
264
  opt) {
265
- this.transforms.push(createZstdCompress(zstdLevelToOptions(level, opt)));
265
+ this.transforms.push(createZstdCompress(zip2.zstdLevelToOptions(level, opt)));
266
266
  this.objectMode = false;
267
267
  return this;
268
268
  }
@@ -302,7 +302,7 @@ export class Pipeline {
302
302
  }));
303
303
  }
304
304
  else if (outputFilePath.endsWith('.zst')) {
305
- this.transforms.push(createZstdCompress(zstdLevelToOptions(level)));
305
+ this.transforms.push(createZstdCompress(zip2.zstdLevelToOptions(level)));
306
306
  }
307
307
  this.destination = fs2.createWriteStream(outputFilePath, {});
308
308
  await this.run();
@@ -90,26 +90,6 @@ export interface ProgressLoggerCfg<T = any> {
90
90
  * Defaults to 1.
91
91
  */
92
92
  chunkSize?: PositiveInteger;
93
- /**
94
- * Experimental logging of item (shunk) sizes, when json-stringified.
95
- *
96
- * Defaults to false.
97
- *
98
- * @experimental
99
- */
100
- logSizes?: boolean;
101
- /**
102
- * How many last item sizes to keep in a buffer, to calculate stats (p50, p90, avg, etc).
103
- * Defaults to 100_000.
104
- * Cannot be Infinity.
105
- */
106
- logSizesBuffer?: number;
107
- /**
108
- * Works in addition to `logSizes`. Adds "zipped sizes".
109
- *
110
- * @experimental
111
- */
112
- logZippedSizes?: boolean;
113
93
  }
114
94
  export interface ProgressLogItem extends AnyObject {
115
95
  heapUsed?: number;
@@ -138,8 +118,6 @@ export declare class ProgressLogger<T> implements Disposable {
138
118
  private processedLastSecond;
139
119
  private progress;
140
120
  private peakRSS;
141
- private sizes?;
142
- private sizesZipped?;
143
121
  private start;
144
122
  log(chunk?: T): void;
145
123
  done(): void;
@@ -3,7 +3,6 @@ import { _hc, _mb } from '@naturalcycles/js-lib';
3
3
  import { _since, localTime } from '@naturalcycles/js-lib/datetime';
4
4
  import { SimpleMovingAverage } from '@naturalcycles/js-lib/math';
5
5
  import { boldWhite, dimGrey, hasColors, white, yellow } from '../colors/colors.js';
6
- import { SizeStack } from './sizeStack.js';
7
6
  const inspectOpt = {
8
7
  colors: hasColors,
9
8
  breakLength: 300,
@@ -34,8 +33,6 @@ export class ProgressLogger {
34
33
  processedLastSecond;
35
34
  progress;
36
35
  peakRSS;
37
- sizes;
38
- sizesZipped;
39
36
  start() {
40
37
  this.started = Date.now();
41
38
  this.lastSecondStarted = Date.now();
@@ -43,18 +40,10 @@ export class ProgressLogger {
43
40
  this.processedLastSecond = 0;
44
41
  this.progress = 0;
45
42
  this.peakRSS = 0;
46
- this.sizes = this.cfg.logSizes ? new SizeStack('json', this.cfg.logSizesBuffer) : undefined;
47
- this.sizesZipped = this.cfg.logZippedSizes
48
- ? new SizeStack('json.gz', this.cfg.logSizesBuffer)
49
- : undefined;
50
43
  }
51
44
  log(chunk) {
52
45
  this.progress++;
53
46
  this.processedLastSecond++;
54
- if (this.sizes) {
55
- // Check it, cause gzipping might be delayed here..
56
- void SizeStack.countItem(chunk, this.cfg.logger, this.sizes, this.sizesZipped);
57
- }
58
47
  if (this.cfg.logProgress && this.progress % this.cfg.logEvery === 0) {
59
48
  this.logStats(chunk, false, this.progress % this.logEvery10 === 0);
60
49
  }
@@ -101,12 +90,6 @@ export class ProgressLogger {
101
90
  if (logRPS)
102
91
  Object.assign(o, { rps10, rpsTotal });
103
92
  logger.log(inspect(o, inspectOpt));
104
- if (this.sizes?.items.length) {
105
- logger.log(this.sizes.getStats());
106
- if (this.sizesZipped?.items.length) {
107
- logger.log(this.sizesZipped.getStats());
108
- }
109
- }
110
93
  if (tenx) {
111
94
  const perHour = _hc((batchedProgress * 1000 * 60 * 60) / (now - this.started));
112
95
  logger.log(`${dimGrey(localTime.now().toPretty())} ${white(metric)} took ${yellow(_since(this.started))} so far to process ${yellow(_hc(batchedProgress))} rows, ~${yellow(perHour)}/hour`);
@@ -11,6 +11,7 @@ export function transformChunk(chunkSize, opt) {
11
11
  let buf = [];
12
12
  return new Transform({
13
13
  objectMode: true,
14
+ highWaterMark: 1,
14
15
  ...opt,
15
16
  transform(chunk, _, cb) {
16
17
  buf.push(chunk);
@@ -16,6 +16,7 @@ export function transformFilterSync(predicate, opt = {}) {
16
16
  let index = 0;
17
17
  return new Transform({
18
18
  objectMode: true,
19
+ highWaterMark: 1,
19
20
  ...opt,
20
21
  transform(chunk, _, cb) {
21
22
  try {
@@ -2,6 +2,7 @@ import { Transform } from 'node:stream';
2
2
  export function transformFlatten() {
3
3
  return new Transform({
4
4
  objectMode: true,
5
+ highWaterMark: 1,
5
6
  transform(chunk, _, cb) {
6
7
  for (const item of chunk) {
7
8
  this.push(item);
@@ -13,6 +14,7 @@ export function transformFlatten() {
13
14
  export function transformFlattenIfNeeded() {
14
15
  return new Transform({
15
16
  objectMode: true,
17
+ highWaterMark: 1,
16
18
  transform(chunk, _, cb) {
17
19
  if (Array.isArray(chunk)) {
18
20
  for (const item of chunk) {
@@ -12,7 +12,7 @@ import { createReadable } from '../readable/createReadable.js';
12
12
  * @experimental
13
13
  */
14
14
  export function transformFork(fn, opt = {}) {
15
- const { objectMode = true, highWaterMark } = opt;
15
+ const { objectMode = true, highWaterMark = 1 } = opt;
16
16
  const logger = createCommonLoggerAtLevel(opt.logger, opt.logLevel);
17
17
  let lock;
18
18
  const fork = createReadable([], {}, () => {
@@ -2,7 +2,7 @@ import { Transform } from 'node:stream';
2
2
  import { PIPELINE_GRACEFUL_ABORT } from '../stream.util.js';
3
3
  import { transformNoOp } from './transformNoOp.js';
4
4
  export function transformLimit(opt) {
5
- const { limit, signal, objectMode = true, highWaterMark } = opt;
5
+ const { limit, signal, objectMode = true, highWaterMark = 1 } = opt;
6
6
  if (!limit) {
7
7
  return transformNoOp();
8
8
  }
@@ -11,7 +11,7 @@ import { ErrorMode } from '@naturalcycles/js-lib/error/errorMode.js';
11
11
  */
12
12
  export function transformMapSimple(mapper, opt = {}) {
13
13
  let index = -1;
14
- const { errorMode = ErrorMode.THROW_IMMEDIATELY, logger = console, objectMode = true, highWaterMark, } = opt;
14
+ const { errorMode = ErrorMode.THROW_IMMEDIATELY, logger = console, objectMode = true, highWaterMark = 1, } = opt;
15
15
  return new Transform({
16
16
  objectMode,
17
17
  highWaterMark,
@@ -20,6 +20,7 @@ export function transformMapSync(mapper, opt = {}) {
20
20
  const logger = createCommonLoggerAtLevel(opt.logger, opt.logLevel);
21
21
  return new Transform({
22
22
  objectMode,
23
+ highWaterMark: 1,
23
24
  ...opt,
24
25
  transform(chunk, _, cb) {
25
26
  // Stop processing if isSettled
@@ -7,6 +7,7 @@ import { Transform } from 'node:stream';
7
7
  export function transformNoOp() {
8
8
  return new Transform({
9
9
  objectMode: true,
10
+ highWaterMark: 1,
10
11
  transform(chunk, _, cb) {
11
12
  cb(null, chunk);
12
13
  },
@@ -9,6 +9,7 @@ export function transformOffset(opt) {
9
9
  let i = 0; // so we start first chunk with 1
10
10
  return new Transform({
11
11
  objectMode: true,
12
+ highWaterMark: 1,
12
13
  ...opt,
13
14
  transform(chunk, _, cb) {
14
15
  if (++i <= offset) {
@@ -20,7 +20,7 @@ import { pDefer } from '@naturalcycles/js-lib/promise/pDefer.js';
20
20
  * @experimental
21
21
  */
22
22
  export function transformThrottle(opt) {
23
- const { throughput, interval, objectMode = true, highWaterMark } = opt;
23
+ const { throughput, interval, objectMode = true, highWaterMark = 1 } = opt;
24
24
  let count = 0;
25
25
  let start;
26
26
  let lock;
@@ -15,7 +15,7 @@ import { pDefer } from '@naturalcycles/js-lib/promise/pDefer.js';
15
15
  */
16
16
  export function transformThrottleByRSS(opt) {
17
17
  const { maxRSS, pollInterval = 5000, pollTimeout = 30 * 60_000, // 30 min
18
- onPollTimeout = 'open-the-floodgates', objectMode = true, highWaterMark, } = opt;
18
+ onPollTimeout = 'open-the-floodgates', objectMode = true, highWaterMark = 1, } = opt;
19
19
  const maxRSSBytes = maxRSS * 1024 * 1024;
20
20
  let lock;
21
21
  let pollTimer;
@@ -12,7 +12,7 @@ import { pDefer } from '@naturalcycles/js-lib/promise/pDefer.js';
12
12
  * @experimental
13
13
  */
14
14
  export function transformWarmup(opt) {
15
- const { concurrency, warmupSeconds, objectMode = true, highWaterMark } = opt;
15
+ const { concurrency, warmupSeconds, objectMode = true, highWaterMark = 1 } = opt;
16
16
  const warmupMs = warmupSeconds * 1000;
17
17
  const logger = createCommonLoggerAtLevel(opt.logger, opt.logLevel);
18
18
  let startTime = 0;
@@ -0,0 +1,51 @@
1
+ import type { ZlibOptions, ZstdOptions } from 'node:zlib';
2
+ import type { Integer } from '@naturalcycles/js-lib/types';
3
+ declare class Zip2 {
4
+ decompressZstdOrInflateToString(buf: Buffer): Promise<string>;
5
+ decompressZstdOrInflateToStringSync(buf: Buffer): string;
6
+ /**
7
+ * Detects if Buffer is zstd-compressed.
8
+ * Otherwise attempts to Inflate.
9
+ */
10
+ decompressZstdOrInflate(buf: Buffer): Promise<Buffer<ArrayBuffer>>;
11
+ decompressZstdOrInflateSync(buf: Buffer): Buffer<ArrayBuffer>;
12
+ /**
13
+ * deflateBuffer uses `deflate`.
14
+ * It's 9 bytes shorter than `gzip`.
15
+ */
16
+ deflate(input: string | Buffer, options?: ZlibOptions): Promise<Buffer<ArrayBuffer>>;
17
+ /**
18
+ * deflateSync uses `deflate`.
19
+ * It's 9 bytes shorter than `gzip`.
20
+ */
21
+ deflateSync(input: string | Buffer, options?: ZlibOptions): Buffer<ArrayBuffer>;
22
+ inflate(buf: Buffer, options?: ZlibOptions): Promise<Buffer<ArrayBuffer>>;
23
+ inflateSync(buf: Buffer, options?: ZlibOptions): Buffer<ArrayBuffer>;
24
+ inflateToString(buf: Buffer, options?: ZlibOptions): Promise<string>;
25
+ inflateToStringSync(buf: Buffer, options?: ZlibOptions): string;
26
+ /**
27
+ * gzipBuffer uses `gzip`
28
+ * It's 9 bytes longer than `deflate`.
29
+ */
30
+ gzip(input: string | Buffer, options?: ZlibOptions): Promise<Buffer<ArrayBuffer>>;
31
+ /**
32
+ * gzipBuffer uses `gzip`
33
+ * It's 9 bytes longer than `deflate`.
34
+ */
35
+ gzipSync(input: string | Buffer, options?: ZlibOptions): Buffer<ArrayBuffer>;
36
+ gunzip(buf: Buffer, options?: ZlibOptions): Promise<Buffer<ArrayBuffer>>;
37
+ gunzipSync(buf: Buffer, options?: ZlibOptions): Buffer<ArrayBuffer>;
38
+ gunzipToString(buf: Buffer, options?: ZlibOptions): Promise<string>;
39
+ gunzipToStringSync(buf: Buffer, options?: ZlibOptions): string;
40
+ zstdCompress(input: Buffer | string, level?: Integer, options?: ZstdOptions): Promise<Buffer<ArrayBuffer>>;
41
+ zstdCompressSync(input: Buffer | string, level?: Integer, options?: ZstdOptions): Buffer<ArrayBuffer>;
42
+ zstdLevelToOptions(level: Integer | undefined, opt?: ZstdOptions): ZstdOptions;
43
+ zstdDecompressToString(input: Buffer, options?: ZstdOptions): Promise<string>;
44
+ zstdDecompress(input: Buffer, options?: ZstdOptions): Promise<Buffer<ArrayBuffer>>;
45
+ zstdDecompressToStringSync(input: Buffer, options?: ZstdOptions): string;
46
+ zstdDecompressSync(input: Buffer, options?: ZstdOptions): Buffer<ArrayBuffer>;
47
+ isZstdBuffer(input: Buffer): boolean;
48
+ isGzipBuffer(input: Buffer): boolean;
49
+ }
50
+ export declare const zip2: Zip2;
51
+ export {};
@@ -0,0 +1,123 @@
1
+ import { promisify } from 'node:util';
2
+ import zlib from 'node:zlib';
3
+ const deflateAsync = promisify(zlib.deflate.bind(zlib));
4
+ const inflateAsync = promisify(zlib.inflate.bind(zlib));
5
+ const gzipAsync = promisify(zlib.gzip.bind(zlib));
6
+ const gunzipAsync = promisify(zlib.gunzip.bind(zlib));
7
+ const zstdCompressAsync = promisify(zlib.zstdCompress.bind(zlib));
8
+ const zstdDecompressAsync = promisify(zlib.zstdDecompress.bind(zlib));
9
+ class Zip2 {
10
+ async decompressZstdOrInflateToString(buf) {
11
+ return (await this.decompressZstdOrInflate(buf)).toString();
12
+ }
13
+ decompressZstdOrInflateToStringSync(buf) {
14
+ return this.decompressZstdOrInflateSync(buf).toString();
15
+ }
16
+ /**
17
+ * Detects if Buffer is zstd-compressed.
18
+ * Otherwise attempts to Inflate.
19
+ */
20
+ async decompressZstdOrInflate(buf) {
21
+ if (this.isZstdBuffer(buf)) {
22
+ return await zstdDecompressAsync(buf);
23
+ }
24
+ return await inflateAsync(buf);
25
+ }
26
+ decompressZstdOrInflateSync(buf) {
27
+ if (this.isZstdBuffer(buf)) {
28
+ return zlib.zstdDecompressSync(buf);
29
+ }
30
+ return zlib.inflateSync(buf);
31
+ }
32
+ /**
33
+ * deflateBuffer uses `deflate`.
34
+ * It's 9 bytes shorter than `gzip`.
35
+ */
36
+ async deflate(input, options = {}) {
37
+ return await deflateAsync(input, options);
38
+ }
39
+ /**
40
+ * deflateSync uses `deflate`.
41
+ * It's 9 bytes shorter than `gzip`.
42
+ */
43
+ deflateSync(input, options) {
44
+ return zlib.deflateSync(input, options);
45
+ }
46
+ async inflate(buf, options = {}) {
47
+ return await inflateAsync(buf, options);
48
+ }
49
+ inflateSync(buf, options = {}) {
50
+ return zlib.inflateSync(buf, options);
51
+ }
52
+ async inflateToString(buf, options) {
53
+ return (await this.inflate(buf, options)).toString();
54
+ }
55
+ inflateToStringSync(buf, options) {
56
+ return zlib.inflateSync(buf, options).toString();
57
+ }
58
+ /**
59
+ * gzipBuffer uses `gzip`
60
+ * It's 9 bytes longer than `deflate`.
61
+ */
62
+ async gzip(input, options = {}) {
63
+ return await gzipAsync(input, options);
64
+ }
65
+ /**
66
+ * gzipBuffer uses `gzip`
67
+ * It's 9 bytes longer than `deflate`.
68
+ */
69
+ gzipSync(input, options = {}) {
70
+ return zlib.gzipSync(input, options);
71
+ }
72
+ async gunzip(buf, options = {}) {
73
+ return await gunzipAsync(buf, options);
74
+ }
75
+ gunzipSync(buf, options = {}) {
76
+ return zlib.gunzipSync(buf, options);
77
+ }
78
+ async gunzipToString(buf, options) {
79
+ return (await this.gunzip(buf, options)).toString();
80
+ }
81
+ gunzipToStringSync(buf, options) {
82
+ return zlib.gunzipSync(buf, options).toString();
83
+ }
84
+ async zstdCompress(input, level, // defaults to 3
85
+ options = {}) {
86
+ return await zstdCompressAsync(input, this.zstdLevelToOptions(level, options));
87
+ }
88
+ zstdCompressSync(input, level, // defaults to 3
89
+ options = {}) {
90
+ return zlib.zstdCompressSync(input, this.zstdLevelToOptions(level, options));
91
+ }
92
+ zstdLevelToOptions(level, opt = {}) {
93
+ if (!level)
94
+ return opt;
95
+ return {
96
+ ...opt,
97
+ params: {
98
+ ...opt.params,
99
+ [zlib.constants.ZSTD_c_compressionLevel]: level,
100
+ },
101
+ };
102
+ }
103
+ async zstdDecompressToString(input, options = {}) {
104
+ return (await zstdDecompressAsync(input, options)).toString();
105
+ }
106
+ async zstdDecompress(input, options = {}) {
107
+ return await zstdDecompressAsync(input, options);
108
+ }
109
+ zstdDecompressToStringSync(input, options = {}) {
110
+ return zlib.zstdDecompressSync(input, options).toString();
111
+ }
112
+ zstdDecompressSync(input, options = {}) {
113
+ return zlib.zstdDecompressSync(input, options);
114
+ }
115
+ isZstdBuffer(input) {
116
+ return input.readUInt32LE(0) === ZSTD_MAGIC_NUMBER;
117
+ }
118
+ isGzipBuffer(input) {
119
+ return input[0] === 0x1f && input[1] === 0x8b;
120
+ }
121
+ }
122
+ export const zip2 = new Zip2();
123
+ const ZSTD_MAGIC_NUMBER = 0xfd2fb528;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@naturalcycles/nodejs-lib",
3
3
  "type": "module",
4
- "version": "15.103.0",
4
+ "version": "15.105.0",
5
5
  "dependencies": {
6
6
  "@naturalcycles/js-lib": "^15",
7
7
  "@standard-schema/spec": "^1",
@@ -38,7 +38,7 @@
38
38
  "./stream/*.js": "./dist/stream/*.js",
39
39
  "./yargs": "./dist/yargs/yargs.util.js",
40
40
  "./ajv": "./dist/validation/ajv/index.js",
41
- "./zip": "./dist/zip/zip.util.js"
41
+ "./zip": "./dist/zip/zip2.js"
42
42
  },
43
43
  "bin": {
44
44
  "kpy": "dist/bin/kpy.js",
@@ -19,7 +19,7 @@ import type {
19
19
  SKIP,
20
20
  } from '@naturalcycles/js-lib/types'
21
21
  import { fs2 } from '../fs/fs2.js'
22
- import { zstdLevelToOptions } from '../zip/zip.util.js'
22
+ import { zip2 } from '../zip/zip2.js'
23
23
  import { createReadStreamAsNDJson } from './ndjson/createReadStreamAsNDJson.js'
24
24
  import { transformJsonParse } from './ndjson/transformJsonParse.js'
25
25
  import { transformToNDJson } from './ndjson/transformToNDJson.js'
@@ -359,7 +359,7 @@ export class Pipeline<T = unknown> {
359
359
  level?: Integer, // defaults to 3
360
360
  opt?: ZstdOptions,
361
361
  ): Pipeline<Uint8Array> {
362
- this.transforms.push(createZstdCompress(zstdLevelToOptions(level, opt)))
362
+ this.transforms.push(createZstdCompress(zip2.zstdLevelToOptions(level, opt)))
363
363
  this.objectMode = false
364
364
  return this as any
365
365
  }
@@ -406,7 +406,7 @@ export class Pipeline<T = unknown> {
406
406
  }),
407
407
  )
408
408
  } else if (outputFilePath.endsWith('.zst')) {
409
- this.transforms.push(createZstdCompress(zstdLevelToOptions(level)))
409
+ this.transforms.push(createZstdCompress(zip2.zstdLevelToOptions(level)))
410
410
  }
411
411
  this.destination = fs2.createWriteStream(outputFilePath, {
412
412
  // highWaterMark: 64 * 1024, // no observed speedup
@@ -6,7 +6,6 @@ import type { CommonLogger } from '@naturalcycles/js-lib/log'
6
6
  import { SimpleMovingAverage } from '@naturalcycles/js-lib/math'
7
7
  import type { AnyObject, PositiveInteger, UnixTimestampMillis } from '@naturalcycles/js-lib/types'
8
8
  import { boldWhite, dimGrey, hasColors, white, yellow } from '../colors/colors.js'
9
- import { SizeStack } from './sizeStack.js'
10
9
  import type { ReadableMapper } from './stream.model.js'
11
10
 
12
11
  export interface ProgressLoggerCfg<T = any> {
@@ -112,29 +111,6 @@ export interface ProgressLoggerCfg<T = any> {
112
111
  * Defaults to 1.
113
112
  */
114
113
  chunkSize?: PositiveInteger
115
-
116
- /**
117
- * Experimental logging of item (shunk) sizes, when json-stringified.
118
- *
119
- * Defaults to false.
120
- *
121
- * @experimental
122
- */
123
- logSizes?: boolean
124
-
125
- /**
126
- * How many last item sizes to keep in a buffer, to calculate stats (p50, p90, avg, etc).
127
- * Defaults to 100_000.
128
- * Cannot be Infinity.
129
- */
130
- logSizesBuffer?: number
131
-
132
- /**
133
- * Works in addition to `logSizes`. Adds "zipped sizes".
134
- *
135
- * @experimental
136
- */
137
- logZippedSizes?: boolean
138
114
  }
139
115
 
140
116
  export interface ProgressLogItem extends AnyObject {
@@ -189,8 +165,6 @@ export class ProgressLogger<T> implements Disposable {
189
165
  private processedLastSecond!: number
190
166
  private progress!: number
191
167
  private peakRSS!: number
192
- private sizes?: SizeStack
193
- private sizesZipped?: SizeStack
194
168
 
195
169
  private start(): void {
196
170
  this.started = Date.now() as UnixTimestampMillis
@@ -199,21 +173,12 @@ export class ProgressLogger<T> implements Disposable {
199
173
  this.processedLastSecond = 0
200
174
  this.progress = 0
201
175
  this.peakRSS = 0
202
- this.sizes = this.cfg.logSizes ? new SizeStack('json', this.cfg.logSizesBuffer) : undefined
203
- this.sizesZipped = this.cfg.logZippedSizes
204
- ? new SizeStack('json.gz', this.cfg.logSizesBuffer)
205
- : undefined
206
176
  }
207
177
 
208
178
  log(chunk?: T): void {
209
179
  this.progress++
210
180
  this.processedLastSecond++
211
181
 
212
- if (this.sizes) {
213
- // Check it, cause gzipping might be delayed here..
214
- void SizeStack.countItem(chunk, this.cfg.logger, this.sizes, this.sizesZipped)
215
- }
216
-
217
182
  if (this.cfg.logProgress && this.progress % this.cfg.logEvery === 0) {
218
183
  this.logStats(chunk, false, this.progress % this.logEvery10 === 0)
219
184
  }
@@ -275,14 +240,6 @@ export class ProgressLogger<T> implements Disposable {
275
240
 
276
241
  logger.log(inspect(o, inspectOpt))
277
242
 
278
- if (this.sizes?.items.length) {
279
- logger.log(this.sizes.getStats())
280
-
281
- if (this.sizesZipped?.items.length) {
282
- logger.log(this.sizesZipped.getStats())
283
- }
284
- }
285
-
286
243
  if (tenx) {
287
244
  const perHour = _hc((batchedProgress * 1000 * 60 * 60) / (now - this.started))
288
245
 
@@ -18,6 +18,7 @@ export function transformChunk<IN = any>(
18
18
 
19
19
  return new Transform({
20
20
  objectMode: true,
21
+ highWaterMark: 1,
21
22
  ...opt,
22
23
  transform(chunk, _, cb) {
23
24
  buf.push(chunk)
@@ -28,6 +28,7 @@ export function transformFilterSync<IN = any>(
28
28
 
29
29
  return new Transform({
30
30
  objectMode: true,
31
+ highWaterMark: 1,
31
32
  ...opt,
32
33
  transform(chunk: IN, _, cb) {
33
34
  try {
@@ -4,6 +4,7 @@ import type { TransformTyped } from '../stream.model.js'
4
4
  export function transformFlatten<T>(): TransformTyped<T[], T> {
5
5
  return new Transform({
6
6
  objectMode: true,
7
+ highWaterMark: 1,
7
8
  transform(chunk: T[], _, cb) {
8
9
  for (const item of chunk) {
9
10
  this.push(item)
@@ -16,6 +17,7 @@ export function transformFlatten<T>(): TransformTyped<T[], T> {
16
17
  export function transformFlattenIfNeeded<T>(): TransformTyped<T[], T> {
17
18
  return new Transform({
18
19
  objectMode: true,
20
+ highWaterMark: 1,
19
21
  transform(chunk: T[], _, cb) {
20
22
  if (Array.isArray(chunk)) {
21
23
  for (const item of chunk) {
@@ -18,7 +18,7 @@ export function transformFork<T>(
18
18
  fn: (pipeline: Pipeline<T>) => Promise<void>,
19
19
  opt: TransformOptions = {},
20
20
  ): TransformTyped<T, T> {
21
- const { objectMode = true, highWaterMark } = opt
21
+ const { objectMode = true, highWaterMark = 1 } = opt
22
22
  const logger = createCommonLoggerAtLevel(opt.logger, opt.logLevel)
23
23
 
24
24
  let lock: DeferredPromise | undefined
@@ -18,7 +18,7 @@ export interface TransformLimitOptions extends TransformOptions {
18
18
  }
19
19
 
20
20
  export function transformLimit<IN>(opt: TransformLimitOptions): TransformTyped<IN, IN> {
21
- const { limit, signal, objectMode = true, highWaterMark } = opt
21
+ const { limit, signal, objectMode = true, highWaterMark = 1 } = opt
22
22
 
23
23
  if (!limit) {
24
24
  return transformNoOp()
@@ -30,7 +30,7 @@ export function transformMapSimple<IN = any, OUT = IN>(
30
30
  errorMode = ErrorMode.THROW_IMMEDIATELY,
31
31
  logger = console,
32
32
  objectMode = true,
33
- highWaterMark,
33
+ highWaterMark = 1,
34
34
  } = opt
35
35
 
36
36
  return new Transform({
@@ -88,6 +88,7 @@ export function transformMapSync<IN = any, OUT = IN>(
88
88
 
89
89
  return new Transform({
90
90
  objectMode,
91
+ highWaterMark: 1,
91
92
  ...opt,
92
93
  transform(chunk: IN, _, cb) {
93
94
  // Stop processing if isSettled
@@ -9,6 +9,7 @@ import type { TransformTyped } from '../stream.model.js'
9
9
  export function transformNoOp<T = any>(): TransformTyped<T, T> {
10
10
  return new Transform({
11
11
  objectMode: true,
12
+ highWaterMark: 1,
12
13
  transform(chunk: T, _, cb) {
13
14
  cb(null, chunk)
14
15
  },
@@ -22,6 +22,7 @@ export function transformOffset<IN>(opt: TransformOffsetOptions): TransformTyped
22
22
  let i = 0 // so we start first chunk with 1
23
23
  return new Transform({
24
24
  objectMode: true,
25
+ highWaterMark: 1,
25
26
  ...opt,
26
27
  transform(chunk: IN, _, cb) {
27
28
  if (++i <= offset) {
@@ -40,7 +40,7 @@ export interface TransformThrottleOptions extends TransformOptions {
40
40
  * @experimental
41
41
  */
42
42
  export function transformThrottle<T>(opt: TransformThrottleOptions): TransformTyped<T, T> {
43
- const { throughput, interval, objectMode = true, highWaterMark } = opt
43
+ const { throughput, interval, objectMode = true, highWaterMark = 1 } = opt
44
44
 
45
45
  let count = 0
46
46
  let start: UnixTimestampMillis
@@ -60,7 +60,7 @@ export function transformThrottleByRSS<T>(
60
60
  pollTimeout = 30 * 60_000, // 30 min
61
61
  onPollTimeout = 'open-the-floodgates',
62
62
  objectMode = true,
63
- highWaterMark,
63
+ highWaterMark = 1,
64
64
  } = opt
65
65
 
66
66
  const maxRSSBytes = maxRSS * 1024 * 1024
@@ -29,7 +29,7 @@ export interface TransformWarmupOptions extends TransformOptions {
29
29
  * @experimental
30
30
  */
31
31
  export function transformWarmup<T>(opt: TransformWarmupOptions): TransformTyped<T, T> {
32
- const { concurrency, warmupSeconds, objectMode = true, highWaterMark } = opt
32
+ const { concurrency, warmupSeconds, objectMode = true, highWaterMark = 1 } = opt
33
33
  const warmupMs = warmupSeconds * 1000
34
34
  const logger = createCommonLoggerAtLevel(opt.logger, opt.logLevel)
35
35
 
@@ -0,0 +1,159 @@
1
+ import { promisify } from 'node:util'
2
+ import type { ZlibOptions, ZstdOptions } from 'node:zlib'
3
+ import zlib from 'node:zlib'
4
+ import type { Integer } from '@naturalcycles/js-lib/types'
5
+
6
+ const deflateAsync = promisify(zlib.deflate.bind(zlib))
7
+ const inflateAsync = promisify(zlib.inflate.bind(zlib))
8
+ const gzipAsync = promisify(zlib.gzip.bind(zlib))
9
+ const gunzipAsync = promisify(zlib.gunzip.bind(zlib))
10
+ const zstdCompressAsync = promisify(zlib.zstdCompress.bind(zlib))
11
+ const zstdDecompressAsync = promisify(zlib.zstdDecompress.bind(zlib))
12
+
13
+ class Zip2 {
14
+ async decompressZstdOrInflateToString(buf: Buffer): Promise<string> {
15
+ return (await this.decompressZstdOrInflate(buf)).toString()
16
+ }
17
+
18
+ decompressZstdOrInflateToStringSync(buf: Buffer): string {
19
+ return this.decompressZstdOrInflateSync(buf).toString()
20
+ }
21
+
22
+ /**
23
+ * Detects if Buffer is zstd-compressed.
24
+ * Otherwise attempts to Inflate.
25
+ */
26
+ async decompressZstdOrInflate(buf: Buffer): Promise<Buffer<ArrayBuffer>> {
27
+ if (this.isZstdBuffer(buf)) {
28
+ return await zstdDecompressAsync(buf)
29
+ }
30
+ return await inflateAsync(buf)
31
+ }
32
+
33
+ decompressZstdOrInflateSync(buf: Buffer): Buffer<ArrayBuffer> {
34
+ if (this.isZstdBuffer(buf)) {
35
+ return zlib.zstdDecompressSync(buf)
36
+ }
37
+ return zlib.inflateSync(buf)
38
+ }
39
+
40
+ /**
41
+ * deflateBuffer uses `deflate`.
42
+ * It's 9 bytes shorter than `gzip`.
43
+ */
44
+ async deflate(input: string | Buffer, options: ZlibOptions = {}): Promise<Buffer<ArrayBuffer>> {
45
+ return await deflateAsync(input, options)
46
+ }
47
+
48
+ /**
49
+ * deflateSync uses `deflate`.
50
+ * It's 9 bytes shorter than `gzip`.
51
+ */
52
+ deflateSync(input: string | Buffer, options?: ZlibOptions): Buffer<ArrayBuffer> {
53
+ return zlib.deflateSync(input, options)
54
+ }
55
+
56
+ async inflate(buf: Buffer, options: ZlibOptions = {}): Promise<Buffer<ArrayBuffer>> {
57
+ return await inflateAsync(buf, options)
58
+ }
59
+
60
+ inflateSync(buf: Buffer, options: ZlibOptions = {}): Buffer<ArrayBuffer> {
61
+ return zlib.inflateSync(buf, options)
62
+ }
63
+
64
+ async inflateToString(buf: Buffer, options?: ZlibOptions): Promise<string> {
65
+ return (await this.inflate(buf, options)).toString()
66
+ }
67
+
68
+ inflateToStringSync(buf: Buffer, options?: ZlibOptions): string {
69
+ return zlib.inflateSync(buf, options).toString()
70
+ }
71
+
72
+ /**
73
+ * gzipBuffer uses `gzip`
74
+ * It's 9 bytes longer than `deflate`.
75
+ */
76
+ async gzip(input: string | Buffer, options: ZlibOptions = {}): Promise<Buffer<ArrayBuffer>> {
77
+ return await gzipAsync(input, options)
78
+ }
79
+
80
+ /**
81
+ * gzipBuffer uses `gzip`
82
+ * It's 9 bytes longer than `deflate`.
83
+ */
84
+ gzipSync(input: string | Buffer, options: ZlibOptions = {}): Buffer<ArrayBuffer> {
85
+ return zlib.gzipSync(input, options)
86
+ }
87
+
88
+ async gunzip(buf: Buffer, options: ZlibOptions = {}): Promise<Buffer<ArrayBuffer>> {
89
+ return await gunzipAsync(buf, options)
90
+ }
91
+
92
+ gunzipSync(buf: Buffer, options: ZlibOptions = {}): Buffer<ArrayBuffer> {
93
+ return zlib.gunzipSync(buf, options)
94
+ }
95
+
96
+ async gunzipToString(buf: Buffer, options?: ZlibOptions): Promise<string> {
97
+ return (await this.gunzip(buf, options)).toString()
98
+ }
99
+
100
+ gunzipToStringSync(buf: Buffer, options?: ZlibOptions): string {
101
+ return zlib.gunzipSync(buf, options).toString()
102
+ }
103
+
104
+ async zstdCompress(
105
+ input: Buffer | string,
106
+ level?: Integer, // defaults to 3
107
+ options: ZstdOptions = {},
108
+ ): Promise<Buffer<ArrayBuffer>> {
109
+ return await zstdCompressAsync(input, this.zstdLevelToOptions(level, options))
110
+ }
111
+
112
+ zstdCompressSync(
113
+ input: Buffer | string,
114
+ level?: Integer, // defaults to 3
115
+ options: ZstdOptions = {},
116
+ ): Buffer<ArrayBuffer> {
117
+ return zlib.zstdCompressSync(input, this.zstdLevelToOptions(level, options))
118
+ }
119
+
120
+ zstdLevelToOptions(level: Integer | undefined, opt: ZstdOptions = {}): ZstdOptions {
121
+ if (!level) return opt
122
+
123
+ return {
124
+ ...opt,
125
+ params: {
126
+ ...opt.params,
127
+ [zlib.constants.ZSTD_c_compressionLevel]: level,
128
+ },
129
+ }
130
+ }
131
+
132
+ async zstdDecompressToString(input: Buffer, options: ZstdOptions = {}): Promise<string> {
133
+ return (await zstdDecompressAsync(input, options)).toString()
134
+ }
135
+
136
+ async zstdDecompress(input: Buffer, options: ZstdOptions = {}): Promise<Buffer<ArrayBuffer>> {
137
+ return await zstdDecompressAsync(input, options)
138
+ }
139
+
140
+ zstdDecompressToStringSync(input: Buffer, options: ZstdOptions = {}): string {
141
+ return zlib.zstdDecompressSync(input, options).toString()
142
+ }
143
+
144
+ zstdDecompressSync(input: Buffer, options: ZstdOptions = {}): Buffer<ArrayBuffer> {
145
+ return zlib.zstdDecompressSync(input, options)
146
+ }
147
+
148
+ isZstdBuffer(input: Buffer): boolean {
149
+ return input.readUInt32LE(0) === ZSTD_MAGIC_NUMBER
150
+ }
151
+
152
+ isGzipBuffer(input: Buffer): boolean {
153
+ return input[0] === 0x1f && input[1] === 0x8b
154
+ }
155
+ }
156
+
157
+ export const zip2 = new Zip2()
158
+
159
+ const ZSTD_MAGIC_NUMBER = 0xfd2fb528
@@ -1,10 +0,0 @@
1
- import type { CommonLogger } from '@naturalcycles/js-lib/log';
2
- import { NumberStack } from '@naturalcycles/js-lib/math/stack.util.js';
3
- export declare class SizeStack extends NumberStack {
4
- name: string;
5
- constructor(name: string, size: number);
6
- total: number;
7
- push(item: any): this;
8
- getStats(): string;
9
- static countItem(item: any, logger: CommonLogger, sizes?: SizeStack, sizesZipped?: SizeStack): Promise<void>;
10
- }
@@ -1,46 +0,0 @@
1
- import { _hb } from '@naturalcycles/js-lib';
2
- import { NumberStack } from '@naturalcycles/js-lib/math/stack.util.js';
3
- import { yellow } from '../colors/colors.js';
4
- import { gzipBuffer } from '../zip/zip.util.js';
5
- export class SizeStack extends NumberStack {
6
- name;
7
- constructor(name, size) {
8
- super(size);
9
- this.name = name;
10
- }
11
- total = 0;
12
- push(item) {
13
- this.total += item;
14
- return super.push(item);
15
- }
16
- getStats() {
17
- // const pcs = this.percentiles([50, 90])
18
- return [
19
- ' ' + this.name,
20
- 'avg',
21
- yellow(_hb(this.avg())),
22
- // 'p50',
23
- // yellow(_hb(pcs[50])),
24
- // 'p90',
25
- // yellow(_hb(pcs[90])),
26
- 'total',
27
- yellow(_hb(this.total)),
28
- ].join(' ');
29
- }
30
- static async countItem(item, logger, sizes, sizesZipped) {
31
- if (!sizes)
32
- return;
33
- // try-catch, because we don't want to fail the pipeline on logProgress
34
- try {
35
- const buf = Buffer.from(JSON.stringify(item));
36
- sizes.push(buf.byteLength);
37
- if (sizesZipped) {
38
- const { byteLength } = await gzipBuffer(buf);
39
- sizesZipped.push(byteLength);
40
- }
41
- }
42
- catch (err) {
43
- logger.warn(`transformLogProgress failed to JSON.stringify the chunk: ${err.message}`);
44
- }
45
- }
46
- }
@@ -1,41 +0,0 @@
1
- import type { ZlibOptions, ZstdOptions } from 'node:zlib';
2
- import type { Integer } from '@naturalcycles/js-lib/types';
3
- export declare function decompressZstdOrInflateToString(buf: Buffer): Promise<string>;
4
- /**
5
- * Detects if Buffer is zstd-compressed.
6
- * Otherwise attempts to Inflate.
7
- */
8
- export declare function decompressZstdOrInflate(buf: Buffer): Promise<Buffer<ArrayBuffer>>;
9
- /**
10
- * deflateBuffer uses `deflate`.
11
- * It's 9 bytes shorter than `gzip`.
12
- */
13
- export declare function deflateBuffer(buf: Buffer, options?: ZlibOptions): Promise<Buffer<ArrayBuffer>>;
14
- export declare function inflateBuffer(buf: Buffer, options?: ZlibOptions): Promise<Buffer<ArrayBuffer>>;
15
- /**
16
- * deflateString uses `deflate`.
17
- * It's 9 bytes shorter than `gzip`.
18
- */
19
- export declare function deflateString(s: string, options?: ZlibOptions): Promise<Buffer<ArrayBuffer>>;
20
- export declare function inflateToString(buf: Buffer, options?: ZlibOptions): Promise<string>;
21
- /**
22
- * gzipBuffer uses `gzip`
23
- * It's 9 bytes longer than `deflate`.
24
- */
25
- export declare function gzipBuffer(buf: Buffer, options?: ZlibOptions): Promise<Buffer<ArrayBuffer>>;
26
- export declare function gunzipBuffer(buf: Buffer, options?: ZlibOptions): Promise<Buffer<ArrayBuffer>>;
27
- /**
28
- * gzipString uses `gzip`.
29
- * It's 9 bytes longer than `deflate`.
30
- */
31
- export declare function gzipString(s: string, options?: ZlibOptions): Promise<Buffer<ArrayBuffer>>;
32
- export declare function gunzipToString(buf: Buffer, options?: ZlibOptions): Promise<string>;
33
- export declare function zstdCompress(input: Buffer | string, level?: Integer, options?: ZstdOptions): Promise<Buffer<ArrayBuffer>>;
34
- export declare function zstdCompressSync(input: Buffer | string, level?: Integer, options?: ZstdOptions): Buffer<ArrayBuffer>;
35
- export declare function zstdLevelToOptions(level: Integer | undefined, opt?: ZstdOptions): ZstdOptions;
36
- export declare function zstdDecompressToString(input: Buffer, options?: ZstdOptions): Promise<string>;
37
- export declare function zstdDecompress(input: Buffer, options?: ZstdOptions): Promise<Buffer<ArrayBuffer>>;
38
- export declare function zstdDecompressToStringSync(input: Buffer, options?: ZstdOptions): string;
39
- export declare function zstdDecompressSync(input: Buffer, options?: ZstdOptions): Buffer<ArrayBuffer>;
40
- export declare function isZstdBuffer(input: Buffer): boolean;
41
- export declare function isGzipBuffer(input: Buffer): boolean;
@@ -1,99 +0,0 @@
1
- import { promisify } from 'node:util';
2
- import zlib from 'node:zlib';
3
- const deflate = promisify(zlib.deflate.bind(zlib));
4
- const inflate = promisify(zlib.inflate.bind(zlib));
5
- const gzip = promisify(zlib.gzip.bind(zlib));
6
- const gunzip = promisify(zlib.gunzip.bind(zlib));
7
- const zstdCompressAsync = promisify(zlib.zstdCompress.bind(zlib));
8
- const zstdDecompressAsync = promisify(zlib.zstdDecompress.bind(zlib));
9
- export async function decompressZstdOrInflateToString(buf) {
10
- return (await decompressZstdOrInflate(buf)).toString();
11
- }
12
- /**
13
- * Detects if Buffer is zstd-compressed.
14
- * Otherwise attempts to Inflate.
15
- */
16
- export async function decompressZstdOrInflate(buf) {
17
- if (isZstdBuffer(buf)) {
18
- return await zstdDecompressAsync(buf);
19
- }
20
- return await inflate(buf);
21
- }
22
- /**
23
- * deflateBuffer uses `deflate`.
24
- * It's 9 bytes shorter than `gzip`.
25
- */
26
- export async function deflateBuffer(buf, options = {}) {
27
- return await deflate(buf, options);
28
- }
29
- export async function inflateBuffer(buf, options = {}) {
30
- return await inflate(buf, options);
31
- }
32
- /**
33
- * deflateString uses `deflate`.
34
- * It's 9 bytes shorter than `gzip`.
35
- */
36
- export async function deflateString(s, options) {
37
- return await deflate(s, options);
38
- }
39
- export async function inflateToString(buf, options) {
40
- return (await inflateBuffer(buf, options)).toString();
41
- }
42
- /**
43
- * gzipBuffer uses `gzip`
44
- * It's 9 bytes longer than `deflate`.
45
- */
46
- export async function gzipBuffer(buf, options = {}) {
47
- return await gzip(buf, options);
48
- }
49
- export async function gunzipBuffer(buf, options = {}) {
50
- return await gunzip(buf, options);
51
- }
52
- /**
53
- * gzipString uses `gzip`.
54
- * It's 9 bytes longer than `deflate`.
55
- */
56
- export async function gzipString(s, options) {
57
- return await gzip(s, options);
58
- }
59
- export async function gunzipToString(buf, options) {
60
- return (await gunzipBuffer(buf, options)).toString();
61
- }
62
- export async function zstdCompress(input, level, // defaults to 3
63
- options = {}) {
64
- return await zstdCompressAsync(input, zstdLevelToOptions(level, options));
65
- }
66
- export function zstdCompressSync(input, level, // defaults to 3
67
- options = {}) {
68
- return zlib.zstdCompressSync(input, zstdLevelToOptions(level, options));
69
- }
70
- export function zstdLevelToOptions(level, opt = {}) {
71
- if (!level)
72
- return opt;
73
- return {
74
- ...opt,
75
- params: {
76
- ...opt.params,
77
- [zlib.constants.ZSTD_c_compressionLevel]: level,
78
- },
79
- };
80
- }
81
- export async function zstdDecompressToString(input, options = {}) {
82
- return (await zstdDecompressAsync(input, options)).toString();
83
- }
84
- export async function zstdDecompress(input, options = {}) {
85
- return await zstdDecompressAsync(input, options);
86
- }
87
- export function zstdDecompressToStringSync(input, options = {}) {
88
- return zlib.zstdDecompressSync(input, options).toString();
89
- }
90
- export function zstdDecompressSync(input, options = {}) {
91
- return zlib.zstdDecompressSync(input, options);
92
- }
93
- const ZSTD_MAGIC_NUMBER = 0xfd2fb528;
94
- export function isZstdBuffer(input) {
95
- return input.readUInt32LE(0) === ZSTD_MAGIC_NUMBER;
96
- }
97
- export function isGzipBuffer(input) {
98
- return input[0] === 0x1f && input[1] === 0x8b;
99
- }
@@ -1,61 +0,0 @@
1
- import { _hb } from '@naturalcycles/js-lib'
2
- import type { CommonLogger } from '@naturalcycles/js-lib/log'
3
- import { NumberStack } from '@naturalcycles/js-lib/math/stack.util.js'
4
- import { yellow } from '../colors/colors.js'
5
- import { gzipBuffer } from '../zip/zip.util.js'
6
-
7
- export class SizeStack extends NumberStack {
8
- constructor(
9
- public name: string,
10
- size: number,
11
- ) {
12
- super(size)
13
- }
14
-
15
- total = 0
16
-
17
- override push(item: any): this {
18
- this.total += item
19
- return super.push(item)
20
- }
21
-
22
- getStats(): string {
23
- // const pcs = this.percentiles([50, 90])
24
-
25
- return [
26
- ' ' + this.name,
27
- 'avg',
28
- yellow(_hb(this.avg())),
29
- // 'p50',
30
- // yellow(_hb(pcs[50])),
31
- // 'p90',
32
- // yellow(_hb(pcs[90])),
33
- 'total',
34
- yellow(_hb(this.total)),
35
- ].join(' ')
36
- }
37
-
38
- static async countItem(
39
- item: any,
40
- logger: CommonLogger,
41
- sizes?: SizeStack,
42
- sizesZipped?: SizeStack,
43
- ): Promise<void> {
44
- if (!sizes) return
45
-
46
- // try-catch, because we don't want to fail the pipeline on logProgress
47
- try {
48
- const buf = Buffer.from(JSON.stringify(item))
49
- sizes.push(buf.byteLength)
50
-
51
- if (sizesZipped) {
52
- const { byteLength } = await gzipBuffer(buf)
53
- sizesZipped.push(byteLength)
54
- }
55
- } catch (err) {
56
- logger.warn(
57
- `transformLogProgress failed to JSON.stringify the chunk: ${(err as Error).message}`,
58
- )
59
- }
60
- }
61
- }
@@ -1,149 +0,0 @@
1
- import { promisify } from 'node:util'
2
- import type { ZlibOptions, ZstdOptions } from 'node:zlib'
3
- import zlib from 'node:zlib'
4
- import type { Integer } from '@naturalcycles/js-lib/types'
5
-
6
- const deflate = promisify(zlib.deflate.bind(zlib))
7
- const inflate = promisify(zlib.inflate.bind(zlib))
8
- const gzip = promisify(zlib.gzip.bind(zlib))
9
- const gunzip = promisify(zlib.gunzip.bind(zlib))
10
- const zstdCompressAsync = promisify(zlib.zstdCompress.bind(zlib))
11
- const zstdDecompressAsync = promisify(zlib.zstdDecompress.bind(zlib))
12
-
13
- export async function decompressZstdOrInflateToString(buf: Buffer): Promise<string> {
14
- return (await decompressZstdOrInflate(buf)).toString()
15
- }
16
-
17
- /**
18
- * Detects if Buffer is zstd-compressed.
19
- * Otherwise attempts to Inflate.
20
- */
21
- export async function decompressZstdOrInflate(buf: Buffer): Promise<Buffer<ArrayBuffer>> {
22
- if (isZstdBuffer(buf)) {
23
- return await zstdDecompressAsync(buf)
24
- }
25
- return await inflate(buf)
26
- }
27
-
28
- /**
29
- * deflateBuffer uses `deflate`.
30
- * It's 9 bytes shorter than `gzip`.
31
- */
32
- export async function deflateBuffer(
33
- buf: Buffer,
34
- options: ZlibOptions = {},
35
- ): Promise<Buffer<ArrayBuffer>> {
36
- return await deflate(buf, options)
37
- }
38
-
39
- export async function inflateBuffer(
40
- buf: Buffer,
41
- options: ZlibOptions = {},
42
- ): Promise<Buffer<ArrayBuffer>> {
43
- return await inflate(buf, options)
44
- }
45
-
46
- /**
47
- * deflateString uses `deflate`.
48
- * It's 9 bytes shorter than `gzip`.
49
- */
50
- export async function deflateString(
51
- s: string,
52
- options?: ZlibOptions,
53
- ): Promise<Buffer<ArrayBuffer>> {
54
- return await deflate(s, options)
55
- }
56
-
57
- export async function inflateToString(buf: Buffer, options?: ZlibOptions): Promise<string> {
58
- return (await inflateBuffer(buf, options)).toString()
59
- }
60
-
61
- /**
62
- * gzipBuffer uses `gzip`
63
- * It's 9 bytes longer than `deflate`.
64
- */
65
- export async function gzipBuffer(
66
- buf: Buffer,
67
- options: ZlibOptions = {},
68
- ): Promise<Buffer<ArrayBuffer>> {
69
- return await gzip(buf, options)
70
- }
71
-
72
- export async function gunzipBuffer(
73
- buf: Buffer,
74
- options: ZlibOptions = {},
75
- ): Promise<Buffer<ArrayBuffer>> {
76
- return await gunzip(buf, options)
77
- }
78
-
79
- /**
80
- * gzipString uses `gzip`.
81
- * It's 9 bytes longer than `deflate`.
82
- */
83
- export async function gzipString(s: string, options?: ZlibOptions): Promise<Buffer<ArrayBuffer>> {
84
- return await gzip(s, options)
85
- }
86
-
87
- export async function gunzipToString(buf: Buffer, options?: ZlibOptions): Promise<string> {
88
- return (await gunzipBuffer(buf, options)).toString()
89
- }
90
-
91
- export async function zstdCompress(
92
- input: Buffer | string,
93
- level?: Integer, // defaults to 3
94
- options: ZstdOptions = {},
95
- ): Promise<Buffer<ArrayBuffer>> {
96
- return await zstdCompressAsync(input, zstdLevelToOptions(level, options))
97
- }
98
-
99
- export function zstdCompressSync(
100
- input: Buffer | string,
101
- level?: Integer, // defaults to 3
102
- options: ZstdOptions = {},
103
- ): Buffer<ArrayBuffer> {
104
- return zlib.zstdCompressSync(input, zstdLevelToOptions(level, options))
105
- }
106
-
107
- export function zstdLevelToOptions(level: Integer | undefined, opt: ZstdOptions = {}): ZstdOptions {
108
- if (!level) return opt
109
-
110
- return {
111
- ...opt,
112
- params: {
113
- ...opt.params,
114
- [zlib.constants.ZSTD_c_compressionLevel]: level,
115
- },
116
- }
117
- }
118
-
119
- export async function zstdDecompressToString(
120
- input: Buffer,
121
- options: ZstdOptions = {},
122
- ): Promise<string> {
123
- return (await zstdDecompressAsync(input, options)).toString()
124
- }
125
-
126
- export async function zstdDecompress(
127
- input: Buffer,
128
- options: ZstdOptions = {},
129
- ): Promise<Buffer<ArrayBuffer>> {
130
- return await zstdDecompressAsync(input, options)
131
- }
132
-
133
- export function zstdDecompressToStringSync(input: Buffer, options: ZstdOptions = {}): string {
134
- return zlib.zstdDecompressSync(input, options).toString()
135
- }
136
-
137
- export function zstdDecompressSync(input: Buffer, options: ZstdOptions = {}): Buffer<ArrayBuffer> {
138
- return zlib.zstdDecompressSync(input, options)
139
- }
140
-
141
- const ZSTD_MAGIC_NUMBER = 0xfd2fb528
142
-
143
- export function isZstdBuffer(input: Buffer): boolean {
144
- return input.readUInt32LE(0) === ZSTD_MAGIC_NUMBER
145
- }
146
-
147
- export function isGzipBuffer(input: Buffer): boolean {
148
- return input[0] === 0x1f && input[1] === 0x8b
149
- }