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.
- package/dist/core/pipelines/download-pipeline.d.ts +18 -0
- package/dist/core/pipelines/download-pipeline.d.ts.map +1 -1
- package/dist/core/services/reconstruction-service.d.ts +6 -0
- package/dist/core/services/reconstruction-service.d.ts.map +1 -1
- package/dist/core/utils/check-abort.d.ts +13 -0
- package/dist/core/utils/check-abort.d.ts.map +1 -0
- package/dist/core/utils/check-abort.js +19 -0
- package/dist/core/utils/index.d.ts +1 -0
- package/dist/core/utils/index.d.ts.map +1 -1
- package/dist/core/utils/index.js +1 -0
- package/dist/infrastructure/pipelines/default-hash-download-pipeline.d.ts.map +1 -1
- package/dist/infrastructure/pipelines/default-hash-download-pipeline.js +8 -0
- package/dist/infrastructure/services/memory-delta-service.d.ts.map +1 -1
- package/dist/infrastructure/services/memory-delta-service.js +5 -1
- package/dist/infrastructure/services/memory-reconstruction-service.d.ts.map +1 -1
- package/dist/infrastructure/services/memory-reconstruction-service.js +30 -9
- package/package.json +1 -1
|
@@ -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":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAClG,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACpE,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAEnC,oBAAY,cAAc;IACxB;;;;;OAKG;IACH,wBAAwB,iCAAiC;IAEzD;;;OAGG;IACH,iBAAiB,wBAAwB;IAEzC;;;OAGG;IACH,sBAAsB,+BAA+B;CACtD;AAED,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAEzB;;OAEG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAEjC;;;OAGG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAEpC;;OAEG;IACH,6BAA6B,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAEhD;;;;;;;;;;;;;;OAcG;IACH,8BAA8B,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAEjD;;OAEG;IACH,UAAU,CAAC,EAAE,CACX,IAAI,EAAE,UAAU,GAAG,UAAU,GAAG,gBAAgB,EAChD,QAAQ,EAAE,MAAM,EAChB,SAAS,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,EAC3B,KAAK,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,KACpB,IAAI,CAAC;IAEV;;OAEG;IACH,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,GAAG,gBAAgB,GAAG,UAAU,GAAG,UAAU,KAAK,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"download-pipeline.d.ts","sourceRoot":"","sources":["../../../src/core/pipelines/download-pipeline.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAClG,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACpE,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAEnC,oBAAY,cAAc;IACxB;;;;;OAKG;IACH,wBAAwB,iCAAiC;IAEzD;;;OAGG;IACH,iBAAiB,wBAAwB;IAEzC;;;OAGG;IACH,sBAAsB,+BAA+B;CACtD;AAED,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAEzB;;OAEG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAEjC;;;OAGG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAEpC;;OAEG;IACH,6BAA6B,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAEhD;;;;;;;;;;;;;;OAcG;IACH,8BAA8B,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAEjD;;OAEG;IACH,UAAU,CAAC,EAAE,CACX,IAAI,EAAE,UAAU,GAAG,UAAU,GAAG,gBAAgB,EAChD,QAAQ,EAAE,MAAM,EAChB,SAAS,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,EAC3B,KAAK,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,KACpB,IAAI,CAAC;IAEV;;OAEG;IACH,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,GAAG,gBAAgB,GAAG,UAAU,GAAG,UAAU,KAAK,IAAI,CAAC;IAE5F;;;;;;;;;;;;;;;;OAgBG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;CAC/B;AAED,8BAAsB,gBAAgB;IACpC,SAAS,CAAC,cAAc,CACtB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,UAAU,GAAG,gBAAgB,GAAG,UAAU,EACjD,SAAS,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,EAC3B,KAAK,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,EACvB,OAAO,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC;IAKpC,SAAS,CAAC,WAAW,CACnB,KAAK,EAAE,aAAa,GAAG,gBAAgB,GAAG,UAAU,GAAG,UAAU,EACjE,OAAO,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC;IAKpC;;;;OAIG;IACH,QAAQ,CAAC,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAEtD;;;;OAIG;IACH,QAAQ,CAAC,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAElE;;;;;OAKG;IACH,QAAQ,CAAC,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAExE;;;;;;;;OAQG;IACH,QAAQ,CAAC,6BAA6B,CACpC,IAAI,EAAE,SAAS,EACf,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,OAAO,EACpB,WAAW,EAAE,WAAW,EACxB,OAAO,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,GACjC,OAAO,CAAC;QAAE,YAAY,EAAE,MAAM,EAAE,CAAC;QAAC,aAAa,EAAE,MAAM,EAAE,CAAC;QAAC,YAAY,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;CACxF;AAED,8BAAsB,oBAAqB,SAAQ,gBAAgB;IAE/D,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,kBAAkB;IAC9C,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,YAAY;IACtC,SAAS,CAAC,QAAQ,CAAC,cAAc,EAAE,qBAAqB;IACxD,SAAS,CAAC,QAAQ,CAAC,UAAU,EAAE,iBAAiB;IAChD,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,cAAc;gBAJtB,OAAO,EAAE,kBAAkB,EAC3B,KAAK,EAAE,YAAY,EACnB,cAAc,EAAE,qBAAqB,EACrC,UAAU,EAAE,iBAAiB,EAC7B,MAAM,EAAE,cAAc;IAK3C,QAAQ,CAAC,OAAO,CACd,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;IAEhB;;;;;;;;;;;;OAYG;IACH,QAAQ,CAAC,wBAAwB,CAC/B,IAAI,EAAE,SAAS,EACf,MAAM,EAAE,QAAQ,GAAG,MAAM,EACzB,OAAO,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,GACjC,OAAO,CAAC,WAAW,CAAC;CACxB;AAED,8BAAsB,mBAAoB,SAAQ,gBAAgB;IAE9D,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,iBAAiB;IAC7C,SAAS,CAAC,QAAQ,CAAC,cAAc,EAAE,qBAAqB;IACxD,SAAS,CAAC,QAAQ,CAAC,UAAU,EAAE,iBAAiB;IAChD,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,YAAY;IACtC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,cAAc;gBAJtB,OAAO,EAAE,iBAAiB,EAC1B,cAAc,EAAE,qBAAqB,EACrC,UAAU,EAAE,iBAAiB,EAC7B,KAAK,EAAE,YAAY,EACnB,MAAM,EAAE,cAAc;IAK3C,QAAQ,CAAC,OAAO,CACd,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE;QACJ,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;QAC3C,QAAQ,EAAE,MAAM,CAAC;KAClB,EACD,QAAQ,EAAE,cAAc,EACxB,IAAI,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,EACzB,OAAO,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,GACjC,OAAO,CAAC,IAAI,CAAC;IAChB,QAAQ,CAAC,wBAAwB,CAC/B,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,EAC1C,MAAM,EAAE,QAAQ,GAAG,MAAM,EACzB,OAAO,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,GACjC,OAAO,CAAC,WAAW,CAAC;CACxB"}
|
|
@@ -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 +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"}
|
package/dist/core/utils/index.js
CHANGED
|
@@ -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;
|
|
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;
|
|
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
|
-
|
|
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;
|
|
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
|
-
|
|
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
|
|
4
|
+
"version": "1.1.0",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"repository": {
|