core-3nweb-client-lib 0.43.9 → 0.43.12
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/build/api-defs/files.d.ts +32 -8
- package/build/api-defs/web3n.d.ts +2 -0
- package/build/core/asmail/inbox/index.js +1 -1
- package/build/core/asmail/inbox/msg-downloader.d.ts +2 -12
- package/build/core/asmail/inbox/msg-downloader.js +13 -46
- package/build/core/storage/synced/downloader.d.ts +6 -15
- package/build/core/storage/synced/downloader.js +25 -48
- package/build/core/storage/synced/obj-files.d.ts +4 -2
- package/build/core/storage/synced/obj-files.js +7 -7
- package/build/core/storage/synced/storage.d.ts +4 -2
- package/build/core/storage/synced/storage.js +2 -2
- package/build/core/storage/synced/upsyncer.d.ts +2 -4
- package/build/core/storage/synced/upsyncer.js +19 -13
- package/build/core-ipc/file.d.ts +10 -0
- package/build/core-ipc/file.js +23 -13
- package/build/core-ipc/fs.js +15 -8
- package/build/lib-client/3nstorage/storage-owner.js +36 -29
- package/build/lib-client/3nweb-signup.js +7 -7
- package/build/lib-client/asmail/recipient.js +14 -11
- package/build/lib-client/asmail/sender.js +24 -25
- package/build/lib-client/asmail/service-config.js +3 -6
- package/build/lib-client/cryptor/cryptor-wasm.js +1 -1
- package/build/lib-client/cryptor/cryptor.wasm +0 -0
- package/build/lib-client/fs-utils/files.js +4 -4
- package/build/lib-client/mailer-id/login.js +7 -7
- package/build/lib-client/mailer-id/provisioner.js +9 -7
- package/build/lib-client/objs-on-disk/file-writing-proc.d.ts +1 -1
- package/build/lib-client/objs-on-disk/obj-on-disk.d.ts +51 -3
- package/build/lib-client/objs-on-disk/obj-on-disk.js +414 -34
- package/build/lib-client/request-utils.d.ts +0 -7
- package/build/lib-client/request-utils.js +16 -11
- package/build/lib-client/service-locator.js +11 -8
- package/build/lib-client/user-with-mid-session.js +2 -6
- package/build/lib-client/user-with-pkl-session.js +25 -24
- package/build/lib-client/xsp-fs/common.d.ts +8 -3
- package/build/lib-client/xsp-fs/common.js +1 -1
- package/build/lib-client/xsp-fs/file.d.ts +3 -1
- package/build/lib-client/xsp-fs/file.js +4 -4
- package/build/lib-client/xsp-fs/folder-node.d.ts +1 -1
- package/build/lib-client/xsp-fs/folder-node.js +4 -4
- package/build/lib-client/xsp-fs/fs.d.ts +3 -1
- package/build/lib-client/xsp-fs/fs.js +4 -4
- package/build/lib-client/xsp-fs/node-in-fs.d.ts +6 -4
- package/build/lib-client/xsp-fs/node-in-fs.js +14 -9
- package/build/lib-common/buffer-utils.js +4 -1
- package/build/lib-common/exceptions/http.d.ts +11 -1
- package/build/lib-common/exceptions/http.js +10 -2
- package/build/lib-common/objs-on-disk/utils.d.ts +1 -1
- package/build/lib-common/processes/labelled-exec-pools.d.ts +1 -1
- package/build/lib-common/processes/labelled-exec-pools.js +8 -2
- package/build/protos/asmail.proto.js +545 -116
- package/build/protos/file.proto.js +485 -56
- package/build/protos/fs.proto.js +545 -116
- package/package.json +1 -1
- package/protos/file.proto +8 -2
- package/protos/fs.proto +3 -3
- /package/build/lib-common/objs-on-disk/{obj-file.d.ts → obj-version-file.d.ts} +0 -0
- /package/build/lib-common/objs-on-disk/{obj-file.js → obj-version-file.js} +0 -0
|
@@ -412,7 +412,7 @@ declare namespace web3n.files {
|
|
|
412
412
|
*/
|
|
413
413
|
getByteSource(): Promise<FileByteSource>;
|
|
414
414
|
|
|
415
|
-
watch(observer: Observer<FileEvent|RemoteEvent|UploadEvent>): () => void;
|
|
415
|
+
watch(observer: Observer<FileEvent|RemoteEvent|UploadEvent|DownloadEvent>): () => void;
|
|
416
416
|
|
|
417
417
|
}
|
|
418
418
|
|
|
@@ -638,7 +638,7 @@ declare namespace web3n.files {
|
|
|
638
638
|
* This downloads bytes onto disk, skipping decryption, as file content isn't read here.
|
|
639
639
|
* @param version
|
|
640
640
|
*/
|
|
641
|
-
|
|
641
|
+
startDownload(version: number): Promise<{ downloadTaskId: number; }|undefined>;
|
|
642
642
|
|
|
643
643
|
/**
|
|
644
644
|
* Adopts remote version.
|
|
@@ -665,7 +665,7 @@ declare namespace web3n.files {
|
|
|
665
665
|
* Undefined is returned when upload is not needed, e.g. version is already synced.
|
|
666
666
|
* Upload version and upload task id are returned together with an indicator of whether
|
|
667
667
|
* this call has started upload, or it has already been going on.
|
|
668
|
-
* Upload task id can be used to
|
|
668
|
+
* Upload task id can be used to filter watched events.
|
|
669
669
|
* @param opts
|
|
670
670
|
*/
|
|
671
671
|
startUpload(
|
|
@@ -674,6 +674,7 @@ declare namespace web3n.files {
|
|
|
674
674
|
|
|
675
675
|
/**
|
|
676
676
|
* Upload in conflicting and behind state of sync requires explicit upload version.
|
|
677
|
+
* This upload will not be generating upload events.
|
|
677
678
|
* @param opts
|
|
678
679
|
*/
|
|
679
680
|
upload(opts?: OptionsToUploadLocal): Promise<number|undefined>;
|
|
@@ -763,16 +764,16 @@ declare namespace web3n.files {
|
|
|
763
764
|
readLink(path: string): Promise<SymLink>;
|
|
764
765
|
|
|
765
766
|
watchFolder(
|
|
766
|
-
path: string, observer: Observer<FolderEvent|RemoteEvent|UploadEvent>
|
|
767
|
+
path: string, observer: Observer<FolderEvent|RemoteEvent|UploadEvent|DownloadEvent>
|
|
767
768
|
): () => void;
|
|
768
769
|
|
|
769
770
|
watchFile(
|
|
770
|
-
path: string, observer: Observer<FileEvent|RemoteEvent|UploadEvent>
|
|
771
|
+
path: string, observer: Observer<FileEvent|RemoteEvent|UploadEvent|DownloadEvent>
|
|
771
772
|
): () => void;
|
|
772
773
|
|
|
773
774
|
watchTree(
|
|
774
775
|
path: string, depth: number|undefined,
|
|
775
|
-
observer: Observer<FolderEvent|FileEvent|RemoteEvent|UploadEvent>
|
|
776
|
+
observer: Observer<FolderEvent|FileEvent|RemoteEvent|UploadEvent|DownloadEvent>
|
|
776
777
|
): () => void;
|
|
777
778
|
|
|
778
779
|
close(): Promise<void>;
|
|
@@ -1288,7 +1289,7 @@ declare namespace web3n.files {
|
|
|
1288
1289
|
* @param path
|
|
1289
1290
|
* @param version
|
|
1290
1291
|
*/
|
|
1291
|
-
|
|
1292
|
+
startDownload(path: string, version: number): Promise<{ downloadTaskId: number; }|undefined>;
|
|
1292
1293
|
|
|
1293
1294
|
/**
|
|
1294
1295
|
* Adopts remote version of fs object at given path.
|
|
@@ -1340,7 +1341,7 @@ declare namespace web3n.files {
|
|
|
1340
1341
|
* Undefined is returned when upload is not needed, e.g. version is already synced.
|
|
1341
1342
|
* Upload version and upload task id are returned together with an indicator of whether
|
|
1342
1343
|
* this call has started upload, or it has already been going on.
|
|
1343
|
-
* Upload task id can be used to
|
|
1344
|
+
* Upload task id can be used to filter watched events.
|
|
1344
1345
|
* @param path
|
|
1345
1346
|
* @param opts
|
|
1346
1347
|
*/
|
|
@@ -1350,6 +1351,7 @@ declare namespace web3n.files {
|
|
|
1350
1351
|
|
|
1351
1352
|
/**
|
|
1352
1353
|
* Upload in conflicting and behind state of sync requires explicit upload version.
|
|
1354
|
+
* This upload will not be generating upload events.
|
|
1353
1355
|
* @param path
|
|
1354
1356
|
* @param opts
|
|
1355
1357
|
*/
|
|
@@ -1470,4 +1472,26 @@ declare namespace web3n.files {
|
|
|
1470
1472
|
type: 'upload-done';
|
|
1471
1473
|
}
|
|
1472
1474
|
|
|
1475
|
+
type DownloadEvent = DownloadStartEvent | DownloadProgressEvent | DownloadDoneEvent;
|
|
1476
|
+
|
|
1477
|
+
interface DownloadEventBase extends FSEvent {
|
|
1478
|
+
downloadTaskId: number;
|
|
1479
|
+
version: number;
|
|
1480
|
+
}
|
|
1481
|
+
|
|
1482
|
+
interface DownloadStartEvent extends DownloadEventBase {
|
|
1483
|
+
type: 'download-started';
|
|
1484
|
+
totalBytesToDownload: number;
|
|
1485
|
+
}
|
|
1486
|
+
|
|
1487
|
+
interface DownloadDoneEvent extends DownloadEventBase {
|
|
1488
|
+
type: 'download-done';
|
|
1489
|
+
}
|
|
1490
|
+
|
|
1491
|
+
interface DownloadProgressEvent extends DownloadEventBase {
|
|
1492
|
+
type: 'download-progress';
|
|
1493
|
+
totalBytesToDownload: number;
|
|
1494
|
+
bytesLeftToDownload: number;
|
|
1495
|
+
}
|
|
1496
|
+
|
|
1473
1497
|
}
|
|
@@ -110,7 +110,7 @@ class InboxOnServer {
|
|
|
110
110
|
return msgOnDisk;
|
|
111
111
|
}
|
|
112
112
|
const meta = await this.downloader.getMsgMeta(msgId);
|
|
113
|
-
return this.cache.addMsg(msgId, meta);
|
|
113
|
+
return await this.cache.addMsg(msgId, meta);
|
|
114
114
|
}
|
|
115
115
|
async startCachingAndAddKeyToIndex(msgId) {
|
|
116
116
|
const msgOnDisk = await this.msgFromDiskOrDownload(msgId);
|
|
@@ -1,20 +1,10 @@
|
|
|
1
1
|
import { MailRecipient } from "../../../lib-client/asmail/recipient";
|
|
2
2
|
import { ObjDownloader } from "../../../lib-client/objs-on-disk/obj-on-disk";
|
|
3
3
|
import { MsgMeta } from "../../../lib-common/service-api/asmail/retrieval";
|
|
4
|
-
/**
|
|
5
|
-
* Downloader is responsible for getting mail objects from server and placing
|
|
6
|
-
* bytes into cache.
|
|
7
|
-
*/
|
|
8
4
|
export declare class MsgDownloader {
|
|
9
|
-
private msgReceiver;
|
|
10
|
-
|
|
11
|
-
* Per-object chained downloads.
|
|
12
|
-
* When it comes to the download start, if chain exists, it means that
|
|
13
|
-
* process has already started.
|
|
14
|
-
*/
|
|
15
|
-
private downloadProcs;
|
|
5
|
+
private readonly msgReceiver;
|
|
6
|
+
private readonly runner;
|
|
16
7
|
constructor(msgReceiver: MailRecipient);
|
|
17
|
-
private sync;
|
|
18
8
|
getMsgMeta(msgId: string): Promise<MsgMeta>;
|
|
19
9
|
getObjDownloader(msgId: string): ObjDownloader;
|
|
20
10
|
private getLayoutWithHeaderAndFirstSegs;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/*
|
|
3
|
-
Copyright (C) 2016 - 2019 3NSoft Inc.
|
|
3
|
+
Copyright (C) 2016 - 2019, 2025 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,72 +13,39 @@
|
|
|
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.MsgDownloader = void 0;
|
|
19
|
-
const
|
|
20
|
-
const buffer_utils_1 = require("../../../lib-common/buffer-utils");
|
|
20
|
+
const obj_on_disk_1 = require("../../../lib-client/objs-on-disk/obj-on-disk");
|
|
21
21
|
const MAX_GETTING_CHUNK = 512 * 1024;
|
|
22
22
|
const DOWNLOAD_START_CHUNK = 128 * 1024;
|
|
23
|
-
/**
|
|
24
|
-
* Downloader is responsible for getting mail objects from server and placing
|
|
25
|
-
* bytes into cache.
|
|
26
|
-
*/
|
|
27
23
|
class MsgDownloader {
|
|
28
24
|
constructor(msgReceiver) {
|
|
29
25
|
this.msgReceiver = msgReceiver;
|
|
30
|
-
|
|
31
|
-
* Per-object chained downloads.
|
|
32
|
-
* When it comes to the download start, if chain exists, it means that
|
|
33
|
-
* process has already started.
|
|
34
|
-
*/
|
|
35
|
-
this.downloadProcs = new synced_1.NamedProcs();
|
|
26
|
+
this.runner = new obj_on_disk_1.DownloadsRunner();
|
|
36
27
|
Object.freeze(this);
|
|
37
28
|
}
|
|
38
|
-
async sync(msgId, objId, action) {
|
|
39
|
-
const id = `${msgId}/${objId}`;
|
|
40
|
-
return this.downloadProcs.startOrChain(id, action);
|
|
41
|
-
}
|
|
42
29
|
getMsgMeta(msgId) {
|
|
43
|
-
return this.
|
|
30
|
+
return this.msgReceiver.getMsgMeta(msgId);
|
|
44
31
|
}
|
|
45
32
|
getObjDownloader(msgId) {
|
|
46
33
|
return {
|
|
47
|
-
getLayoutWithHeaderAndFirstSegs: objId => this.getLayoutWithHeaderAndFirstSegs(msgId, objId),
|
|
48
|
-
getSegs: (objId, v, start, end) => this.getSegs(msgId, objId, start, end)
|
|
34
|
+
getLayoutWithHeaderAndFirstSegs: (objId, v) => this.getLayoutWithHeaderAndFirstSegs(msgId, objId),
|
|
35
|
+
getSegs: (objId, v, start, end) => this.getSegs(msgId, objId, start, end),
|
|
36
|
+
splitSegsDownloads: (start, end) => (0, obj_on_disk_1.splitSegsDownloads)(start, end, MAX_GETTING_CHUNK),
|
|
37
|
+
schedule: this.runner.schedule.bind(this.runner)
|
|
49
38
|
};
|
|
50
39
|
}
|
|
51
40
|
async getLayoutWithHeaderAndFirstSegs(msgId, objId) {
|
|
52
|
-
|
|
53
|
-
throw new Error(`Message object cannot be null`);
|
|
54
|
-
}
|
|
55
|
-
const { header, segsChunk, segsTotalLen } = await this.sync(msgId, objId, () => this.msgReceiver.getObj(msgId, objId, DOWNLOAD_START_CHUNK));
|
|
41
|
+
const { header, segsChunk, segsTotalLen } = await this.msgReceiver.getObj(msgId, objId, DOWNLOAD_START_CHUNK);
|
|
56
42
|
const layout = {
|
|
57
43
|
sections: [{ src: 'new', ofs: 0, len: segsTotalLen }]
|
|
58
44
|
};
|
|
59
45
|
return { header, segs: segsChunk, layout };
|
|
60
46
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
throw new Error(`Message object cannot have null id`);
|
|
64
|
-
}
|
|
65
|
-
return this.sync(msgId, objId, async () => {
|
|
66
|
-
if ((end - start) < MAX_GETTING_CHUNK) {
|
|
67
|
-
const allBytes = await this.msgReceiver.getObjSegs(msgId, objId, start, end);
|
|
68
|
-
return allBytes;
|
|
69
|
-
}
|
|
70
|
-
else {
|
|
71
|
-
const chunks = [];
|
|
72
|
-
let ofs = start;
|
|
73
|
-
while (ofs < end) {
|
|
74
|
-
const len = Math.min(end - ofs, MAX_GETTING_CHUNK);
|
|
75
|
-
const chunk = await this.msgReceiver.getObjSegs(msgId, objId, ofs, ofs + len);
|
|
76
|
-
chunks.push(chunk);
|
|
77
|
-
ofs += chunk.length;
|
|
78
|
-
}
|
|
79
|
-
return (0, buffer_utils_1.joinByteArrs)(chunks);
|
|
80
|
-
}
|
|
81
|
-
});
|
|
47
|
+
getSegs(msgId, objId, start, end) {
|
|
48
|
+
return this.msgReceiver.getObjSegs(msgId, objId, start, end);
|
|
82
49
|
}
|
|
83
50
|
}
|
|
84
51
|
exports.MsgDownloader = MsgDownloader;
|
|
@@ -1,25 +1,16 @@
|
|
|
1
1
|
import { StorageOwner } from '../../../lib-client/3nstorage/storage-owner';
|
|
2
2
|
import { ObjId } from '../../../lib-client/xsp-fs/common';
|
|
3
|
-
import { ObjDownloader, InitDownloadParts } from '../../../lib-client/objs-on-disk/obj-on-disk';
|
|
4
|
-
import { Layout } from 'xsp-files';
|
|
3
|
+
import { ObjDownloader, InitDownloadParts, Section, Download } from '../../../lib-client/objs-on-disk/obj-on-disk';
|
|
5
4
|
export declare class Downloader implements ObjDownloader {
|
|
6
|
-
private remoteStorage;
|
|
7
|
-
|
|
8
|
-
* Per-object chained downloads.
|
|
9
|
-
* When it comes to the download start, if chain exists, it means that
|
|
10
|
-
* process has already started.
|
|
11
|
-
*/
|
|
12
|
-
private downloadProcs;
|
|
5
|
+
private readonly remoteStorage;
|
|
6
|
+
private readonly runner;
|
|
13
7
|
constructor(remoteStorage: StorageOwner);
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
layout: Layout;
|
|
17
|
-
header: Uint8Array;
|
|
18
|
-
segs?: Uint8Array;
|
|
19
|
-
}>;
|
|
8
|
+
getLayoutWithHeaderAndFirstSegs(objId: ObjId, version: number): Promise<InitDownloadParts>;
|
|
9
|
+
schedule(download: Download): void;
|
|
20
10
|
getSegs(objId: ObjId, version: number, start: number, end: number): Promise<Uint8Array>;
|
|
21
11
|
getCurrentObjVersion(objId: ObjId): Promise<{
|
|
22
12
|
version: number;
|
|
23
13
|
parts: InitDownloadParts;
|
|
24
14
|
}>;
|
|
15
|
+
splitSegsDownloads(start: number, end: number): Section[];
|
|
25
16
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/*
|
|
3
|
-
Copyright (C) 2016 - 2019 3NSoft Inc.
|
|
3
|
+
Copyright (C) 2016 - 2019, 2025 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
|
|
@@ -17,65 +17,42 @@
|
|
|
17
17
|
*/
|
|
18
18
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
19
|
exports.Downloader = void 0;
|
|
20
|
-
const
|
|
21
|
-
const buffer_utils_1 = require("../../../lib-common/buffer-utils");
|
|
20
|
+
const obj_on_disk_1 = require("../../../lib-client/objs-on-disk/obj-on-disk");
|
|
22
21
|
const MAX_GETTING_CHUNK = 512 * 1024;
|
|
23
22
|
const DOWNLOAD_START_CHUNK = 128 * 1024;
|
|
24
23
|
class Downloader {
|
|
25
24
|
constructor(remoteStorage) {
|
|
26
25
|
this.remoteStorage = remoteStorage;
|
|
27
|
-
|
|
28
|
-
* Per-object chained downloads.
|
|
29
|
-
* When it comes to the download start, if chain exists, it means that
|
|
30
|
-
* process has already started.
|
|
31
|
-
*/
|
|
32
|
-
this.downloadProcs = new synced_1.NamedProcs();
|
|
26
|
+
this.runner = new obj_on_disk_1.DownloadsRunner();
|
|
33
27
|
Object.seal(this);
|
|
34
28
|
}
|
|
35
|
-
async
|
|
36
|
-
const
|
|
37
|
-
|
|
29
|
+
async getLayoutWithHeaderAndFirstSegs(objId, version) {
|
|
30
|
+
const { header, segsTotalLen, version: currentVersion, segsChunk } = await this.remoteStorage.getCurrentObj(objId, DOWNLOAD_START_CHUNK);
|
|
31
|
+
// XXX this gets current version, but it will have to change to getting
|
|
32
|
+
// just version. It will be seen, if version's state needs passing.
|
|
33
|
+
if (currentVersion !== version) {
|
|
34
|
+
throw new Error(`Current version on server is ${currentVersion} while request was for ${version}`);
|
|
35
|
+
}
|
|
36
|
+
const layout = {
|
|
37
|
+
sections: [{ src: 'new', ofs: 0, len: segsTotalLen }]
|
|
38
|
+
};
|
|
39
|
+
return { header, segs: segsChunk, layout };
|
|
38
40
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
// XXX this gets current version, but it will have to change to getting
|
|
42
|
-
// just version. It will be seen, if version's state needs passing.
|
|
43
|
-
const { header, segsTotalLen, version, segsChunk } = await this.remoteStorage.getCurrentObj(objId, DOWNLOAD_START_CHUNK);
|
|
44
|
-
const layout = {
|
|
45
|
-
sections: [{ src: 'new', ofs: 0, len: segsTotalLen }]
|
|
46
|
-
};
|
|
47
|
-
return { header, segs: segsChunk, layout };
|
|
48
|
-
});
|
|
41
|
+
schedule(download) {
|
|
42
|
+
this.runner.schedule(download);
|
|
49
43
|
}
|
|
50
44
|
getSegs(objId, version, start, end) {
|
|
51
|
-
|
|
52
|
-
// just version. It will be seen, if version's state needs passing.
|
|
53
|
-
return this.sync(objId, version, async () => {
|
|
54
|
-
if ((end - start) < MAX_GETTING_CHUNK) {
|
|
55
|
-
const allBytes = await this.remoteStorage.getCurrentObjSegs(objId, version, start, end);
|
|
56
|
-
return allBytes;
|
|
57
|
-
}
|
|
58
|
-
else {
|
|
59
|
-
const chunks = [];
|
|
60
|
-
let ofs = start;
|
|
61
|
-
while (ofs < end) {
|
|
62
|
-
const len = Math.min(end - ofs, MAX_GETTING_CHUNK);
|
|
63
|
-
const chunk = await this.remoteStorage.getCurrentObjSegs(objId, version, ofs, ofs + len);
|
|
64
|
-
chunks.push(chunk);
|
|
65
|
-
ofs += chunk.length;
|
|
66
|
-
}
|
|
67
|
-
return (0, buffer_utils_1.joinByteArrs)(chunks);
|
|
68
|
-
}
|
|
69
|
-
});
|
|
45
|
+
return this.remoteStorage.getCurrentObjSegs(objId, version, start, end);
|
|
70
46
|
}
|
|
71
47
|
async getCurrentObjVersion(objId) {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
48
|
+
const { header, segsTotalLen, version, segsChunk: segs } = await this.remoteStorage.getCurrentObj(objId, DOWNLOAD_START_CHUNK);
|
|
49
|
+
const layout = {
|
|
50
|
+
sections: [{ src: 'new', ofs: 0, len: segsTotalLen }]
|
|
51
|
+
};
|
|
52
|
+
return { version, parts: { header, segs, layout } };
|
|
53
|
+
}
|
|
54
|
+
splitSegsDownloads(start, end) {
|
|
55
|
+
return (0, obj_on_disk_1.splitSegsDownloads)(start, end, MAX_GETTING_CHUNK);
|
|
79
56
|
}
|
|
80
57
|
}
|
|
81
58
|
exports.Downloader = Downloader;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Observable } from 'rxjs';
|
|
2
|
-
import { ObjId, SyncedObjStatus } from '../../../lib-client/xsp-fs/common';
|
|
2
|
+
import { DownloadEventSink, ObjId, SyncedObjStatus } from '../../../lib-client/xsp-fs/common';
|
|
3
3
|
import { InitDownloadParts } from '../../../lib-client/objs-on-disk/obj-on-disk';
|
|
4
4
|
import { ObjSource, Subscribe } from 'xsp-files';
|
|
5
5
|
import { Downloader } from './downloader';
|
|
@@ -91,5 +91,7 @@ export declare class SyncedObj {
|
|
|
91
91
|
recordRemovalUploadAndGC(): Promise<void>;
|
|
92
92
|
isRemoteVersionOnDisk(version: number): Promise<'complete' | 'partial' | 'none'>;
|
|
93
93
|
getNumOfBytesNeedingDownload(version: number): Promise<number | 'unknown'>;
|
|
94
|
-
|
|
94
|
+
startDownloadProcess(version: number, eventSink: DownloadEventSink): Promise<{
|
|
95
|
+
downloadTaskId: number;
|
|
96
|
+
} | undefined>;
|
|
95
97
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/*
|
|
3
|
-
Copyright (C) 2016 - 2020, 2022 3NSoft Inc.
|
|
3
|
+
Copyright (C) 2016 - 2020, 2022, 2025 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
|
|
@@ -128,9 +128,8 @@ class ObjFiles {
|
|
|
128
128
|
// Should it be a pattern: version not in status -> get info first.
|
|
129
129
|
async makeByDownloadingCurrentVersion(objId) {
|
|
130
130
|
// initial download implicitly checks existence of obj on server
|
|
131
|
-
const
|
|
132
|
-
|
|
133
|
-
return obj;
|
|
131
|
+
const initDownload = await this.downloader.getCurrentObjVersion(objId);
|
|
132
|
+
return await this.makeObj(objId, initDownload);
|
|
134
133
|
}
|
|
135
134
|
async saveFirstVersion(objId, encSub) {
|
|
136
135
|
const newObj = await this.makeObj(objId);
|
|
@@ -406,7 +405,7 @@ class SyncedObj {
|
|
|
406
405
|
return 'none';
|
|
407
406
|
}
|
|
408
407
|
const objVer = await this.instanceOfRemoteObjVer(version);
|
|
409
|
-
return (objVer.doesFileNeedDownload() ? '
|
|
408
|
+
return (objVer.doesFileNeedDownload() ? 'partial' : 'complete');
|
|
410
409
|
}
|
|
411
410
|
async getNumOfBytesNeedingDownload(version) {
|
|
412
411
|
if (!this.status.isAmongRemote(version)) {
|
|
@@ -424,9 +423,10 @@ class SyncedObj {
|
|
|
424
423
|
const objVer = await this.instanceOfRemoteObjVer(version);
|
|
425
424
|
return objVer.numOfBytesNeedingDownload();
|
|
426
425
|
}
|
|
427
|
-
async
|
|
426
|
+
async startDownloadProcess(version, eventSink) {
|
|
428
427
|
const objVer = await this.instanceOfRemoteObjVer(version);
|
|
429
|
-
|
|
428
|
+
const downloadTaskId = objVer.startDownloadInBackground(eventSink);
|
|
429
|
+
return (downloadTaskId ? { downloadTaskId } : undefined);
|
|
430
430
|
}
|
|
431
431
|
}
|
|
432
432
|
exports.SyncedObj = SyncedObj;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { IGetMailerIdSigner } from '../../../lib-client/user-with-mid-session';
|
|
2
|
-
import { SyncedStorage as ISyncedStorage, NodesContainer, Storage as IStorage, StorageGetter, ObjId, NodeEvent, SyncedObjStatus } from '../../../lib-client/xsp-fs/common';
|
|
2
|
+
import { SyncedStorage as ISyncedStorage, NodesContainer, Storage as IStorage, StorageGetter, ObjId, NodeEvent, SyncedObjStatus, DownloadEventSink } from '../../../lib-client/xsp-fs/common';
|
|
3
3
|
import { ScryptGenParams } from '../../../lib-client/key-derivation';
|
|
4
4
|
import { LogError } from '../../../lib-client/logging/log-to-file';
|
|
5
5
|
import { AsyncSBoxCryptor, Subscribe, ObjSource } from 'xsp-files';
|
|
@@ -39,7 +39,9 @@ export declare class SyncedStore implements ISyncedStorage {
|
|
|
39
39
|
adoptRemote(objId: ObjId, opts: OptionsToAdopteRemote | undefined): Promise<number | undefined>;
|
|
40
40
|
updateStatusInfo(objId: ObjId): Promise<SyncStatus>;
|
|
41
41
|
isRemoteVersionOnDisk(objId: ObjId, version: number): Promise<'complete' | 'partial' | 'none'>;
|
|
42
|
-
|
|
42
|
+
startDownload(objId: ObjId, version: number, eventSink: DownloadEventSink): Promise<{
|
|
43
|
+
downloadTaskId: number;
|
|
44
|
+
} | undefined>;
|
|
43
45
|
startUpload(objId: ObjId, localVersion: number, uploadVersion: number, uploadHeader: UploadHeaderChange | undefined, createOnRemote: boolean, eventSink: (event: UploadEvent) => void): Promise<{
|
|
44
46
|
uploadTaskId: number;
|
|
45
47
|
completion: Promise<void>;
|
|
@@ -118,9 +118,9 @@ class SyncedStore {
|
|
|
118
118
|
const obj = await this.getObjOrThrow(objId, true);
|
|
119
119
|
return obj.isRemoteVersionOnDisk(version);
|
|
120
120
|
}
|
|
121
|
-
async
|
|
121
|
+
async startDownload(objId, version, eventSink) {
|
|
122
122
|
const obj = await this.getObjOrThrow(objId, true);
|
|
123
|
-
return obj.
|
|
123
|
+
return obj.startDownloadProcess(version, eventSink);
|
|
124
124
|
}
|
|
125
125
|
async startUpload(objId, localVersion, uploadVersion, uploadHeader, createOnRemote, eventSink) {
|
|
126
126
|
const obj = await this.getObjOrThrow(objId, true);
|
|
@@ -4,8 +4,7 @@ import { MonoTypeOperatorFunction } from "rxjs";
|
|
|
4
4
|
import { FileWrite } from "../../../lib-client/objs-on-disk/file-writing-proc";
|
|
5
5
|
import { LogError } from "../../../lib-client/logging/log-to-file";
|
|
6
6
|
import { NewVersionUpload } from "./obj-status";
|
|
7
|
-
import { UploadHeaderChange } from "../../../lib-client/xsp-fs/common";
|
|
8
|
-
type UploadEvent = web3n.files.UploadEvent;
|
|
7
|
+
import { UploadEventSink, UploadHeaderChange } from "../../../lib-client/xsp-fs/common";
|
|
9
8
|
export type FileWriteTapOperator = MonoTypeOperatorFunction<FileWrite[]>;
|
|
10
9
|
export declare class UpSyncer {
|
|
11
10
|
private readonly remoteStorage;
|
|
@@ -23,7 +22,7 @@ export declare class UpSyncer {
|
|
|
23
22
|
*/
|
|
24
23
|
tapFileWrite(obj: SyncedObj, isNew: boolean, newVersion: number, baseVersion?: number): FileWriteTapOperator;
|
|
25
24
|
removeCurrentVersionOf(obj: SyncedObj): Promise<void>;
|
|
26
|
-
startUploadFromDisk(obj: SyncedObj, localVersion: number, uploadVersion: number, uploadHeader: UploadHeaderChange | undefined, createOnRemote: boolean, eventSink:
|
|
25
|
+
startUploadFromDisk(obj: SyncedObj, localVersion: number, uploadVersion: number, uploadHeader: UploadHeaderChange | undefined, createOnRemote: boolean, eventSink: UploadEventSink | undefined): Promise<{
|
|
27
26
|
completion: Promise<void>;
|
|
28
27
|
uploadTaskId: number;
|
|
29
28
|
}>;
|
|
@@ -33,4 +32,3 @@ export interface UploadStatusRecorder {
|
|
|
33
32
|
recordUploadCancellation(info: NewVersionUpload): Promise<void>;
|
|
34
33
|
recordUploadInterimState(info: NewVersionUpload): Promise<void>;
|
|
35
34
|
}
|
|
36
|
-
export {};
|
|
@@ -88,7 +88,7 @@ class UpSyncer {
|
|
|
88
88
|
if (uploadHeader) {
|
|
89
89
|
await obj.saveUploadHeaderFile(uploadHeader);
|
|
90
90
|
}
|
|
91
|
-
const task = await UploadTask.for(obj, localVersion, uploadVersion, uploadHeader === null || uploadHeader === void 0 ? void 0 : uploadHeader.uploadHeader, syncedBase, createOnRemote, uploadTaskId, eventSink, this.remoteStorage,
|
|
91
|
+
const task = await UploadTask.for(obj, localVersion, uploadVersion, uploadHeader === null || uploadHeader === void 0 ? void 0 : uploadHeader.uploadHeader, syncedBase, createOnRemote, uploadTaskId, eventSink, this.remoteStorage, async () => {
|
|
92
92
|
if (this.tasksByIds.delete(task.taskId)) {
|
|
93
93
|
this.tasksByObjIds.delete(task.objId);
|
|
94
94
|
}
|
|
@@ -113,13 +113,12 @@ exports.UpSyncer = UpSyncer;
|
|
|
113
113
|
Object.freeze(UpSyncer.prototype);
|
|
114
114
|
Object.freeze(UpSyncer);
|
|
115
115
|
class UploadTask {
|
|
116
|
-
constructor(taskId, remoteStorage, objId, objStatus, src,
|
|
116
|
+
constructor(taskId, remoteStorage, objId, objStatus, src, info, uploadHeader, doAtCompletion, eventSink) {
|
|
117
117
|
this.taskId = taskId;
|
|
118
118
|
this.remoteStorage = remoteStorage;
|
|
119
119
|
this.objId = objId;
|
|
120
120
|
this.objStatus = objStatus;
|
|
121
121
|
this.src = src;
|
|
122
|
-
this.execPools = execPools;
|
|
123
122
|
this.info = info;
|
|
124
123
|
this.uploadHeader = uploadHeader;
|
|
125
124
|
this.doAtCompletion = doAtCompletion;
|
|
@@ -130,7 +129,7 @@ class UploadTask {
|
|
|
130
129
|
this.emitUploadEvent('upload-started', { totalBytesToUpload: this.totalBytesToUpload });
|
|
131
130
|
Object.seal(this);
|
|
132
131
|
}
|
|
133
|
-
static async for(obj, localVersion, uploadVersion, uploadHeader, syncedBase, createObj, taskId, eventSink, remoteStorage,
|
|
132
|
+
static async for(obj, localVersion, uploadVersion, uploadHeader, syncedBase, createObj, taskId, eventSink, remoteStorage, doAtCompletion) {
|
|
134
133
|
const src = await obj.getObjSrcFromLocalAndSyncedBranch(localVersion);
|
|
135
134
|
let needUpload;
|
|
136
135
|
if (syncedBase) {
|
|
@@ -149,7 +148,7 @@ class UploadTask {
|
|
|
149
148
|
};
|
|
150
149
|
const objStatus = obj.statusObj();
|
|
151
150
|
await objStatus.recordUploadStart(info);
|
|
152
|
-
return new UploadTask(taskId, remoteStorage, obj.objId, objStatus, src,
|
|
151
|
+
return new UploadTask(taskId, remoteStorage, obj.objId, objStatus, src, info, uploadHeader, doAtCompletion, eventSink);
|
|
153
152
|
}
|
|
154
153
|
neededExecutor() {
|
|
155
154
|
return (!this.info.needUpload ? undefined : this.execLabel);
|
|
@@ -158,7 +157,8 @@ class UploadTask {
|
|
|
158
157
|
return this.uploadCompletion.promise;
|
|
159
158
|
}
|
|
160
159
|
emitUploadEvent(type, fields) {
|
|
161
|
-
|
|
160
|
+
var _a;
|
|
161
|
+
(_a = this.eventSink) === null || _a === void 0 ? void 0 : _a.call(this, {
|
|
162
162
|
type,
|
|
163
163
|
localVersion: this.info.localVersion,
|
|
164
164
|
uploadTaskId: this.taskId,
|
|
@@ -169,7 +169,7 @@ class UploadTask {
|
|
|
169
169
|
}
|
|
170
170
|
async process() {
|
|
171
171
|
if (!this.info.needUpload) {
|
|
172
|
-
return;
|
|
172
|
+
return true;
|
|
173
173
|
}
|
|
174
174
|
try {
|
|
175
175
|
const upload = this.info.needUpload;
|
|
@@ -194,17 +194,22 @@ class UploadTask {
|
|
|
194
194
|
}
|
|
195
195
|
await this.objStatus.recordUploadInterimState(this.info);
|
|
196
196
|
if (this.info.needUpload) {
|
|
197
|
-
this.
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
197
|
+
if (this.eventSink) {
|
|
198
|
+
this.emitUploadEvent('upload-progress', {
|
|
199
|
+
totalBytesToUpload: this.totalBytesToUpload,
|
|
200
|
+
bytesLeftToUpload: (0, obj_status_1.countBytesIn)(this.info)
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
return false;
|
|
202
204
|
}
|
|
203
205
|
else {
|
|
204
206
|
await this.doAtCompletion().finally(() => {
|
|
205
207
|
this.uploadCompletion.resolve();
|
|
206
|
-
this.
|
|
208
|
+
if (this.eventSink) {
|
|
209
|
+
this.emitUploadEvent('upload-done', {});
|
|
210
|
+
}
|
|
207
211
|
});
|
|
212
|
+
return true;
|
|
208
213
|
}
|
|
209
214
|
}
|
|
210
215
|
catch (exc) {
|
|
@@ -215,6 +220,7 @@ class UploadTask {
|
|
|
215
220
|
cause: exc
|
|
216
221
|
}));
|
|
217
222
|
await this.objStatus.recordUploadCancellation(this.info);
|
|
223
|
+
return true;
|
|
218
224
|
}
|
|
219
225
|
}
|
|
220
226
|
async startOrderedUpload(upload) {
|
package/build/core-ipc/file.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { ProtoType } from '../lib-client/protobuf-type';
|
|
|
3
3
|
import { ExposedFn, EnvelopeBody, Caller, CoreSideServices } from "../ipc-via-protobuf/connector";
|
|
4
4
|
type ReadonlyFile = web3n.files.ReadonlyFile;
|
|
5
5
|
type ReadonlyFileVersionedAPI = web3n.files.ReadonlyFileVersionedAPI;
|
|
6
|
+
type ReadonlyFileSyncAPI = web3n.files.ReadonlyFileSyncAPI;
|
|
6
7
|
type WritableFile = web3n.files.WritableFile;
|
|
7
8
|
type WritableFileVersionedAPI = web3n.files.WritableFileVersionedAPI;
|
|
8
9
|
type WritableFileSyncAPI = web3n.files.WritableFileSyncAPI;
|
|
@@ -147,6 +148,15 @@ export declare namespace vGetByteSink {
|
|
|
147
148
|
function wrapService(fn: WritableFileVersionedAPI['getByteSink'], expServices: CoreSideServices): ExposedFn;
|
|
148
149
|
function makeCaller(caller: Caller, objPath: string[]): WritableFileVersionedAPI['getByteSink'];
|
|
149
150
|
}
|
|
151
|
+
export declare namespace vsStartDownload {
|
|
152
|
+
const replyType: ProtoType<{
|
|
153
|
+
startedDownload?: {
|
|
154
|
+
downloadTaskId: number;
|
|
155
|
+
};
|
|
156
|
+
}>;
|
|
157
|
+
function wrapService(fn: ReadonlyFileSyncAPI['startDownload']): ExposedFn;
|
|
158
|
+
function makeCaller(caller: Caller, objPath: string[]): ReadonlyFileSyncAPI['startDownload'];
|
|
159
|
+
}
|
|
150
160
|
export interface OptionsToUploadLocalMsg {
|
|
151
161
|
localVersion?: Value<number>;
|
|
152
162
|
uploadVersion?: Value<number>;
|