core-3nweb-client-lib 0.25.5 → 0.26.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/build/api-defs/files.d.ts +23 -20
- package/build/core/asmail/config/common.js +2 -2
- package/build/core/asmail/delivery/index.js +4 -3
- package/build/core/asmail/delivery/msg.js +5 -4
- package/build/core/asmail/delivery/per-recipient-wip.js +2 -2
- package/build/core/asmail/inbox/attachments/fs.js +6 -0
- package/build/core/asmail/inbox/cached-msgs.js +2 -2
- package/build/core/asmail/inbox/inbox-events.js +2 -1
- package/build/core/asmail/inbox/index.js +2 -2
- package/build/core/asmail/inbox/msg-downloader.js +2 -2
- package/build/core/asmail/inbox/msg-indexing.js +3 -3
- package/build/core/asmail/inbox/msg-on-disk.js +2 -2
- package/build/core/asmail/keyring/keyring-storage.js +2 -2
- package/build/core/asmail/sending-params/own-params.js +2 -2
- package/build/core/asmail/sending-params/params-from-others.js +2 -2
- package/build/core/id-manager.js +2 -2
- package/build/core/sign-in.d.ts +5 -4
- package/build/core/sign-in.js +9 -11
- package/build/core/sign-up.d.ts +1 -0
- package/build/core/sign-up.js +7 -3
- package/build/core/storage/common/json-saving.d.ts +21 -0
- package/build/core/storage/common/json-saving.js +82 -0
- package/build/core/storage/common/obj-info-file.d.ts +43 -0
- package/build/core/storage/common/obj-info-file.js +119 -3
- package/build/core/storage/index.js +1 -1
- package/build/core/storage/local/obj-files-gc.js +8 -6
- package/build/core/storage/local/obj-files.d.ts +3 -3
- package/build/core/storage/local/obj-files.js +9 -9
- package/build/core/storage/local/obj-status.d.ts +9 -25
- package/build/core/storage/local/obj-status.js +28 -110
- package/build/core/storage/local/storage.d.ts +8 -1
- package/build/core/storage/local/storage.js +10 -2
- package/build/core/storage/synced/downloader.js +6 -5
- package/build/core/storage/synced/obj-files-gc.d.ts +1 -0
- package/build/core/storage/synced/obj-files-gc.js +44 -5
- package/build/core/storage/synced/obj-files.d.ts +13 -20
- package/build/core/storage/synced/obj-files.js +70 -48
- package/build/core/storage/synced/obj-status.d.ts +74 -15
- package/build/core/storage/synced/obj-status.js +291 -107
- package/build/core/storage/synced/remote-events.js +32 -26
- package/build/core/storage/synced/storage.d.ts +11 -1
- package/build/core/storage/synced/storage.js +28 -3
- package/build/core/storage/synced/upsyncer.d.ts +8 -7
- package/build/core/storage/synced/upsyncer.js +211 -163
- package/build/ipc-via-protobuf/asmail-cap.js +17 -34
- package/build/ipc-via-protobuf/connector-clients-side.d.ts +2 -0
- package/build/ipc-via-protobuf/connector-clients-side.js +50 -12
- package/build/ipc-via-protobuf/file.js +26 -18
- package/build/ipc-via-protobuf/fs.js +33 -35
- package/build/ipc-via-protobuf/mailerid.js +3 -2
- package/build/ipc-via-protobuf/protobuf-msg.d.ts +2 -0
- package/build/ipc-via-protobuf/protobuf-msg.js +11 -1
- package/build/ipc-via-protobuf/startup-cap.js +5 -5
- package/build/lib-client/3nstorage/exceptions.d.ts +9 -8
- package/build/lib-client/3nstorage/exceptions.js +18 -9
- package/build/lib-client/3nstorage/service.js +10 -6
- package/build/lib-client/3nstorage/xsp-fs/common.d.ts +18 -4
- package/build/lib-client/3nstorage/xsp-fs/common.js +6 -1
- package/build/lib-client/3nstorage/xsp-fs/file-node.js +3 -3
- package/build/lib-client/3nstorage/xsp-fs/file.js +4 -1
- package/build/lib-client/3nstorage/xsp-fs/folder-node.js +27 -13
- package/build/lib-client/3nstorage/xsp-fs/fs.d.ts +11 -6
- package/build/lib-client/3nstorage/xsp-fs/fs.js +189 -58
- package/build/lib-client/3nstorage/xsp-fs/node-in-fs.d.ts +4 -0
- package/build/lib-client/3nstorage/xsp-fs/node-in-fs.js +51 -24
- package/build/lib-client/3nstorage/xsp-fs/node-persistence.js +2 -2
- package/build/lib-client/3nstorage/xsp-fs/xsp-payload-v1.js +2 -2
- package/build/lib-client/3nstorage/xsp-fs/xsp-payload-v2.js +3 -3
- package/build/lib-client/cryptor/cryptor-in-worker.js +4 -4
- package/build/lib-client/cryptor/cryptor-wasm.js +1 -1
- package/build/lib-client/cryptor/cryptor.wasm +0 -0
- package/build/lib-client/cryptor/in-proc-wasm.js +2 -2
- package/build/lib-client/files.js +2 -0
- package/build/lib-client/fs-collection.js +3 -2
- package/build/lib-client/logging/log-to-file.js +4 -4
- package/build/lib-client/objs-on-disk/file-writing-proc.js +2 -2
- package/build/lib-client/objs-on-disk/obj-folders.js +2 -2
- package/build/lib-client/request-utils.js +2 -2
- package/build/lib-client/server-events.js +4 -3
- package/build/lib-client/ws-utils.js +2 -2
- package/build/lib-common/async-fs-node.js +4 -3
- package/build/lib-common/byte-streaming/wrapping.js +17 -17
- package/build/lib-common/exceptions/file.js +6 -1
- package/build/lib-common/ipc/generic-ipc.js +2 -2
- package/build/lib-common/json-utils.js +2 -1
- package/build/lib-common/objs-on-disk/obj-file.js +4 -3
- package/build/lib-common/objs-on-disk/utils.js +2 -2
- package/build/lib-common/processes/deferred.d.ts +6 -0
- package/build/lib-common/processes/deferred.js +30 -0
- package/build/lib-common/processes/labelled-exec-pools.d.ts +33 -0
- package/build/lib-common/processes/labelled-exec-pools.js +141 -0
- package/build/lib-common/processes/pressure.d.ts +7 -0
- package/build/lib-common/processes/pressure.js +56 -0
- package/build/lib-common/processes/sleep.d.ts +1 -0
- package/build/lib-common/processes/sleep.js +26 -0
- package/build/lib-common/{processes.d.ts → processes/synced.d.ts} +0 -40
- package/build/lib-common/{processes.js → processes/synced.js} +187 -204
- package/build/lib-common/processes/timeout.d.ts +1 -0
- package/build/lib-common/processes/timeout.js +51 -0
- package/build/lib-common/service-api/3nstorage/owner.d.ts +5 -4
- package/build/lib-common/service-api/3nstorage/owner.js +3 -2
- package/build/lib-common/utils-for-observables.d.ts +15 -1
- package/build/lib-common/utils-for-observables.js +68 -17
- package/build/protos/asmail.proto.js +404 -78
- package/build/protos/file.proto.js +370 -44
- package/build/protos/fs.proto.js +404 -78
- package/package.json +4 -4
- package/protos/file.proto +10 -2
- package/protos/fs.proto +2 -2
- package/build/core/storage/synced/upsync-status.d.ts +0 -41
- package/build/core/storage/synced/upsync-status.js +0 -158
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/*
|
|
3
|
-
Copyright (C) 2020 3NSoft Inc.
|
|
3
|
+
Copyright (C) 2020, 2022 3NSoft Inc.
|
|
4
4
|
|
|
5
5
|
This program is free software: you can redistribute it and/or modify it under
|
|
6
6
|
the terms of the GNU General Public License as published by the Free Software
|
|
@@ -13,10 +13,13 @@
|
|
|
13
13
|
See the GNU General Public License for more details.
|
|
14
14
|
|
|
15
15
|
You should have received a copy of the GNU General Public License along with
|
|
16
|
-
this program. If not, see <http://www.gnu.org/licenses/>.
|
|
16
|
+
this program. If not, see <http://www.gnu.org/licenses/>.
|
|
17
|
+
*/
|
|
17
18
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
19
|
exports.GC = void 0;
|
|
19
|
-
const
|
|
20
|
+
const synced_1 = require("../../../lib-common/processes/synced");
|
|
21
|
+
const fs = require("../../../lib-common/async-fs-node");
|
|
22
|
+
const path_1 = require("path");
|
|
20
23
|
class GC {
|
|
21
24
|
constructor(sync, rmObjFromCache, rmObjFolder) {
|
|
22
25
|
this.sync = sync;
|
|
@@ -26,7 +29,7 @@ class GC {
|
|
|
26
29
|
/**
|
|
27
30
|
* All gc steps are done in this process.
|
|
28
31
|
*/
|
|
29
|
-
this.gcProc = new
|
|
32
|
+
this.gcProc = new synced_1.SingleProc();
|
|
30
33
|
/**
|
|
31
34
|
* wip are objects that are currently processed. When wip set is empty,
|
|
32
35
|
* it gets swapped with non-empty scheduled set.
|
|
@@ -55,7 +58,7 @@ class GC {
|
|
|
55
58
|
if (!obj) {
|
|
56
59
|
return;
|
|
57
60
|
}
|
|
58
|
-
|
|
61
|
+
await this.sync(obj.objId, () => this.collectIn(obj).catch(noop));
|
|
59
62
|
return this.objCollecting();
|
|
60
63
|
};
|
|
61
64
|
Object.seal(this);
|
|
@@ -63,6 +66,41 @@ class GC {
|
|
|
63
66
|
async stop() {
|
|
64
67
|
this.isStopped = true;
|
|
65
68
|
}
|
|
69
|
+
async collectIn(obj) {
|
|
70
|
+
// calculate versions that should not be removed
|
|
71
|
+
const { gcMaxVer, nonGarbage } = obj.getNonGarbageVersions();
|
|
72
|
+
// if object is set archived, and there is nothing in it worth keeping,
|
|
73
|
+
// whole folder can be removed
|
|
74
|
+
if ((nonGarbage.size === 0)
|
|
75
|
+
&& obj.isArchived() && obj.sync().isSyncDone()) {
|
|
76
|
+
if (!obj.isStatusFileSaved()) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
this.rmObjFromCache(obj);
|
|
80
|
+
if (obj.objId) {
|
|
81
|
+
await this.rmObjFolder(obj.objId);
|
|
82
|
+
}
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
// for all other cases, we remove version files that are not worth
|
|
86
|
+
// keeping.
|
|
87
|
+
const lst = await fs.readdir(obj.objFolder).catch(noop);
|
|
88
|
+
if (!lst) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
const rmProcs = [];
|
|
92
|
+
for (const f of lst) {
|
|
93
|
+
const ver = parseInt(f);
|
|
94
|
+
if (isNaN(ver) || nonGarbage.has(ver)
|
|
95
|
+
|| (gcMaxVer && (ver >= gcMaxVer))) {
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
rmProcs.push(fs.unlink(path_1.join(obj.objFolder, f)).catch(noop));
|
|
99
|
+
}
|
|
100
|
+
if (rmProcs.length > 0) {
|
|
101
|
+
await Promise.all(rmProcs);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
66
104
|
}
|
|
67
105
|
exports.GC = GC;
|
|
68
106
|
Object.freeze(GC.prototype);
|
|
@@ -76,4 +114,5 @@ function getAndRemoveOneFrom(set) {
|
|
|
76
114
|
set.delete(value);
|
|
77
115
|
return value;
|
|
78
116
|
}
|
|
117
|
+
function noop() { }
|
|
79
118
|
Object.freeze(exports);
|
|
@@ -5,22 +5,8 @@ import { ObjSource, Subscribe } from 'xsp-files';
|
|
|
5
5
|
import { Downloader } from './downloader';
|
|
6
6
|
import { FileWrite } from '../../../lib-client/objs-on-disk/file-writing-proc';
|
|
7
7
|
import { GC } from './obj-files-gc';
|
|
8
|
+
import { UpSyncStatus } from './obj-status';
|
|
8
9
|
import { LogError } from '../../../lib-client/logging/log-to-file';
|
|
9
|
-
/**
|
|
10
|
-
* This is an extention for an unsynced version file. File name starts with a
|
|
11
|
-
* version number.
|
|
12
|
-
*/
|
|
13
|
-
export declare const UNSYNCED_FILE_NAME_EXT = "unsynced";
|
|
14
|
-
/**
|
|
15
|
-
* This is an upload info file. When an upload is complete,
|
|
16
|
-
* this info file is removed.
|
|
17
|
-
*/
|
|
18
|
-
export declare const UPLOAD_INFO_FNAME = "upload";
|
|
19
|
-
/**
|
|
20
|
-
* Presence of this empty file in a object folder indicates that object's
|
|
21
|
-
* removal hasn't been synchronized, yet.
|
|
22
|
-
*/
|
|
23
|
-
export declare const UNSYNCED_REMOVAL = "unsynced-removal";
|
|
24
10
|
export declare class ObjFiles {
|
|
25
11
|
private readonly folders;
|
|
26
12
|
private readonly downloader;
|
|
@@ -61,9 +47,11 @@ export declare class SyncedObj {
|
|
|
61
47
|
*/
|
|
62
48
|
private readonly remoteConflictVerObjs;
|
|
63
49
|
private constructor();
|
|
64
|
-
static forExistingObj(objId: ObjId, objFolder: string, downloader: Downloader, scheduleGC: GC['scheduleCollection']): Promise<SyncedObj>;
|
|
65
|
-
static forDownloadedObj(objId: ObjId, objFolder: string, downloader: Downloader, scheduleGC: GC['scheduleCollection'], version: number, parts: InitDownloadParts): Promise<SyncedObj>;
|
|
66
|
-
static forNewObj(objId: ObjId, objFolder: string, downloader: Downloader, scheduleGC: GC['scheduleCollection']): Promise<SyncedObj>;
|
|
50
|
+
static forExistingObj(objId: ObjId, objFolder: string, downloader: Downloader, scheduleGC: GC['scheduleCollection'], logError: LogError): Promise<SyncedObj>;
|
|
51
|
+
static forDownloadedObj(objId: ObjId, objFolder: string, downloader: Downloader, scheduleGC: GC['scheduleCollection'], version: number, parts: InitDownloadParts, logError: LogError): Promise<SyncedObj>;
|
|
52
|
+
static forNewObj(objId: ObjId, objFolder: string, downloader: Downloader, scheduleGC: GC['scheduleCollection'], logError: LogError): Promise<SyncedObj>;
|
|
53
|
+
sync(): UpSyncStatus;
|
|
54
|
+
scheduleSelfGC(): void;
|
|
67
55
|
private path;
|
|
68
56
|
getObjSrc(version: number): Promise<ObjSource>;
|
|
69
57
|
private objSegsGetterFromDisk;
|
|
@@ -77,9 +65,14 @@ export declare class SyncedObj {
|
|
|
77
65
|
getCurrentVersionOrThrow(): number;
|
|
78
66
|
isRemoteVersionGreaterOrEqualTo(newRemoteVersion: number): boolean;
|
|
79
67
|
isDeletedOnRemote(): boolean;
|
|
80
|
-
setUnsyncedCurrentVersion
|
|
81
|
-
|
|
68
|
+
private setUnsyncedCurrentVersion;
|
|
69
|
+
markVersionSynced(version: number): Promise<void>;
|
|
82
70
|
setRemoteVersion(version: number): Promise<void>;
|
|
83
71
|
setDeletedOnRemote(): Promise<void>;
|
|
84
72
|
removeCurrentVersion(): Promise<void>;
|
|
73
|
+
getNonGarbageVersions(): {
|
|
74
|
+
gcMaxVer?: number;
|
|
75
|
+
nonGarbage: Set<number>;
|
|
76
|
+
};
|
|
77
|
+
isStatusFileSaved(): boolean;
|
|
85
78
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/*
|
|
3
|
-
Copyright (C) 2016 - 2020 3NSoft Inc.
|
|
3
|
+
Copyright (C) 2016 - 2020, 2022 3NSoft Inc.
|
|
4
4
|
|
|
5
5
|
This program is free software: you can redistribute it and/or modify it under
|
|
6
6
|
the terms of the GNU General Public License as published by the Free Software
|
|
@@ -16,9 +16,10 @@
|
|
|
16
16
|
this program. If not, see <http://www.gnu.org/licenses/>.
|
|
17
17
|
*/
|
|
18
18
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
-
exports.SyncedObj = exports.ObjFiles =
|
|
19
|
+
exports.SyncedObj = exports.ObjFiles = void 0;
|
|
20
20
|
const rxjs_1 = require("rxjs");
|
|
21
|
-
const
|
|
21
|
+
const synced_1 = require("../../../lib-common/processes/synced");
|
|
22
|
+
const sleep_1 = require("../../../lib-common/processes/sleep");
|
|
22
23
|
const obj_folders_1 = require("../../../lib-client/objs-on-disk/obj-folders");
|
|
23
24
|
const fs = require("../../../lib-common/async-fs-node");
|
|
24
25
|
const obj_on_disk_1 = require("../../../lib-client/objs-on-disk/obj-on-disk");
|
|
@@ -29,21 +30,9 @@ const utils_for_observables_1 = require("../../../lib-common/utils-for-observabl
|
|
|
29
30
|
const obj_files_gc_1 = require("./obj-files-gc");
|
|
30
31
|
const obj_status_1 = require("./obj-status");
|
|
31
32
|
const timed_cache_1 = require("../../../lib-common/timed-cache");
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
*/
|
|
36
|
-
exports.UNSYNCED_FILE_NAME_EXT = 'unsynced';
|
|
37
|
-
/**
|
|
38
|
-
* This is an upload info file. When an upload is complete,
|
|
39
|
-
* this info file is removed.
|
|
40
|
-
*/
|
|
41
|
-
exports.UPLOAD_INFO_FNAME = 'upload';
|
|
42
|
-
/**
|
|
43
|
-
* Presence of this empty file in a object folder indicates that object's
|
|
44
|
-
* removal hasn't been synchronized, yet.
|
|
45
|
-
*/
|
|
46
|
-
exports.UNSYNCED_REMOVAL = 'unsynced-removal';
|
|
33
|
+
const UNSYNCED_FILE_NAME_EXT = 'unsynced';
|
|
34
|
+
const SYNCED_FILE_NAME_EXT = 'v';
|
|
35
|
+
const REMOTE_FILE_NAME_EXT = 'remote';
|
|
47
36
|
class ObjFiles {
|
|
48
37
|
constructor(folders, downloader, logError) {
|
|
49
38
|
this.folders = folders;
|
|
@@ -65,11 +54,17 @@ class ObjFiles {
|
|
|
65
54
|
}
|
|
66
55
|
const lst = await fs.readdir(objFolderPath);
|
|
67
56
|
for (const fName of lst) {
|
|
68
|
-
if (fName.endsWith(
|
|
69
|
-
|| (fName === exports.UPLOAD_INFO_FNAME)
|
|
70
|
-
|| (fName === exports.UNSYNCED_REMOVAL)) {
|
|
57
|
+
if (fName.endsWith(UNSYNCED_FILE_NAME_EXT)) {
|
|
71
58
|
return false;
|
|
72
59
|
}
|
|
60
|
+
if (fName === obj_status_1.STATUS_FILE_NAME) {
|
|
61
|
+
if (!objFiles.objs.has(objId)) {
|
|
62
|
+
const status = await obj_status_1.readAndCheckStatus(objFolderPath, objId).catch(noop);
|
|
63
|
+
if (status && status.syncTasks) {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
73
68
|
}
|
|
74
69
|
return true;
|
|
75
70
|
}, logError);
|
|
@@ -86,7 +81,7 @@ class ObjFiles {
|
|
|
86
81
|
if (!folder) {
|
|
87
82
|
return;
|
|
88
83
|
}
|
|
89
|
-
const obj = await SyncedObj.forExistingObj(objId, folder, this.downloader, this.gc.scheduleCollection);
|
|
84
|
+
const obj = await SyncedObj.forExistingObj(objId, folder, this.downloader, this.gc.scheduleCollection, this.logError);
|
|
90
85
|
this.objs.set(objId, obj);
|
|
91
86
|
return obj;
|
|
92
87
|
});
|
|
@@ -97,10 +92,10 @@ class ObjFiles {
|
|
|
97
92
|
let obj;
|
|
98
93
|
if (download) {
|
|
99
94
|
assert_1.assert(typeof download.version === 'number');
|
|
100
|
-
obj = await SyncedObj.forDownloadedObj(objId, folder, this.downloader, this.gc.scheduleCollection, download.version, download.parts);
|
|
95
|
+
obj = await SyncedObj.forDownloadedObj(objId, folder, this.downloader, this.gc.scheduleCollection, download.version, download.parts, this.logError);
|
|
101
96
|
}
|
|
102
97
|
else {
|
|
103
|
-
obj = await SyncedObj.forNewObj(objId, folder, this.downloader, this.gc.scheduleCollection);
|
|
98
|
+
obj = await SyncedObj.forNewObj(objId, folder, this.downloader, this.gc.scheduleCollection, this.logError);
|
|
104
99
|
}
|
|
105
100
|
this.objs.set(objId, obj);
|
|
106
101
|
return obj;
|
|
@@ -136,7 +131,7 @@ class ObjFiles {
|
|
|
136
131
|
operators_1.mergeMap(() => this.folders.listRecent()),
|
|
137
132
|
// flatten array and space it in time, to process folders one by one
|
|
138
133
|
operators_1.mergeMap(objsAndPaths => objsAndPaths), operators_1.filter(({ objId }) => !this.objs.has(objId)), operators_1.mergeMap(async (objsAndPaths) => {
|
|
139
|
-
await
|
|
134
|
+
await sleep_1.sleep(20);
|
|
140
135
|
return objsAndPaths;
|
|
141
136
|
}, 1),
|
|
142
137
|
// check, emiting objId, if not synced, and undefined, if synced
|
|
@@ -155,10 +150,10 @@ Object.freeze(ObjFiles.prototype);
|
|
|
155
150
|
Object.freeze(ObjFiles);
|
|
156
151
|
function makeSynchronizer(proc) {
|
|
157
152
|
if (!proc) {
|
|
158
|
-
proc = new
|
|
153
|
+
proc = new synced_1.NamedProcs();
|
|
159
154
|
}
|
|
160
155
|
async function sync(objId, action) {
|
|
161
|
-
const id = (
|
|
156
|
+
const id = (objId ? objId : '==root==');
|
|
162
157
|
return proc.startOrChain(id, action);
|
|
163
158
|
}
|
|
164
159
|
return sync;
|
|
@@ -234,25 +229,34 @@ class SyncedObj {
|
|
|
234
229
|
};
|
|
235
230
|
Object.freeze(this);
|
|
236
231
|
}
|
|
237
|
-
static async forExistingObj(objId, objFolder, downloader, scheduleGC) {
|
|
238
|
-
const status = await obj_status_1.ObjStatus.readFrom(objFolder, objId);
|
|
232
|
+
static async forExistingObj(objId, objFolder, downloader, scheduleGC, logError) {
|
|
233
|
+
const status = await obj_status_1.ObjStatus.readFrom(objFolder, objId, logError);
|
|
239
234
|
return new SyncedObj(objId, objFolder, status, downloader, scheduleGC);
|
|
240
235
|
}
|
|
241
|
-
static async forDownloadedObj(objId, objFolder, downloader, scheduleGC, version, parts) {
|
|
242
|
-
|
|
236
|
+
static async forDownloadedObj(objId, objFolder, downloader, scheduleGC, version, parts, logError) {
|
|
237
|
+
// XXX let's note that given version is used to be current on server
|
|
238
|
+
const status = await obj_status_1.ObjStatus.makeForDownloadedVersion(objFolder, objId, version, version, logError);
|
|
243
239
|
const obj = new SyncedObj(objId, objFolder, status, downloader, scheduleGC);
|
|
244
|
-
const fPath = obj.path(version,
|
|
240
|
+
const fPath = obj.path(version, true);
|
|
245
241
|
const objVer = await obj_on_disk_1.ObjOnDisk.createFileForExistingVersion(obj.objId, version, fPath, obj.downloader, obj.objSegsGetterFromDisk, parts);
|
|
246
242
|
obj.verObjs.set(version, objVer);
|
|
247
243
|
return obj;
|
|
248
244
|
}
|
|
249
|
-
static async forNewObj(objId, objFolder, downloader, scheduleGC) {
|
|
250
|
-
const status = await obj_status_1.ObjStatus.makeNew(objFolder, objId);
|
|
245
|
+
static async forNewObj(objId, objFolder, downloader, scheduleGC, logError) {
|
|
246
|
+
const status = await obj_status_1.ObjStatus.makeNew(objFolder, objId, logError);
|
|
251
247
|
return new SyncedObj(objId, objFolder, status, downloader, scheduleGC);
|
|
252
248
|
}
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
249
|
+
sync() {
|
|
250
|
+
return this.status;
|
|
251
|
+
}
|
|
252
|
+
scheduleSelfGC() {
|
|
253
|
+
this.scheduleGC(this);
|
|
254
|
+
}
|
|
255
|
+
path(version, synced, remote) {
|
|
256
|
+
const fileExt = (synced ?
|
|
257
|
+
SYNCED_FILE_NAME_EXT :
|
|
258
|
+
(remote ? REMOTE_FILE_NAME_EXT : UNSYNCED_FILE_NAME_EXT));
|
|
259
|
+
const fName = `${version}.${fileExt}`;
|
|
256
260
|
return path_1.join(this.objFolder, fName);
|
|
257
261
|
}
|
|
258
262
|
async getObjSrc(version) {
|
|
@@ -297,11 +301,13 @@ class SyncedObj {
|
|
|
297
301
|
const fPath = this.path(version, false);
|
|
298
302
|
const { obj, write$ } = await obj_on_disk_1.ObjOnDisk.createFileForWriteOfNewVersion(this.objId, version, fPath, encSub, this.downloader, this.objSegsGetterFromDisk);
|
|
299
303
|
this.verObjs.set(version, obj);
|
|
300
|
-
const fileWrite$ = write$.pipe(operators_1.tap(
|
|
301
|
-
|
|
302
|
-
this.verObjs.
|
|
304
|
+
const fileWrite$ = write$.pipe(operators_1.tap({
|
|
305
|
+
error: err => {
|
|
306
|
+
if (this.verObjs.get(version) === obj) {
|
|
307
|
+
this.verObjs.delete(version);
|
|
308
|
+
}
|
|
303
309
|
}
|
|
304
|
-
}), utils_for_observables_1.flatTap(undefined, undefined, () => this.setUnsyncedCurrentVersion(version)));
|
|
310
|
+
}), utils_for_observables_1.flatTap(undefined, undefined, () => this.setUnsyncedCurrentVersion(version, obj.getBaseVersion())));
|
|
305
311
|
return { fileWrite$, baseVer: obj.getBaseVersion() };
|
|
306
312
|
}
|
|
307
313
|
isArchived() {
|
|
@@ -316,13 +322,22 @@ class SyncedObj {
|
|
|
316
322
|
isDeletedOnRemote() {
|
|
317
323
|
return this.status.isDeletedOnRemote();
|
|
318
324
|
}
|
|
319
|
-
async setUnsyncedCurrentVersion(version) {
|
|
320
|
-
await this.status.setUnsyncedCurrentVersion(version);
|
|
321
|
-
|
|
325
|
+
async setUnsyncedCurrentVersion(version, baseVersion) {
|
|
326
|
+
await this.status.setUnsyncedCurrentVersion(version, baseVersion);
|
|
327
|
+
if (version > 1) {
|
|
328
|
+
this.scheduleSelfGC();
|
|
329
|
+
}
|
|
322
330
|
}
|
|
323
|
-
async
|
|
324
|
-
|
|
325
|
-
|
|
331
|
+
async markVersionSynced(version) {
|
|
332
|
+
const verObj = this.verObjs.get(version);
|
|
333
|
+
if (verObj) {
|
|
334
|
+
await verObj.moveFile(this.path(version, true));
|
|
335
|
+
}
|
|
336
|
+
else {
|
|
337
|
+
await fs.rename(this.path(version, false), this.path(version, true));
|
|
338
|
+
}
|
|
339
|
+
await this.status.markVersionSynced(version);
|
|
340
|
+
this.scheduleSelfGC();
|
|
326
341
|
}
|
|
327
342
|
async setRemoteVersion(version) {
|
|
328
343
|
await this.status.setRemoteVersion(version);
|
|
@@ -332,7 +347,13 @@ class SyncedObj {
|
|
|
332
347
|
}
|
|
333
348
|
async removeCurrentVersion() {
|
|
334
349
|
await this.status.removeCurrentVersion(this.verObjs);
|
|
335
|
-
this.
|
|
350
|
+
this.scheduleSelfGC();
|
|
351
|
+
}
|
|
352
|
+
getNonGarbageVersions() {
|
|
353
|
+
return this.status.getNonGarbageVersions();
|
|
354
|
+
}
|
|
355
|
+
isStatusFileSaved() {
|
|
356
|
+
return this.status.isFileSaved();
|
|
336
357
|
}
|
|
337
358
|
}
|
|
338
359
|
exports.SyncedObj = SyncedObj;
|
|
@@ -347,4 +368,5 @@ async function isOnDisk(path) {
|
|
|
347
368
|
throw exc;
|
|
348
369
|
}));
|
|
349
370
|
}
|
|
371
|
+
function noop() { }
|
|
350
372
|
Object.freeze(exports);
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { ObjId } from '../../../lib-client/3nstorage/xsp-fs/common';
|
|
2
|
+
import { VersionsInfo } from '../common/obj-info-file';
|
|
3
|
+
import { LogError } from '../../../lib-client/logging/log-to-file';
|
|
4
|
+
declare type Stats = web3n.files.Stats;
|
|
2
5
|
/**
|
|
3
6
|
* Storage object can be in following states:
|
|
4
7
|
* 1. Synced state indicates that current local version and one on the server
|
|
@@ -14,45 +17,101 @@ export declare type SyncState = 'synced' | 'behind' | 'unsynced' | 'conflicting'
|
|
|
14
17
|
export interface ObjStatusInfo {
|
|
15
18
|
objId: ObjId;
|
|
16
19
|
isArchived?: boolean;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
versions: VersionsInfo;
|
|
21
|
+
sync: {
|
|
22
|
+
state: SyncState;
|
|
23
|
+
latest?: number;
|
|
21
24
|
conflictingRemote?: number[];
|
|
22
|
-
current?: number;
|
|
23
|
-
archived?: number[];
|
|
24
|
-
unsynchedArchived?: number[];
|
|
25
25
|
remote?: number;
|
|
26
|
+
deletedOnRemote?: true;
|
|
26
27
|
};
|
|
27
|
-
|
|
28
|
+
syncTasks?: {
|
|
29
|
+
queued: UpSyncTaskInfo[];
|
|
30
|
+
current?: UpSyncTaskInfo;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
export interface UploadInfo {
|
|
34
|
+
type: 'upload';
|
|
35
|
+
transactionId?: string;
|
|
36
|
+
createObj?: true;
|
|
37
|
+
needUpload?: {
|
|
38
|
+
header?: number;
|
|
39
|
+
segs: BytesSection[];
|
|
40
|
+
allByteOnDisk?: true;
|
|
41
|
+
};
|
|
42
|
+
version: number;
|
|
43
|
+
baseVersion?: number;
|
|
44
|
+
}
|
|
45
|
+
export interface BytesSection {
|
|
46
|
+
ofs: number;
|
|
47
|
+
len: number;
|
|
28
48
|
}
|
|
29
|
-
export
|
|
49
|
+
export interface RemovalInfo {
|
|
50
|
+
type: 'removal';
|
|
51
|
+
archivedVersions?: number[] | number;
|
|
52
|
+
currentVersion?: true;
|
|
53
|
+
}
|
|
54
|
+
export interface ArchivalInfo {
|
|
55
|
+
type: 'archiving';
|
|
56
|
+
archivalOfCurrent?: true;
|
|
57
|
+
}
|
|
58
|
+
export declare type UpSyncTaskInfo = UploadInfo | RemovalInfo | ArchivalInfo;
|
|
59
|
+
export interface UpSyncStatus {
|
|
60
|
+
queueTask(t: UpSyncTaskInfo): void;
|
|
61
|
+
getTaskForProcessing(): Promise<UpSyncTaskInfo | undefined>;
|
|
62
|
+
glanceOnNextTask(): UpSyncTaskInfo | undefined;
|
|
63
|
+
recordInterimStateOfCurrentTask(t: UploadInfo): Promise<void>;
|
|
64
|
+
recordTaskCompletion(t: UpSyncTaskInfo): Promise<void>;
|
|
65
|
+
isSyncDone(): boolean;
|
|
66
|
+
stat(): NonNullable<Stats['sync']>;
|
|
67
|
+
}
|
|
68
|
+
export declare const STATUS_FILE_NAME = "status";
|
|
69
|
+
export declare class ObjStatus implements UpSyncStatus {
|
|
30
70
|
private readonly objFolder;
|
|
31
71
|
private readonly status;
|
|
72
|
+
private readonly logError;
|
|
32
73
|
private readonly saveProc;
|
|
33
74
|
private constructor();
|
|
34
|
-
static readFrom(objFolder: string, objId: ObjId): Promise<ObjStatus>;
|
|
35
|
-
static makeNew(objFolder: string, objId: ObjId): Promise<ObjStatus>;
|
|
36
|
-
static makeForDownloadedVersion(objFolder: string, objId: ObjId, version: number): Promise<ObjStatus>;
|
|
75
|
+
static readFrom(objFolder: string, objId: ObjId, logError: LogError): Promise<ObjStatus>;
|
|
76
|
+
static makeNew(objFolder: string, objId: ObjId, logError: LogError): Promise<ObjStatus>;
|
|
77
|
+
static makeForDownloadedVersion(objFolder: string, objId: ObjId, version: number, currentRemote: number, logError: LogError): Promise<ObjStatus>;
|
|
37
78
|
static fileShowsObjNotInSyncedState(objFolder: string, objId: ObjId): Promise<boolean>;
|
|
38
|
-
private saveFile;
|
|
39
79
|
isArchived(): boolean;
|
|
40
80
|
getCurrentVersionOrThrow(): number;
|
|
81
|
+
getNonGarbageVersions(): {
|
|
82
|
+
gcMaxVer?: number;
|
|
83
|
+
nonGarbage: Set<number>;
|
|
84
|
+
};
|
|
41
85
|
isRemoteVersionGreaterOrEqualTo(newRemoteVersion: number): boolean;
|
|
42
86
|
isDeletedOnRemote(): boolean;
|
|
43
87
|
syncedVersionGreaterOrEqual(version: number): boolean;
|
|
44
88
|
removeCurrentVersion(verObjs: ContainerWithDelete<number>): Promise<void>;
|
|
89
|
+
private triggerSaveProc;
|
|
45
90
|
setDeletedOnRemote(): Promise<void>;
|
|
46
91
|
setRemoteVersion(version: number): Promise<void>;
|
|
47
|
-
|
|
48
|
-
setUnsyncedCurrentVersion(version: number): Promise<void>;
|
|
92
|
+
markVersionSynced(version: number): Promise<void>;
|
|
93
|
+
setUnsyncedCurrentVersion(version: number, baseVer: number | undefined): Promise<void>;
|
|
49
94
|
/**
|
|
50
95
|
* This method ignores remote conflicting versions.
|
|
51
96
|
* @param version
|
|
52
97
|
*/
|
|
53
98
|
isVersionSynced(version: number): boolean;
|
|
99
|
+
isVersionArchived(version: number): boolean;
|
|
100
|
+
queueTask(t: UpSyncTaskInfo): void;
|
|
101
|
+
private addUploadToQueue;
|
|
102
|
+
private addRemoveCurrentToQueue;
|
|
103
|
+
private addRemoveArchivedToQueue;
|
|
104
|
+
private addArchivalToQueue;
|
|
105
|
+
getTaskForProcessing(): Promise<UpSyncTaskInfo | undefined>;
|
|
106
|
+
glanceOnNextTask(): UpSyncTaskInfo | undefined;
|
|
107
|
+
recordInterimStateOfCurrentTask(t: UploadInfo): Promise<void>;
|
|
108
|
+
recordTaskCompletion(t: UpSyncTaskInfo): Promise<void>;
|
|
109
|
+
isSyncDone(): boolean;
|
|
110
|
+
isFileSaved(): boolean;
|
|
111
|
+
stat(): NonNullable<Stats['sync']>;
|
|
54
112
|
}
|
|
55
113
|
interface ContainerWithDelete<T> {
|
|
56
114
|
delete(key: T): void;
|
|
57
115
|
}
|
|
116
|
+
export declare function readAndCheckStatus(objFolder: string, objId: ObjId): Promise<ObjStatusInfo>;
|
|
58
117
|
export {};
|