rac-delta 1.0.20 → 1.1.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.
@@ -65,6 +65,24 @@ export interface DownloadOptions {
65
65
  * Optinal callback for state changes.
66
66
  */
67
67
  onStateChange?: (state: 'downloading' | 'reconstructing' | 'cleaning' | 'scanning') => void;
68
+ /**
69
+ * AbortSignal for cooperative cancellation of the download.
70
+ *
71
+ * When aborted, the pipeline stops at the next safe checkpoint (between files
72
+ * or between chunks). Files already fully reconstructed on disk are kept.
73
+ * Any file that was mid-reconstruction has its .tmp discarded cleanly.
74
+ *
75
+ * On the next 'execute()' call, rac-delta will automatically diff the local
76
+ * directory against the remote index and only download what is still missing -
77
+ * effectively resuming from where it stopped.
78
+ *
79
+ * @example
80
+ * const controller = new AbortController();
81
+ * pipeline.execute(dir, strategy, index, { signal: controller.signal });
82
+ * // later:
83
+ * controller.abort();
84
+ */
85
+ signal?: Nullish<AbortSignal>;
68
86
  }
69
87
  export declare abstract class DownloadPipeline {
70
88
  protected updateProgress(value: number, state: 'download' | 'reconstructing' | 'deleting', diskUsage?: Nullish<number>, speed?: Nullish<number>, options?: Nullish<DownloadOptions>): void;
@@ -1 +1 @@
1
- {"version":3,"file":"download-pipeline.d.ts","sourceRoot":"","sources":["../../../src/core/pipelines/download-pipeline.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"download-pipeline.d.ts","sourceRoot":"","sources":["../../../src/core/pipelines/download-pipeline.ts"],"names":[],"mappings":"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"}
@@ -32,6 +32,12 @@ export interface ReconstructionOptions {
32
32
  * How many files will reconstruct concurrently (default value is 5)
33
33
  */
34
34
  fileConcurrency?: Nullish<number>;
35
+ /**
36
+ * AbortSignal for cooperative cancellation.
37
+ * Checked between files and between chunk writes.
38
+ * Any .tmp in progress is discarded cleanly before throwing.
39
+ */
40
+ signal?: Nullish<AbortSignal>;
35
41
  /**
36
42
  * Callback that returns disk usage and optional network speed (only for storage chunk sources via streaming download-reconstruction)
37
43
  *
@@ -1 +1 @@
1
- {"version":3,"file":"reconstruction-service.d.ts","sourceRoot":"","sources":["../../../src/core/services/reconstruction-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAElC,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAEnC,eAAO,MAAM,yCAAyC,QAAoB,CAAC;AAE3E,MAAM,WAAW,qBAAqB;IACpC;;OAEG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAEhC;;;OAGG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAEtC;;;;;;;;;;;;;;OAcG;IACH,8BAA8B,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAEjD;;OAEG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAElC;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,CACX,mBAAmB,EAAE,MAAM,EAC3B,SAAS,EAAE,MAAM,EACjB,eAAe,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,EACjC,YAAY,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,KAC3B,IAAI,CAAC;CACX;AAED,MAAM,WAAW,WAAW;IAC1B;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAExC;;OAEG;IACH,SAAS,CAAC,CACR,MAAM,EAAE,MAAM,EAAE,EAChB,OAAO,CAAC,EAAE,OAAO,CAAC;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,GAC1C,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAEhC;;;;;;;OAOG;IACH,YAAY,CAAC,CACX,MAAM,EAAE,MAAM,EAAE,EAChB,OAAO,CAAC,EAAE,OAAO,CAAC;QAAE,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,OAAO,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,GACzF,cAAc,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,QAAQ,CAAA;KAAE,CAAC,CAAC;CACrD;AAED,MAAM,WAAW,qBAAqB;IACpC;;;;;;;;OAQG;IACH,eAAe,CACb,KAAK,EAAE,SAAS,EAChB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,WAAW,EACxB,OAAO,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,GACvC,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjB;;;;;;;OAOG;IACH,cAAc,CACZ,IAAI,EAAE,SAAS,EACf,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,WAAW,EACxB,OAAO,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,GACvC,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjB;;;;;OAKG;IACH,mBAAmB,CAAC,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;CACpF"}
1
+ {"version":3,"file":"reconstruction-service.d.ts","sourceRoot":"","sources":["../../../src/core/services/reconstruction-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAElC,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAEnC,eAAO,MAAM,yCAAyC,QAAoB,CAAC;AAE3E,MAAM,WAAW,qBAAqB;IACpC;;OAEG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAEhC;;;OAGG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAEtC;;;;;;;;;;;;;;OAcG;IACH,8BAA8B,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAEjD;;OAEG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAElC;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;IAE9B;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,CACX,mBAAmB,EAAE,MAAM,EAC3B,SAAS,EAAE,MAAM,EACjB,eAAe,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,EACjC,YAAY,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,KAC3B,IAAI,CAAC;CACX;AAED,MAAM,WAAW,WAAW;IAC1B;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAExC;;OAEG;IACH,SAAS,CAAC,CACR,MAAM,EAAE,MAAM,EAAE,EAChB,OAAO,CAAC,EAAE,OAAO,CAAC;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,GAC1C,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAEhC;;;;;;;OAOG;IACH,YAAY,CAAC,CACX,MAAM,EAAE,MAAM,EAAE,EAChB,OAAO,CAAC,EAAE,OAAO,CAAC;QAAE,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,OAAO,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,GACzF,cAAc,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,QAAQ,CAAA;KAAE,CAAC,CAAC;CACrD;AAED,MAAM,WAAW,qBAAqB;IACpC;;;;;;;;OAQG;IACH,eAAe,CACb,KAAK,EAAE,SAAS,EAChB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,WAAW,EACxB,OAAO,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,GACvC,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjB;;;;;;;OAOG;IACH,cAAc,CACZ,IAAI,EAAE,SAAS,EACf,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,WAAW,EACxB,OAAO,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,GACvC,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjB;;;;;OAKG;IACH,mBAAmB,CAAC,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;CACpF"}
@@ -0,0 +1,13 @@
1
+ import { Nullish, UnknownAny } from '../types';
2
+ /**
3
+ * Throws an Abort exception if the given signal has been aborted.
4
+ * Use at the start of async operations and between loop iterations for cooperative
5
+ * cancellation via AbortController.
6
+ */
7
+ export declare function checkAbort(signal?: Nullish<AbortSignal>): void;
8
+ /**
9
+ * Returns true if the given error is an AbortError - i.e. the download was
10
+ * intentionally cancelled by the user, not a real failure.
11
+ */
12
+ export declare function isAbortError(err: UnknownAny): boolean;
13
+ //# sourceMappingURL=check-abort.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check-abort.d.ts","sourceRoot":"","sources":["../../../src/core/utils/check-abort.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE/C;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,IAAI,CAE9D;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAErD"}
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.checkAbort = checkAbort;
4
+ exports.isAbortError = isAbortError;
5
+ /**
6
+ * Throws an Abort exception if the given signal has been aborted.
7
+ * Use at the start of async operations and between loop iterations for cooperative
8
+ * cancellation via AbortController.
9
+ */
10
+ function checkAbort(signal) {
11
+ signal?.throwIfAborted();
12
+ }
13
+ /**
14
+ * Returns true if the given error is an AbortError - i.e. the download was
15
+ * intentionally cancelled by the user, not a real failure.
16
+ */
17
+ function isAbortError(err) {
18
+ return err?.name === 'AbortError';
19
+ }
@@ -1,3 +1,4 @@
1
1
  export * from './invariant';
2
2
  export * from './stream-to-buffer';
3
+ export * from './check-abort';
3
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC"}
@@ -16,3 +16,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./invariant"), exports);
18
18
  __exportStar(require("./stream-to-buffer"), exports);
19
+ __exportStar(require("./check-abort"), exports);
@@ -1 +1 @@
1
- {"version":3,"file":"default-hash-download-pipeline.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/pipelines/default-hash-download-pipeline.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC7F,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC7F,OAAO,EAAE,WAAW,EAAE,MAAM,4CAA4C,CAAC;AACzE,OAAO,EAAc,SAAS,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAEnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAM3C,qBAAa,2BAA4B,SAAQ,oBAAoB;IAEjE,SAAS,CAAC,QAAQ,CAAC,cAAc,EAAE,qBAAqB;IACxD,SAAS,CAAC,QAAQ,CAAC,UAAU,EAAE,iBAAiB;IAChD,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,kBAAkB;IAC9C,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,cAAc;IACzC,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,YAAY;gBAJnB,cAAc,EAAE,qBAAqB,EACrC,UAAU,EAAE,iBAAiB,EAC7B,OAAO,EAAE,kBAAkB,EAC3B,MAAM,EAAE,cAAc,EACtB,KAAK,EAAE,YAAY;IAKlC,OAAO,CACX,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,cAAc,EACxB,WAAW,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,EAC9B,OAAO,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,GACjC,OAAO,CAAC,IAAI,CAAC;IA8FV,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IASlD,wBAAwB,CAC5B,IAAI,EAAE,SAAS,EACf,MAAM,EAAE,QAAQ,GAAG,MAAM,EACzB,OAAO,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,GACjC,OAAO,CAAC,WAAW,CAAC;IAmEjB,6BAA6B,CACjC,IAAI,EAAE,SAAS,EACf,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,OAAO,EACpB,WAAW,EAAE,WAAW,EACxB,OAAO,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC;;;;;IA8C9B,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO;IAO/C,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAyB/D,OAAO,CAAC,WAAW;CAapB"}
1
+ {"version":3,"file":"default-hash-download-pipeline.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/pipelines/default-hash-download-pipeline.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC7F,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC7F,OAAO,EAAE,WAAW,EAAE,MAAM,4CAA4C,CAAC;AACzE,OAAO,EAAc,SAAS,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAEnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnD,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAM3C,qBAAa,2BAA4B,SAAQ,oBAAoB;IAEjE,SAAS,CAAC,QAAQ,CAAC,cAAc,EAAE,qBAAqB;IACxD,SAAS,CAAC,QAAQ,CAAC,UAAU,EAAE,iBAAiB;IAChD,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,kBAAkB;IAC9C,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,cAAc;IACzC,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,YAAY;gBAJnB,cAAc,EAAE,qBAAqB,EACrC,UAAU,EAAE,iBAAiB,EAC7B,OAAO,EAAE,kBAAkB,EAC3B,MAAM,EAAE,cAAc,EACtB,KAAK,EAAE,YAAY;IAKlC,OAAO,CACX,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,cAAc,EACxB,WAAW,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,EAC9B,OAAO,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,GACjC,OAAO,CAAC,IAAI,CAAC;IA0GV,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IASlD,wBAAwB,CAC5B,IAAI,EAAE,SAAS,EACf,MAAM,EAAE,QAAQ,GAAG,MAAM,EACzB,OAAO,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,GACjC,OAAO,CAAC,WAAW,CAAC;IAqEjB,6BAA6B,CACjC,IAAI,EAAE,SAAS,EACf,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,OAAO,EACpB,WAAW,EAAE,WAAW,EACxB,OAAO,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC;;;;;IAgD9B,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO;IAO/C,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAyB/D,OAAO,CAAC,WAAW;CAapB"}
@@ -5,6 +5,7 @@ const promises_1 = require("fs/promises");
5
5
  const path_1 = require("path");
6
6
  const pipelines_1 = require("../../core/pipelines");
7
7
  const stream_to_buffer_1 = require("../../core/utils/stream-to-buffer");
8
+ const utils_1 = require("../../core/utils");
8
9
  const storage_chunk_source_1 = require("../chunk-sources/storage-chunk-source");
9
10
  const memory_chunk_source_1 = require("../chunk-sources/memory-chunk-source");
10
11
  const disk_chunk_source_1 = require("../chunk-sources/disk-chunk-source");
@@ -24,6 +25,7 @@ class DefaultHashDownloadPipeline extends pipelines_1.HashDownloadPipeline {
24
25
  }
25
26
  async execute(localDir, strategy, remoteIndex, options) {
26
27
  try {
28
+ (0, utils_1.checkAbort)(options?.signal);
27
29
  this.changeState('scanning', options);
28
30
  const localIndex = !options?.force
29
31
  ? options?.useExistingIndex
@@ -42,6 +44,7 @@ class DefaultHashDownloadPipeline extends pipelines_1.HashDownloadPipeline {
42
44
  console.info('No changes to download, you are up to date.');
43
45
  return;
44
46
  }
47
+ (0, utils_1.checkAbort)(options?.signal);
45
48
  let chunkSource = null;
46
49
  if (strategy === pipelines_1.UpdateStrategy.DownloadAllFirstToMemory) {
47
50
  this.changeState('downloading', options);
@@ -59,12 +62,14 @@ class DefaultHashDownloadPipeline extends pipelines_1.HashDownloadPipeline {
59
62
  throw new Error('No chunkSource found');
60
63
  }
61
64
  if (plan.newAndModifiedFiles.length) {
65
+ (0, utils_1.checkAbort)(options?.signal);
62
66
  this.changeState('reconstructing', options);
63
67
  await this.reconstruction.reconstructAll(plan, localDir, chunkSource, {
64
68
  forceRebuild: options?.force,
65
69
  verifyAfterRebuild: true,
66
70
  fileConcurrency: options?.fileReconstructionConcurrency,
67
71
  inPlaceReconstructionThreshold: options?.inPlaceReconstructionThreshold,
72
+ signal: options?.signal,
68
73
  onProgress: (reconstructProgress, diskSpeed, networkProgress, networkSpeed) => {
69
74
  this.updateProgress(reconstructProgress, 'reconstructing', diskSpeed, undefined, options);
70
75
  if (networkProgress) {
@@ -74,6 +79,7 @@ class DefaultHashDownloadPipeline extends pipelines_1.HashDownloadPipeline {
74
79
  });
75
80
  }
76
81
  if (plan.obsoleteChunks.length || plan.deletedFiles.length) {
82
+ (0, utils_1.checkAbort)(options?.signal);
77
83
  this.changeState('cleaning', options);
78
84
  await this.verifyAndDeleteObsoleteChunks(plan, localDir, remoteIndexToUse, chunkSource, options);
79
85
  }
@@ -111,6 +117,7 @@ class DefaultHashDownloadPipeline extends pipelines_1.HashDownloadPipeline {
111
117
  let speed = 0;
112
118
  const worker = async () => {
113
119
  while (queue.length) {
120
+ (0, utils_1.checkAbort)(options?.signal);
114
121
  const chunk = queue.pop();
115
122
  const readable = await this.storage.getChunk(chunk.hash);
116
123
  if (!readable) {
@@ -150,6 +157,7 @@ class DefaultHashDownloadPipeline extends pipelines_1.HashDownloadPipeline {
150
157
  const totalFiles = allFiles.size;
151
158
  let completedFiles = 0;
152
159
  for (const filePath of allFiles) {
160
+ (0, utils_1.checkAbort)(options?.signal);
153
161
  const absPath = (0, path_1.join)(dir, filePath);
154
162
  const remoteFile = remoteIndex.files.find((file) => file.path === filePath);
155
163
  // Fully removed file
@@ -1 +1 @@
1
- {"version":3,"file":"memory-delta-service.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/services/memory-delta-service.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpF,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAqB,MAAM,mBAAmB,CAAC;AAErF,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAE3C,qBAAa,kBAAmB,YAAW,YAAY;IACzC,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,aAAa;IAE5C,wBAAwB,CAC5B,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,WAAW,SAAI,EACf,cAAc,CAAC,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,GACjC,OAAO,CAAC,OAAO,CAAC;IA8Cb,yBAAyB,CAC7B,MAAM,EAAE,gBAAgB,EACxB,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,SAAS,CAAC;YAwBN,SAAS;IAuBxB,OAAO,CAAC,iBAAiB;IAYzB,OAAO,CAAC,WAAW;IAanB,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI,GAAG,SAAS;IAiE3D,UAAU,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,GAAG,SAAS;IA0CpD,gBAAgB,CAAC,UAAU,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,GAAG,IAAI,GAAG,OAAO,CAAC,SAAS,CAAC;IAkBtF,kBAAkB,CAAC,UAAU,EAAE,OAAO,GAAG,IAAI,EAAE,WAAW,EAAE,OAAO,GAAG,OAAO,CAAC,SAAS,CAAC;CAG/F"}
1
+ {"version":3,"file":"memory-delta-service.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/services/memory-delta-service.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpF,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAqB,MAAM,mBAAmB,CAAC;AAErF,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAE3C,qBAAa,kBAAmB,YAAW,YAAY;IACzC,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,aAAa;IAE5C,wBAAwB,CAC5B,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,WAAW,SAAI,EACf,cAAc,CAAC,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,GACjC,OAAO,CAAC,OAAO,CAAC;IA8Cb,yBAAyB,CAC7B,MAAM,EAAE,gBAAgB,EACxB,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,SAAS,CAAC;YAwBN,SAAS;IAuBxB,OAAO,CAAC,iBAAiB;IAYzB,OAAO,CAAC,WAAW;IAanB,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI,GAAG,SAAS;IAsE3D,UAAU,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,GAAG,SAAS;IA0CpD,gBAAgB,CAAC,UAAU,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,GAAG,IAAI,GAAG,OAAO,CAAC,SAAS,CAAC;IAkBtF,kBAAkB,CAAC,UAAU,EAAE,OAAO,GAAG,IAAI,EAAE,WAAW,EAAE,OAAO,GAAG,OAAO,CAAC,SAAS,CAAC;CAG/F"}
@@ -131,13 +131,17 @@ class MemoryDeltaService {
131
131
  const targetChunks = new Map(targetFile.chunks.map((c) => [`${c.hash}@${c.offset}`, c]));
132
132
  const sourceChunkKeys = new Set(srcFile.chunks.map((c) => `${c.hash}@${c.offset}`));
133
133
  // File exists -> compare chunks
134
+ let fileModified = false;
134
135
  for (const chunk of srcFile.chunks) {
135
136
  const key = `${chunk.hash}@${chunk.offset}`;
136
137
  if (!targetChunks.has(key)) {
137
138
  deltaPlan.missingChunks.push({ ...chunk, filePath: srcFile.path });
138
- deltaPlan.newAndModifiedFiles.push(srcFile);
139
+ fileModified = true;
139
140
  }
140
141
  }
142
+ if (fileModified) {
143
+ deltaPlan.newAndModifiedFiles.push(srcFile);
144
+ }
141
145
  // Check obsolete chunks in target that are not in source
142
146
  for (const chunk of targetFile.chunks) {
143
147
  const key = `${chunk.hash}@${chunk.offset}`;
@@ -1 +1 @@
1
- {"version":3,"file":"memory-reconstruction-service.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/services/memory-reconstruction-service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAyB,MAAM,QAAQ,CAAC;AAIzD,OAAO,EACL,WAAW,EAEX,aAAa,EACb,qBAAqB,EACrB,qBAAqB,EACtB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,SAAS,EAAE,SAAS,EAAS,MAAM,mBAAmB,CAAC;AAEhE,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAE3C,qBAAa,2BAA4B,YAAW,qBAAqB;IAC3D,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,aAAa;IAE5C,cAAc,CAClB,IAAI,EAAE,SAAS,EACf,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,WAAW,EACxB,OAAO,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,GACvC,OAAO,CAAC,IAAI,CAAC;IAmFV,eAAe,CACnB,KAAK,EAAE,SAAS,EAChB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,WAAW,EACxB,OAAO,GAAE,qBAIR,GACA,OAAO,CAAC,IAAI,CAAC;IAgDV,mBAAmB,CAAC,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC;YA8C1E,UAAU;IASxB,oEAAoE;YACtD,kBAAkB;IAiChC,oFAAoF;YACtE,iBAAiB;IAmF/B;;;OAGG;YACW,qBAAqB;YA2BrB,YAAY;YAcZ,aAAa;YAyCZ,gBAAgB;CAmChC"}
1
+ {"version":3,"file":"memory-reconstruction-service.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/services/memory-reconstruction-service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAyB,MAAM,QAAQ,CAAC;AAIzD,OAAO,EACL,WAAW,EAEX,aAAa,EACb,qBAAqB,EACrB,qBAAqB,EACtB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,SAAS,EAAE,SAAS,EAAS,MAAM,mBAAmB,CAAC;AAEhE,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAE3C,qBAAa,2BAA4B,YAAW,qBAAqB;IAC3D,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,aAAa;IAE5C,cAAc,CAClB,IAAI,EAAE,SAAS,EACf,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,WAAW,EACxB,OAAO,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,GACvC,OAAO,CAAC,IAAI,CAAC;IAgGV,eAAe,CACnB,KAAK,EAAE,SAAS,EAChB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,WAAW,EACxB,OAAO,GAAE,qBAIR,GACA,OAAO,CAAC,IAAI,CAAC;IAyDV,mBAAmB,CAAC,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC;YA8C1E,UAAU;IASxB,oEAAoE;YACtD,kBAAkB;IAoChC,oFAAoF;YACtE,iBAAiB;IA8F/B;;;OAGG;YACW,qBAAqB;YA2BrB,YAAY;YAcZ,aAAa;YAyCZ,gBAAgB;CAmChC"}
@@ -17,6 +17,7 @@ class MemoryReconstructionService {
17
17
  async reconstructAll(plan, outputDir, chunkSource, options) {
18
18
  const dir = (0, path_1.isAbsolute)(outputDir) ? outputDir : (0, path_1.resolve)(process.cwd(), outputDir);
19
19
  await (0, promises_1.mkdir)(dir, { recursive: true });
20
+ const activePaths = new Set();
20
21
  const files = [...plan.newAndModifiedFiles];
21
22
  const total = files.length;
22
23
  let completed = 0;
@@ -33,8 +34,14 @@ class MemoryReconstructionService {
33
34
  const totalBytesToWrite = files.reduce((accumulator, file) => accumulator + (file.size ?? 0), 0);
34
35
  const next = async () => {
35
36
  while (queue.length && !error) {
37
+ (0, utils_1.checkAbort)(options?.signal);
36
38
  const { entry } = queue.shift();
37
39
  const outputPath = (0, path_1.join)(dir, entry.path);
40
+ if (activePaths.has(outputPath)) {
41
+ queue.push({ entry, index: 0 });
42
+ continue;
43
+ }
44
+ activePaths.add(outputPath);
38
45
  try {
39
46
  await this.reconstructFile(entry, outputPath, chunkSource, {
40
47
  ...options,
@@ -66,6 +73,9 @@ class MemoryReconstructionService {
66
73
  error = err instanceof Error ? err : new Error(String(err));
67
74
  break;
68
75
  }
76
+ finally {
77
+ activePaths.delete(outputPath);
78
+ }
69
79
  }
70
80
  };
71
81
  const workers = Array.from({ length: Math.min(options?.fileConcurrency ?? 5, total) }, next);
@@ -99,14 +109,17 @@ class MemoryReconstructionService {
99
109
  };
100
110
  try {
101
111
  if (existingLargeFileWithoutRebuild && inPlaceReconstructionThreshold !== 0) {
102
- await this.reconstructInPlace(entry, defOutputPath, chunkSource, progressCb);
112
+ await this.reconstructInPlace(entry, defOutputPath, chunkSource, options.signal, progressCb);
103
113
  }
104
114
  else {
105
- await this.reconstructToTemp(entry, defOutputPath, tempPath, chunkSource, !!verifyAfterRebuild, exists, !!options.forceRebuild, progressCb);
115
+ await this.reconstructToTemp(entry, defOutputPath, tempPath, chunkSource, !!verifyAfterRebuild, exists, !!options.forceRebuild, options.signal, progressCb);
106
116
  }
107
117
  }
108
118
  catch (err) {
109
- await (0, promises_1.rm)(tempPath, { force: true });
119
+ try {
120
+ await (0, promises_1.rm)(tempPath, { force: true });
121
+ }
122
+ catch { }
110
123
  throw err;
111
124
  }
112
125
  }
@@ -161,13 +174,14 @@ class MemoryReconstructionService {
161
174
  }
162
175
  }
163
176
  /** Performs partial reconstruction directly in the existing file */
164
- async reconstructInPlace(entry, outputPath, chunkSource, progressCb) {
177
+ async reconstructInPlace(entry, outputPath, chunkSource, signal, progressCb) {
165
178
  const fd = await (0, promises_1.open)(outputPath, 'r+');
166
179
  const isNetworkSource = typeof chunkSource.streamChunks === 'function';
167
180
  try {
168
181
  const chunkMap = new Map(entry.chunks.map((c) => [c.hash, c]));
169
182
  let processed = 0;
170
183
  for await (const { hash, data } of this.fetchChunksSmart(entry.chunks, chunkSource, false)) {
184
+ (0, utils_1.checkAbort)(signal);
171
185
  const chunk = chunkMap.get(hash);
172
186
  if (!chunk) {
173
187
  continue;
@@ -184,7 +198,8 @@ class MemoryReconstructionService {
184
198
  }
185
199
  }
186
200
  /** Reconstructs file fully or partially via .tmp file and replaces it atomically */
187
- async reconstructToTemp(entry, outputPath, tempPath, chunkSource, verifyAfterRebuild, fileExists, force, progressCb) {
201
+ async reconstructToTemp(entry, outputPath, tempPath, chunkSource, verifyAfterRebuild, fileExists, force, signal, progressCb) {
202
+ await (0, promises_1.mkdir)((0, path_1.dirname)(tempPath), { recursive: true });
188
203
  const writeStream = (0, fs_1.createWriteStream)(tempPath, { flags: 'w' });
189
204
  let writeError = null;
190
205
  const onWriteError = (err) => {
@@ -199,6 +214,7 @@ class MemoryReconstructionService {
199
214
  const readFd = await (0, promises_1.open)(outputPath, 'r');
200
215
  try {
201
216
  for (const chunk of entry.chunks) {
217
+ (0, utils_1.checkAbort)(signal);
202
218
  await this.processChunkDataSmart(chunk, readFd, chunkSource, writeStream);
203
219
  processed++;
204
220
  progressCb?.(chunk.size, 0, processed);
@@ -212,6 +228,7 @@ class MemoryReconstructionService {
212
228
  if (!fileExists || force) {
213
229
  try {
214
230
  for await (const { data } of this.fetchChunksSmart(entry.chunks, chunkSource)) {
231
+ (0, utils_1.checkAbort)(signal);
215
232
  let totalWritten = 0;
216
233
  await this.writeToStream(data, writeStream, (totalBytes) => {
217
234
  totalWritten = totalBytes;
@@ -227,10 +244,6 @@ class MemoryReconstructionService {
227
244
  writeStream.destroy();
228
245
  throw err;
229
246
  }
230
- finally {
231
- writeStream.removeListener('error', onWriteError);
232
- writeStream.end();
233
- }
234
247
  }
235
248
  writeStream.end();
236
249
  await new Promise((resolve, reject) => {
@@ -246,8 +259,16 @@ class MemoryReconstructionService {
246
259
  await (0, promises_1.rename)(tempPath, outputPath);
247
260
  }
248
261
  catch (err) {
262
+ try {
263
+ writeStream.destroy();
264
+ await (0, promises_1.rm)(tempPath, { force: true });
265
+ }
266
+ catch { }
249
267
  throw err;
250
268
  }
269
+ finally {
270
+ writeStream.removeListener('error', onWriteError);
271
+ }
251
272
  }
252
273
  /**
253
274
  * Tries to read an existing chunk from a file descriptor if possible.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "rac-delta",
3
3
  "description": "Storage agnostic delta patching implementation of rac-delta protocol for NodeJs. With streaming support and file reconstruction.",
4
- "version": "1.0.20",
4
+ "version": "1.1.0",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "repository": {