core-3nweb-client-lib 0.25.3 → 0.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/README.md +2 -2
  2. package/build/api-defs/files.d.ts +23 -20
  3. package/build/core/asmail/config/common.js +2 -2
  4. package/build/core/asmail/delivery/index.js +4 -3
  5. package/build/core/asmail/delivery/msg.js +5 -4
  6. package/build/core/asmail/delivery/per-recipient-wip.js +2 -2
  7. package/build/core/asmail/inbox/attachments/fs.js +6 -0
  8. package/build/core/asmail/inbox/cached-msgs.js +2 -2
  9. package/build/core/asmail/inbox/inbox-events.js +2 -1
  10. package/build/core/asmail/inbox/index.js +2 -2
  11. package/build/core/asmail/inbox/msg-downloader.js +2 -2
  12. package/build/core/asmail/inbox/msg-indexing.js +3 -3
  13. package/build/core/asmail/inbox/msg-on-disk.js +2 -2
  14. package/build/core/asmail/keyring/keyring-storage.js +2 -2
  15. package/build/core/asmail/sending-params/own-params.js +2 -2
  16. package/build/core/asmail/sending-params/params-from-others.js +2 -2
  17. package/build/core/id-manager.js +2 -2
  18. package/build/core/sign-in.d.ts +5 -4
  19. package/build/core/sign-in.js +9 -11
  20. package/build/core/sign-up.d.ts +1 -0
  21. package/build/core/sign-up.js +7 -3
  22. package/build/core/storage/common/json-saving.d.ts +21 -0
  23. package/build/core/storage/common/json-saving.js +82 -0
  24. package/build/core/storage/common/obj-info-file.d.ts +43 -0
  25. package/build/core/storage/common/obj-info-file.js +119 -3
  26. package/build/core/storage/index.js +1 -1
  27. package/build/core/storage/local/obj-files-gc.js +8 -6
  28. package/build/core/storage/local/obj-files.d.ts +3 -3
  29. package/build/core/storage/local/obj-files.js +9 -9
  30. package/build/core/storage/local/obj-status.d.ts +9 -25
  31. package/build/core/storage/local/obj-status.js +28 -110
  32. package/build/core/storage/local/storage.d.ts +8 -1
  33. package/build/core/storage/local/storage.js +10 -2
  34. package/build/core/storage/synced/downloader.js +6 -5
  35. package/build/core/storage/synced/obj-files-gc.d.ts +1 -0
  36. package/build/core/storage/synced/obj-files-gc.js +44 -5
  37. package/build/core/storage/synced/obj-files.d.ts +13 -20
  38. package/build/core/storage/synced/obj-files.js +70 -48
  39. package/build/core/storage/synced/obj-status.d.ts +74 -15
  40. package/build/core/storage/synced/obj-status.js +291 -107
  41. package/build/core/storage/synced/remote-events.js +32 -26
  42. package/build/core/storage/synced/storage.d.ts +11 -1
  43. package/build/core/storage/synced/storage.js +28 -3
  44. package/build/core/storage/synced/upsyncer.d.ts +8 -7
  45. package/build/core/storage/synced/upsyncer.js +211 -163
  46. package/build/ipc-via-protobuf/asmail-cap.js +17 -34
  47. package/build/ipc-via-protobuf/connector-clients-side.js +2 -2
  48. package/build/ipc-via-protobuf/file.js +26 -18
  49. package/build/ipc-via-protobuf/fs.js +33 -35
  50. package/build/ipc-via-protobuf/mailerid.js +3 -2
  51. package/build/ipc-via-protobuf/protobuf-msg.d.ts +2 -0
  52. package/build/ipc-via-protobuf/protobuf-msg.js +11 -1
  53. package/build/ipc-via-protobuf/startup-cap.js +5 -5
  54. package/build/lib-client/3nstorage/exceptions.d.ts +9 -8
  55. package/build/lib-client/3nstorage/exceptions.js +18 -9
  56. package/build/lib-client/3nstorage/service.js +10 -6
  57. package/build/lib-client/3nstorage/xsp-fs/common.d.ts +18 -4
  58. package/build/lib-client/3nstorage/xsp-fs/common.js +6 -1
  59. package/build/lib-client/3nstorage/xsp-fs/file-node.js +3 -3
  60. package/build/lib-client/3nstorage/xsp-fs/file.js +4 -1
  61. package/build/lib-client/3nstorage/xsp-fs/folder-node.js +27 -13
  62. package/build/lib-client/3nstorage/xsp-fs/fs.d.ts +11 -6
  63. package/build/lib-client/3nstorage/xsp-fs/fs.js +189 -58
  64. package/build/lib-client/3nstorage/xsp-fs/node-in-fs.d.ts +4 -0
  65. package/build/lib-client/3nstorage/xsp-fs/node-in-fs.js +51 -24
  66. package/build/lib-client/3nstorage/xsp-fs/node-persistence.js +2 -2
  67. package/build/lib-client/3nstorage/xsp-fs/xsp-payload-v1.js +2 -2
  68. package/build/lib-client/3nstorage/xsp-fs/xsp-payload-v2.js +3 -3
  69. package/build/lib-client/cryptor/cryptor-in-worker.js +4 -4
  70. package/build/lib-client/cryptor/cryptor-wasm.js +1 -1
  71. package/build/lib-client/cryptor/cryptor.wasm +0 -0
  72. package/build/lib-client/cryptor/in-proc-wasm.js +2 -2
  73. package/build/lib-client/files.js +2 -0
  74. package/build/lib-client/fs-collection.js +3 -2
  75. package/build/lib-client/logging/log-to-file.js +6 -14
  76. package/build/lib-client/objs-on-disk/file-writing-proc.js +2 -2
  77. package/build/lib-client/objs-on-disk/obj-folders.d.ts +12 -1
  78. package/build/lib-client/objs-on-disk/obj-folders.js +26 -19
  79. package/build/lib-client/request-utils.js +2 -2
  80. package/build/lib-client/server-events.js +4 -3
  81. package/build/lib-client/ws-utils.js +2 -2
  82. package/build/lib-common/async-fs-node.d.ts +6 -0
  83. package/build/lib-common/async-fs-node.js +28 -4
  84. package/build/lib-common/byte-streaming/wrapping.js +17 -17
  85. package/build/lib-common/exceptions/file.js +6 -1
  86. package/build/lib-common/ipc/generic-ipc.js +2 -2
  87. package/build/lib-common/json-utils.js +2 -1
  88. package/build/lib-common/objs-on-disk/obj-file.js +4 -3
  89. package/build/lib-common/objs-on-disk/utils.js +2 -2
  90. package/build/lib-common/processes/deferred.d.ts +6 -0
  91. package/build/lib-common/processes/deferred.js +30 -0
  92. package/build/lib-common/processes/labelled-exec-pools.d.ts +33 -0
  93. package/build/lib-common/processes/labelled-exec-pools.js +141 -0
  94. package/build/lib-common/processes/pressure.d.ts +7 -0
  95. package/build/lib-common/processes/pressure.js +56 -0
  96. package/build/lib-common/processes/sleep.d.ts +1 -0
  97. package/build/lib-common/processes/sleep.js +26 -0
  98. package/build/lib-common/{processes.d.ts → processes/synced.d.ts} +0 -40
  99. package/build/lib-common/{processes.js → processes/synced.js} +187 -204
  100. package/build/lib-common/processes/timeout.d.ts +1 -0
  101. package/build/lib-common/processes/timeout.js +51 -0
  102. package/build/lib-common/service-api/3nstorage/owner.d.ts +5 -4
  103. package/build/lib-common/service-api/3nstorage/owner.js +3 -2
  104. package/build/lib-common/utils-for-observables.d.ts +15 -1
  105. package/build/lib-common/utils-for-observables.js +68 -17
  106. package/build/protos/asmail.proto.js +404 -78
  107. package/build/protos/file.proto.js +370 -44
  108. package/build/protos/fs.proto.js +404 -78
  109. package/package.json +4 -4
  110. package/protos/file.proto +10 -2
  111. package/protos/fs.proto +2 -2
  112. package/build/core/storage/synced/upsync-status.d.ts +0 -41
  113. 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 processes_1 = require("../../../lib-common/processes");
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 processes_1.SingleProc();
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
- // XXX
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(version: number): Promise<void>;
81
- setSyncedCurrentVersion(version: number): Promise<void>;
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 = exports.UNSYNCED_REMOVAL = exports.UPLOAD_INFO_FNAME = exports.UNSYNCED_FILE_NAME_EXT = void 0;
19
+ exports.SyncedObj = exports.ObjFiles = void 0;
20
20
  const rxjs_1 = require("rxjs");
21
- const processes_1 = require("../../../lib-common/processes");
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
- * This is an extention for an unsynced version file. File name starts with a
34
- * version number.
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(exports.UNSYNCED_FILE_NAME_EXT)
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 processes_1.sleep(20);
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 processes_1.NamedProcs();
153
+ proc = new synced_1.NamedProcs();
159
154
  }
160
155
  async function sync(objId, action) {
161
- const id = (!objId ? '==root==' : objId);
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
- const status = await obj_status_1.ObjStatus.makeForDownloadedVersion(objFolder, objId, version);
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, false);
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
- path(version, synced) {
254
- const fName = (synced ?
255
- `${version}.v` : `${version}.${exports.UNSYNCED_FILE_NAME_EXT}`);
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(undefined, err => {
301
- if (this.verObjs.get(version) === obj) {
302
- this.verObjs.delete(version);
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
- this.scheduleGC(this);
325
+ async setUnsyncedCurrentVersion(version, baseVersion) {
326
+ await this.status.setUnsyncedCurrentVersion(version, baseVersion);
327
+ if (version > 1) {
328
+ this.scheduleSelfGC();
329
+ }
322
330
  }
323
- async setSyncedCurrentVersion(version) {
324
- await this.status.setSyncedCurrentVersion(version);
325
- this.scheduleGC(this);
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.scheduleGC(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
- deletedOnRemote?: boolean;
18
- syncState: SyncState;
19
- versions: {
20
- latestSynced?: number;
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
- gcWorkInfo?: object;
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 declare class ObjStatus {
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
- setSyncedCurrentVersion(version: number): Promise<void>;
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 {};