@gudhub/core 1.2.4-beta.3 → 1.2.4-beta.30
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/GUDHUB/AppProcessor/AppProcessor.js +62 -24
- package/GUDHUB/ChunksManager/ChunksManager.js +61 -61
- package/GUDHUB/ChunksManager/ChunksManager.test.js +8 -4
- package/GUDHUB/DataService/AppDataService.js +232 -0
- package/GUDHUB/DataService/ChunkDataService.js +10 -0
- package/GUDHUB/DataService/IndexedDB/IndexedDBAppService.js +799 -63
- package/GUDHUB/DataService/IndexedDB/IndexedDBChunkService.js +303 -46
- package/GUDHUB/DataService/IndexedDB/IndexedDBService.js +342 -2
- package/GUDHUB/DataService/IndexedDB/StoreManager/BaseStoreManager.js +124 -0
- package/GUDHUB/DataService/IndexedDB/StoreManager/managers.js +113 -0
- package/GUDHUB/DataService/IndexedDB/appDataConf.js +6 -3
- package/GUDHUB/DataService/IndexedDB/appRequestWorker.js +225 -0
- package/GUDHUB/DataService/IndexedDB/chunkDataConf.js +3 -3
- package/GUDHUB/DataService/IndexedDB/consts.js +3 -1
- package/GUDHUB/DataService/IndexedDB/init.js +15 -14
- package/GUDHUB/DataService/IndexedDB/storeManagerConf/chunkCacheStoreManagerConf.js +11 -0
- package/GUDHUB/DataService/IndexedDB/storeManagerConf/init.js +1 -0
- package/GUDHUB/DataService/export.js +8 -5
- package/GUDHUB/DataService/httpService/AppHttpService.js +22 -4
- package/GUDHUB/DataService/httpService/ChunkHttpService.js +19 -2
- package/GUDHUB/DataService/utils.js +104 -1
- package/GUDHUB/FileManager/FileManager.js +7 -3
- package/GUDHUB/GHConstructor/createAngularModuleInstance.js +3 -3
- package/GUDHUB/GHConstructor/createClassInstance.js +3 -3
- package/GUDHUB/ItemProcessor/ItemProcessor.js +24 -0
- package/GUDHUB/Storage/ModulesList.js +18 -2
- package/GUDHUB/Utils/AppsTemplateService/AppsTemplateService.js +37 -1
- package/GUDHUB/Utils/Utils.js +29 -1
- package/GUDHUB/Utils/merge_chunks/merge_chunks.js +36 -28
- package/GUDHUB/Utils/merge_chunks/merge_chunks.worker.js +78 -0
- package/GUDHUB/Utils/merge_compare_items/merge_compare_items.js +40 -9
- package/GUDHUB/WebSocket/WebSocket.js +2 -1
- package/GUDHUB/consts.js +21 -1
- package/GUDHUB/gudhub.js +39 -14
- package/appRequestWorker.js +1 -0
- package/appRequestWorker.js.LICENSE.txt +13 -0
- package/appRequestWorker.js.map +1 -0
- package/package.json +17 -6
- package/umd/appRequestWorker.js +1 -0
- package/umd/library.min.js +1 -300
- package/webpack.config.js +154 -0
- package/.vscode/launch.json +0 -31
- package/umd/library.min.js.map +0 -1
|
@@ -2,7 +2,14 @@ import { AppDataService } from "../AppDataService.js";
|
|
|
2
2
|
import { ChunkDataService } from "../ChunkDataService.js"; // removed "ChunkCacheDataService" from imported because it was causing an error "{ ChunkCacheDataService } not found in exported names" in "gudhub-node-server"
|
|
3
3
|
import { AppHttpService } from "../httpService/AppHttpService.js";
|
|
4
4
|
import { objectAssignWithOverride } from "../utils.js";
|
|
5
|
-
import { IndexedDBService } from "./IndexedDBService.js";
|
|
5
|
+
import { IndexedDBManager, IndexedDBService } from "./IndexedDBService.js";
|
|
6
|
+
|
|
7
|
+
import { IndexedDBChunkService } from "./IndexedDBChunkService.js";
|
|
8
|
+
import { chunksConf } from "./chunkDataConf.js";
|
|
9
|
+
import { AppStoreManager } from "./StoreManager/managers.js";
|
|
10
|
+
import { dbName, dbVersion } from "./consts.js";
|
|
11
|
+
import { appsConf } from "./appDataConf.js";
|
|
12
|
+
import { chunksMergeConf } from "./storeManagerConf/chunkCacheStoreManagerConf.js";
|
|
6
13
|
|
|
7
14
|
|
|
8
15
|
//this should be global in project
|
|
@@ -10,25 +17,204 @@ import { IndexedDBService } from "./IndexedDBService.js";
|
|
|
10
17
|
|
|
11
18
|
// }
|
|
12
19
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class IndexedDBManager1 {
|
|
23
|
+
constructor(dbName, storeName) {
|
|
24
|
+
this.dbName = dbName;
|
|
25
|
+
this.storeName = storeName;
|
|
26
|
+
this.db = null;
|
|
27
|
+
this.queue = [];
|
|
28
|
+
this.isProcessing = false;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async openDB() {
|
|
32
|
+
if (this.db) return this.db;
|
|
33
|
+
|
|
34
|
+
return new Promise((resolve, reject) => {
|
|
35
|
+
const request = indexedDB.open(this.dbName, 1);
|
|
36
|
+
|
|
37
|
+
request.onupgradeneeded = (event) => {
|
|
38
|
+
const db = event.target.result;
|
|
39
|
+
if (!db.objectStoreNames.contains(this.storeName)) {
|
|
40
|
+
db.createObjectStore(this.storeName, { keyPath: 'id', autoIncrement: true });
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
request.onsuccess = (event) => {
|
|
45
|
+
this.db = event.target.result;
|
|
46
|
+
resolve(this.db);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
request.onerror = (event) => {
|
|
50
|
+
reject(event.target.error);
|
|
51
|
+
};
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async executeOperation(operation) {
|
|
56
|
+
await this.openDB();
|
|
57
|
+
return new Promise((resolve, reject) => {
|
|
58
|
+
const transaction = this.db.transaction(this.storeName, 'readwrite');
|
|
59
|
+
const store = transaction.objectStore(this.storeName);
|
|
60
|
+
|
|
61
|
+
transaction.oncomplete = () => resolve();
|
|
62
|
+
transaction.onerror = (event) => reject(event.target.error);
|
|
63
|
+
|
|
64
|
+
operation(store);
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async enqueueOperation(operation) {
|
|
69
|
+
this.queue.push(operation);
|
|
70
|
+
|
|
71
|
+
if (!this.isProcessing) {
|
|
72
|
+
this.isProcessing = true;
|
|
73
|
+
while (this.queue.length > 0) {
|
|
74
|
+
const currentOperation = this.queue.shift();
|
|
75
|
+
try {
|
|
76
|
+
await this.executeOperation(currentOperation);
|
|
77
|
+
} catch (error) {
|
|
78
|
+
console.error('Operation failed:', error);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
this.isProcessing = false;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
class IndexedDBManager2 {
|
|
91
|
+
constructor(dbName, storeName) {
|
|
92
|
+
this.dbName = dbName;
|
|
93
|
+
this.storeName = storeName;
|
|
94
|
+
this.db = null;
|
|
95
|
+
this.queue = [];
|
|
96
|
+
this.isProcessing = false;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
async openDB() {
|
|
100
|
+
if (this.db) return this.db;
|
|
101
|
+
|
|
102
|
+
return new Promise((resolve, reject) => {
|
|
103
|
+
const request = indexedDB.open(this.dbName, 1);
|
|
104
|
+
|
|
105
|
+
request.onupgradeneeded = (event) => {
|
|
106
|
+
const db = event.target.result;
|
|
107
|
+
if (!db.objectStoreNames.contains(this.storeName)) {
|
|
108
|
+
db.createObjectStore(this.storeName, { keyPath: 'id', autoIncrement: true });
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
request.onsuccess = (event) => {
|
|
113
|
+
this.db = event.target.result;
|
|
114
|
+
resolve(this.db);
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
request.onerror = (event) => {
|
|
118
|
+
reject(event.target.error);
|
|
119
|
+
};
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
async executeOperation(operation) {
|
|
124
|
+
await this.openDB();
|
|
125
|
+
return new Promise((resolve, reject) => {
|
|
126
|
+
const transaction = this.db.transaction(this.storeName, 'readwrite');
|
|
127
|
+
const store = transaction.objectStore(this.storeName);
|
|
128
|
+
|
|
129
|
+
transaction.oncomplete = () => resolve();
|
|
130
|
+
transaction.onerror = (event) => reject(event.target.error);
|
|
131
|
+
|
|
132
|
+
operation(store);
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
async enqueueOperation(operation) {
|
|
137
|
+
this.queue.push(operation);
|
|
138
|
+
|
|
139
|
+
if (!this.isProcessing) {
|
|
140
|
+
this.isProcessing = true;
|
|
141
|
+
while (this.queue.length > 0) {
|
|
142
|
+
const currentOperation = this.queue.shift();
|
|
143
|
+
try {
|
|
144
|
+
await this.executeOperation(currentOperation);
|
|
145
|
+
} catch (error) {
|
|
146
|
+
console.error('Operation failed:', error);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
this.isProcessing = false;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
//todo андрей сказал чанки два раза грузятся
|
|
157
|
+
//при первой загрузке когда нет бд ничего не отображается
|
|
158
|
+
//андрей предлагает грохать бд если проблемы со сторами
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
// может поменять имя на StoreAppService???? потому что я уже сделал абстракцию
|
|
162
|
+
|
|
163
|
+
export class IndexedDBAppServiceForWorker extends AppDataService {
|
|
164
|
+
constructor(req, conf, gudhub) {
|
|
165
|
+
super(req, conf, gudhub);
|
|
16
166
|
|
|
17
|
-
this.dataService = new AppHttpService(req);
|
|
167
|
+
this.dataService = new AppHttpService(req, conf, gudhub);
|
|
168
|
+
|
|
169
|
+
// let indexDBService = new IndexedDBService(conf);
|
|
170
|
+
// let indexDBAppStoreManager = new AppStoreManager;
|
|
171
|
+
|
|
172
|
+
this.requestCache = new Map; // id -> promise ///TODO seems irrelevant to class IndexedDBManager (could be renamed to Facade already)
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
this.gudhub = gudhub;
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
this.chunkDataService = new IndexedDBChunkService(req, chunksMergeConf, gudhub);
|
|
179
|
+
|
|
180
|
+
// let res = await this.chunkDataService.getMergedChunkForIDList(id, sentData.chunks);
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
//TODO objectAssignWithOverride here too?
|
|
186
|
+
// this.dbManager = new IndexedDBManager('myDatabase', 'appsStore');
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
//TODO also think how to use AppDataService without overriding chunkDataService here. seems it gets http chunk service for worker somehow
|
|
191
|
+
// maybe IS_WEB is wrong inside worker
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
// this.db = null;
|
|
196
|
+
// this.queue = [];
|
|
197
|
+
// this.isProcessing = false;
|
|
198
|
+
|
|
18
199
|
|
|
19
|
-
let indexDBService = new IndexedDBService(conf);
|
|
20
200
|
|
|
21
|
-
|
|
201
|
+
//todo worker pool?
|
|
202
|
+
|
|
203
|
+
this.storeManager = new AppStoreManager;
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
// objectAssignWithOverride(this, indexDBService);
|
|
207
|
+
// objectAssignWithOverride(this, new AppStoreManager);
|
|
22
208
|
}
|
|
23
209
|
|
|
24
210
|
|
|
25
211
|
static [Symbol.hasInstance](instance) {
|
|
26
212
|
try {
|
|
27
|
-
if (instance instanceof
|
|
213
|
+
if (instance instanceof IndexedDBAppServiceForWorker) return true;
|
|
28
214
|
if (instance instanceof IndexedDBService) return true; //TODO requires multiple inheritance, thhink how to overcome it
|
|
29
215
|
return false;
|
|
30
216
|
} catch (error) {
|
|
31
|
-
|
|
217
|
+
return false;
|
|
32
218
|
}
|
|
33
219
|
}
|
|
34
220
|
|
|
@@ -36,83 +222,633 @@ export class IndexedDBAppService extends AppDataService {
|
|
|
36
222
|
// indexDBAccess = new IndexedDBFacade;
|
|
37
223
|
|
|
38
224
|
|
|
225
|
+
isWithCache() {
|
|
226
|
+
return false;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// getApp(id) {
|
|
230
|
+
// let worker = new Worker('../../appRequestWorker.js');
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
// worker.postMessage({ type: 'init', gudhubSerialized: this.gudhub.serialized });
|
|
234
|
+
|
|
235
|
+
// // Send the main data to be processed
|
|
236
|
+
// const mainData = { /* your data here */ };
|
|
237
|
+
// worker.postMessage({ type: 'processData', data: mainData });
|
|
238
|
+
|
|
239
|
+
// worker.onmessage = function(e) {
|
|
240
|
+
// console.log('Data processed by worker:', e.data);
|
|
241
|
+
// };
|
|
242
|
+
|
|
243
|
+
// worker.onerror = function(e) {
|
|
244
|
+
// console.error('Error in worker:', e);
|
|
245
|
+
// };
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
// worker.onmessage = (msgEv) => {
|
|
249
|
+
|
|
250
|
+
// }
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
// }
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
//TODO для чанков с индексддб будет точно такой код поєтому может вынести его в какое-то место? например в отдельный класс
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
// async executeOperation(operation) {
|
|
261
|
+
// await this.openDB();
|
|
262
|
+
// return new Promise((resolve, reject) => {
|
|
263
|
+
// const transaction = this.db.transaction(this.storeName, 'readwrite');
|
|
264
|
+
// const store = transaction.objectStore(this.storeName);
|
|
265
|
+
|
|
266
|
+
// transaction.oncomplete = () => resolve();
|
|
267
|
+
// transaction.onerror = (event) => reject(event.target.error);
|
|
268
|
+
|
|
269
|
+
// operation(store);
|
|
270
|
+
// });
|
|
271
|
+
// }
|
|
272
|
+
|
|
273
|
+
// async enqueueOperation(operation) {
|
|
274
|
+
// this.queue.push(operation);
|
|
275
|
+
|
|
276
|
+
// if (!this.isProcessing) {
|
|
277
|
+
// this.isProcessing = true;
|
|
278
|
+
// while (this.queue.length > 0) {
|
|
279
|
+
// const currentOperation = this.queue.shift();
|
|
280
|
+
// try {
|
|
281
|
+
// await this.executeOperation(currentOperation);
|
|
282
|
+
// } catch (error) {
|
|
283
|
+
// console.error('Operation failed:', error);
|
|
284
|
+
// }
|
|
285
|
+
// }
|
|
286
|
+
// this.isProcessing = false;
|
|
287
|
+
// }
|
|
288
|
+
// }
|
|
289
|
+
|
|
290
|
+
// async addData(data) {
|
|
291
|
+
// await this.enqueueOperation((store) => {
|
|
292
|
+
// store.add(data);
|
|
293
|
+
// });
|
|
294
|
+
// }
|
|
295
|
+
|
|
296
|
+
// async updateData(id, updatedData) {
|
|
297
|
+
// await this.enqueueOperation((store) => {
|
|
298
|
+
// const request = store.get(id);
|
|
299
|
+
// request.onsuccess = () => {
|
|
300
|
+
// const data = request.result;
|
|
301
|
+
// Object.assign(data, updatedData);
|
|
302
|
+
// store.put(data);
|
|
303
|
+
// };
|
|
304
|
+
// });
|
|
305
|
+
// }
|
|
306
|
+
|
|
307
|
+
// async deleteData(id) {
|
|
308
|
+
// await this.enqueueOperation((store) => {
|
|
309
|
+
// store.delete(id);
|
|
310
|
+
// });
|
|
311
|
+
// }
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
async getAppWithoutProcessing(id) {
|
|
315
|
+
let data = await this.dataService.getAppWithoutProcessing(id);
|
|
316
|
+
|
|
317
|
+
await this.putApp(id, data);
|
|
318
|
+
|
|
319
|
+
return data;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// this returns data for specific chunks + app request data
|
|
323
|
+
// async getAppWithSpecificChunksList(id, list) {
|
|
324
|
+
// let data = await this.dataService.getAppWithoutProcessing(id);
|
|
325
|
+
|
|
326
|
+
// await self.putApp(id, data);
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
// let processedData = await self.processRequestedApp(id, data);//here нужно пересмотреть
|
|
330
|
+
|
|
331
|
+
// return processedData;
|
|
332
|
+
// }
|
|
333
|
+
|
|
39
334
|
async getApp(id) {
|
|
40
|
-
if (this.requestCache.has(id)) return this.requestCache.get(id);
|
|
335
|
+
// if (this.requestCache.has(id)) return this.requestCache.get(id);
|
|
41
336
|
|
|
42
|
-
let dataServiceRequest = this.dataService.getApp(id);
|
|
43
337
|
|
|
44
|
-
|
|
338
|
+
// return at first time cached app request?????? no seems for worker its ok
|
|
45
339
|
|
|
46
|
-
|
|
47
|
-
|
|
340
|
+
let self = this;
|
|
341
|
+
|
|
342
|
+
// let dataServiceRequest = this.dataService.getAppWithoutProcessing(id);
|
|
343
|
+
let data = await this.dataService.getAppWithoutProcessing(id);
|
|
344
|
+
|
|
345
|
+
// await self.putApp(id, data);
|
|
346
|
+
|
|
347
|
+
let processedData = await self.processRequestedApp(id, data);//here нужно пересмотреть
|
|
348
|
+
|
|
349
|
+
return processedData;
|
|
350
|
+
|
|
351
|
+
let pr = new Promise(async (resolve, reject) => {
|
|
352
|
+
try {
|
|
353
|
+
await self.openDatabase();
|
|
48
354
|
|
|
49
|
-
let pr = new Promise(async (resolve, reject) => {
|
|
50
|
-
try {
|
|
51
|
-
const db = await self.openDatabase();
|
|
52
|
-
const transaction = db.transaction(self.store, "readonly");
|
|
53
|
-
const store = transaction.objectStore(self.store);
|
|
54
355
|
|
|
55
|
-
|
|
356
|
+
const transaction = self.db.transaction(self.store, "readonly");
|
|
357
|
+
const store = transaction.objectStore(self.store);
|
|
358
|
+
|
|
359
|
+
const storeRequest = store.get(id);
|
|
56
360
|
|
|
57
|
-
|
|
361
|
+
storeRequest.onsuccess = (e) => {
|
|
362
|
+
|
|
363
|
+
let cachedData = e.target.result;
|
|
58
364
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
if (
|
|
68
|
-
cachedData
|
|
69
|
-
) {
|
|
70
|
-
resolve(cachedData);
|
|
71
|
-
}
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
storeRequest.onerror = reject
|
|
75
|
-
} catch (error) {
|
|
76
|
-
reject();
|
|
77
|
-
}
|
|
78
|
-
});
|
|
365
|
+
if (
|
|
366
|
+
!cachedData
|
|
367
|
+
) {
|
|
368
|
+
dataServiceRequest.then(async data => {
|
|
369
|
+
let processedData = await self.processRequestedApp(id, data);//here
|
|
370
|
+
|
|
371
|
+
|
|
372
|
+
// let comparison = this.gudhub.util.compareItems([], processedData.items_list);
|
|
79
373
|
|
|
80
|
-
|
|
374
|
+
// let cached
|
|
81
375
|
|
|
82
|
-
|
|
376
|
+
resolve(processedData);
|
|
377
|
+
|
|
378
|
+
self.putApp(id, processedData);
|
|
379
|
+
|
|
380
|
+
}, reject);
|
|
381
|
+
}
|
|
83
382
|
|
|
84
|
-
|
|
383
|
+
if (
|
|
384
|
+
cachedData
|
|
385
|
+
) {
|
|
386
|
+
// resolve(cachedData);
|
|
85
387
|
|
|
86
|
-
|
|
87
|
-
|
|
388
|
+
dataServiceRequest.then(async data => {
|
|
389
|
+
let processedData = await self.processRequestedApp(id, data);//here
|
|
88
390
|
|
|
89
|
-
|
|
90
|
-
|
|
391
|
+
// let comparison = this.gudhub.util.compareItems(cachedData.items_list, processedData.items_list);
|
|
392
|
+
|
|
393
|
+
resolve(processedData);
|
|
394
|
+
self.putApp(id, processedData);
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
};
|
|
398
|
+
|
|
399
|
+
storeRequest.onerror = () => {
|
|
400
|
+
dataServiceRequest.then(async data => {
|
|
401
|
+
let processedData = await self.processRequestedApp(id, data);//here
|
|
402
|
+
|
|
403
|
+
// let comparison = this.gudhub.util.compareItems([], processedData.items_list);
|
|
404
|
+
|
|
405
|
+
// let cached
|
|
406
|
+
|
|
407
|
+
resolve(processedData);
|
|
408
|
+
|
|
409
|
+
self.putApp(id, processedData);
|
|
410
|
+
|
|
411
|
+
}, reject);
|
|
412
|
+
}
|
|
413
|
+
} catch (error) {
|
|
414
|
+
dataServiceRequest.then(async data => {
|
|
415
|
+
let processedData = await self.processRequestedApp(id, data);//here
|
|
416
|
+
|
|
417
|
+
// let comparison = this.gudhub.util.compareItems([], processedData.items_list);
|
|
418
|
+
|
|
419
|
+
// let cached
|
|
420
|
+
|
|
421
|
+
resolve(processedData);
|
|
422
|
+
|
|
423
|
+
self.putApp(id, processedData);
|
|
424
|
+
|
|
425
|
+
}, reject);
|
|
426
|
+
}
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
// self.requestCache.set(id, pr);
|
|
430
|
+
|
|
431
|
+
return pr;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
async getCached(id) {
|
|
435
|
+
|
|
436
|
+
return this.storeManager.getApp(id); //TODO investigate method name
|
|
437
|
+
|
|
438
|
+
|
|
439
|
+
let self = this;
|
|
440
|
+
|
|
441
|
+
let pr = new Promise(async (resolve, reject) => {
|
|
442
|
+
try {
|
|
443
|
+
await self.openDatabase();
|
|
444
|
+
|
|
445
|
+
const transaction = self.db.transaction(self.store, "readonly");
|
|
446
|
+
const store = transaction.objectStore(self.store);
|
|
447
|
+
|
|
448
|
+
const storeRequest = store.get(id);
|
|
449
|
+
|
|
450
|
+
storeRequest.onsuccess = (e) => {
|
|
451
|
+
|
|
452
|
+
let cachedData = e.target.result;
|
|
453
|
+
|
|
454
|
+
if (
|
|
455
|
+
!cachedData
|
|
456
|
+
) {
|
|
457
|
+
reject();
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
if (
|
|
461
|
+
cachedData
|
|
462
|
+
) {
|
|
463
|
+
resolve(cachedData);
|
|
464
|
+
}
|
|
465
|
+
};
|
|
466
|
+
|
|
467
|
+
storeRequest.onerror = reject;
|
|
468
|
+
} catch (error) {
|
|
469
|
+
reject();
|
|
470
|
+
}
|
|
471
|
+
});
|
|
472
|
+
|
|
473
|
+
return pr;
|
|
91
474
|
}
|
|
92
475
|
|
|
93
476
|
async putApp(id, data) {
|
|
94
|
-
|
|
95
|
-
const db = await this.openDatabase();
|
|
477
|
+
return this.storeManager.putApp(id, data);
|
|
96
478
|
|
|
97
|
-
|
|
98
|
-
|
|
479
|
+
// try {
|
|
480
|
+
// await this.openDatabase();
|
|
99
481
|
|
|
100
|
-
|
|
101
|
-
|
|
482
|
+
// const transaction = this.db.transaction(this.store, "readwrite");
|
|
483
|
+
// const store = transaction.objectStore(this.store);
|
|
484
|
+
|
|
485
|
+
// store.put(data, id);
|
|
486
|
+
// } catch (error) {
|
|
487
|
+
|
|
488
|
+
// }
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
// duplicated code 2 times in 2 classes openDatabase
|
|
492
|
+
|
|
493
|
+
// async openDatabase() {
|
|
494
|
+
// if (this.db) return this.db;
|
|
495
|
+
|
|
496
|
+
// return new Promise((resolve, reject) => {
|
|
497
|
+
// const request = indexedDB.open(this.dbName, this.dbVersion);
|
|
498
|
+
|
|
499
|
+
// request.onsuccess = event => {
|
|
500
|
+
// this.db = event.target.result;
|
|
501
|
+
// resolve(this.db);
|
|
502
|
+
// };
|
|
503
|
+
// request.onerror = event => {
|
|
504
|
+
// reject(event.target.error);
|
|
505
|
+
// };
|
|
506
|
+
// });
|
|
507
|
+
// }
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
|
|
511
|
+
export class IndexedDBAppService extends AppDataService {
|
|
512
|
+
constructor(req, conf, gudhub) {
|
|
513
|
+
super(req, conf, gudhub);
|
|
102
514
|
|
|
515
|
+
this.dataService = new AppHttpService(req, conf, gudhub);// TODO isnt used in class. Why?
|
|
516
|
+
|
|
517
|
+
// let indexDBService = new IndexedDBService(conf);
|
|
518
|
+
|
|
519
|
+
this.requestCache = new Map; // id -> promise ///TODO seems irrelevant to class IndexedDBManager (could be renamed to Facade already)
|
|
520
|
+
|
|
521
|
+
|
|
522
|
+
this.gudhub = gudhub;
|
|
523
|
+
|
|
524
|
+
|
|
525
|
+
this.resolveFnMap = new Map; // id -> resolve
|
|
526
|
+
|
|
527
|
+
|
|
528
|
+
|
|
529
|
+
// this.appRequestAndProcessWorker = new Worker('./appRequestWorker.js');
|
|
530
|
+
// this.appRequestAndProcessWorker = new Worker(new URL('./appRequestWorker.js', import.meta.url));
|
|
531
|
+
this.appRequestAndProcessWorker = new Worker('node_modules/@gudhub/core/umd/appRequestWorker.js');
|
|
532
|
+
// this.appRequestAndProcessWorker = new Worker('override_npm/gudhub/umd/appRequestWorker.js');
|
|
533
|
+
// this.appRequestAndProcessWorker = new AppRequestWorker();
|
|
534
|
+
|
|
535
|
+
// new Worker(new URL('./worker.js', import.meta.url));
|
|
536
|
+
|
|
537
|
+
|
|
538
|
+
this.appRequestAndProcessWorker.postMessage({ type: 'init', gudhubSerialized: this.gudhub.serialized });
|
|
539
|
+
|
|
540
|
+
|
|
541
|
+
let self = this;
|
|
542
|
+
this.appRequestAndProcessWorker.onerror = function(e) {
|
|
543
|
+
// self.appRequestAndProcessWorker.terminate();
|
|
544
|
+
|
|
545
|
+
|
|
546
|
+
// console.error('Error in worker:', e);
|
|
547
|
+
};
|
|
548
|
+
|
|
549
|
+
|
|
550
|
+
// let self = this;
|
|
551
|
+
|
|
552
|
+
this.appRequestAndProcessWorker.onmessage = function(e) {
|
|
553
|
+
|
|
554
|
+
|
|
555
|
+
|
|
556
|
+
|
|
557
|
+
|
|
558
|
+
if (
|
|
559
|
+
e.data.type == 'requestApp'
|
|
560
|
+
) {
|
|
561
|
+
|
|
562
|
+
if (
|
|
563
|
+
self.resolveFnMap.has(e.data.id)
|
|
564
|
+
) {
|
|
565
|
+
let resolver = self.resolveFnMap.get(e.data.id);
|
|
566
|
+
|
|
567
|
+
resolver(e.data.data);
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
|
|
571
|
+
// self.requestCache.set(id, new Promise);
|
|
572
|
+
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
|
|
576
|
+
// todo check this for new code
|
|
577
|
+
// todo outdated code, to remove
|
|
578
|
+
if (
|
|
579
|
+
e.data.type == 'processData'
|
|
580
|
+
) {
|
|
581
|
+
// if (id == e.data.id) {
|
|
582
|
+
self.gudhub.itemProcessor.handleDiff(e.data.id, e.data.compareRes);
|
|
583
|
+
|
|
584
|
+
|
|
585
|
+
if (
|
|
586
|
+
e.data.viewListChanged ||
|
|
587
|
+
e.data.fieldListChanged
|
|
588
|
+
) {
|
|
589
|
+
self.gudhub.appProcessor.updateAppFieldsAndViews(e.data.newVersion);
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
|
|
593
|
+
|
|
594
|
+
|
|
595
|
+
//here
|
|
596
|
+
|
|
597
|
+
// }
|
|
103
598
|
}
|
|
599
|
+
|
|
600
|
+
|
|
601
|
+
|
|
602
|
+
|
|
603
|
+
|
|
604
|
+
|
|
605
|
+
// worker.terminate();
|
|
606
|
+
|
|
607
|
+
// this.postMessage({id: e.data.id, compareRes: comparison});
|
|
608
|
+
|
|
609
|
+
|
|
610
|
+
// console.log('Data processed by worker:', e.data);
|
|
611
|
+
};
|
|
612
|
+
|
|
613
|
+
// worker.onerror = function(e) {
|
|
614
|
+
// // worker.terminate();
|
|
615
|
+
|
|
616
|
+
|
|
617
|
+
// // console.error('Error in worker:', e);
|
|
618
|
+
// };
|
|
619
|
+
|
|
620
|
+
|
|
621
|
+
|
|
622
|
+
//todo worker pool?
|
|
623
|
+
|
|
624
|
+
|
|
625
|
+
this.storeManager = new AppStoreManager;
|
|
626
|
+
|
|
627
|
+
// objectAssignWithOverride(this, indexDBService);
|
|
628
|
+
// objectAssignWithOverride(this, new AppStoreManager());
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
|
|
632
|
+
static [Symbol.hasInstance](instance) {
|
|
633
|
+
try {
|
|
634
|
+
if (instance instanceof IndexedDBAppService) return true;
|
|
635
|
+
if (instance instanceof IndexedDBService) return true; //TODO requires multiple inheritance, thhink how to overcome it
|
|
636
|
+
return false;
|
|
637
|
+
} catch (error) {
|
|
638
|
+
return false;
|
|
104
639
|
}
|
|
640
|
+
}
|
|
105
641
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
const request = indexedDB.open(this.dbName, this.dbVersion);
|
|
642
|
+
//TODO use IndexedDBFacade here
|
|
643
|
+
// indexDBAccess = new IndexedDBFacade;
|
|
109
644
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
645
|
+
|
|
646
|
+
isWithCache() {
|
|
647
|
+
return false; //doesnt use indexeddb
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
async getApp(id) {//TODO -> get?
|
|
651
|
+
if (this.requestCache.has(id)) return this.requestCache.get(id); // по этому коду есть вопрос - вызовы getApp кешируются выше и тогда выходит возвращается старая версия?
|
|
652
|
+
|
|
653
|
+
|
|
654
|
+
let self = this;
|
|
655
|
+
|
|
656
|
+
|
|
657
|
+
let hasId = await this.has(id);
|
|
658
|
+
|
|
659
|
+
|
|
660
|
+
if (
|
|
661
|
+
false
|
|
662
|
+
) {
|
|
663
|
+
|
|
664
|
+
// let promiseObject = Promise.
|
|
665
|
+
|
|
666
|
+
let cached = await this.getCached(id); // todo here should be merged with cached mergedChunk
|
|
667
|
+
|
|
668
|
+
// repetitive operation again, seems should be in getCached
|
|
669
|
+
let cachedMergedChunk = await this.chunkDataService.getCachedMergedChunk(id, cached.chunks);
|
|
670
|
+
|
|
671
|
+
|
|
672
|
+
// let mergedData = this.gudhub
|
|
673
|
+
|
|
674
|
+
|
|
675
|
+
cached.items_list = await this.gudhub.util.mergeChunks([
|
|
676
|
+
cachedMergedChunk,
|
|
677
|
+
cached,
|
|
678
|
+
]);
|
|
679
|
+
|
|
680
|
+
|
|
681
|
+
let getFromDBPrms = Promise.resolve(cached);
|
|
682
|
+
|
|
683
|
+
// let getFromDBPrms = await this.getCached(id); // todo here should be merged with cached mergedChunk
|
|
684
|
+
this.requestCache.set(id, getFromDBPrms);
|
|
685
|
+
|
|
686
|
+
this.appRequestAndProcessWorker.postMessage({ type: 'processData', id: id });
|
|
687
|
+
|
|
688
|
+
return getFromDBPrms;
|
|
689
|
+
} else {
|
|
690
|
+
// this.requestCache.set(id, new Promise);
|
|
691
|
+
|
|
692
|
+
let prms = new Promise((resolve, reject) => {
|
|
693
|
+
self.resolveFnMap.set(id, resolve);
|
|
116
694
|
});
|
|
695
|
+
|
|
696
|
+
|
|
697
|
+
this.requestCache.set(id, prms);
|
|
698
|
+
|
|
699
|
+
//todo define types as constants
|
|
700
|
+
this.appRequestAndProcessWorker.postMessage({ type: 'requestApp', id: id });
|
|
701
|
+
|
|
702
|
+
|
|
703
|
+
|
|
704
|
+
return prms;
|
|
705
|
+
|
|
706
|
+
//todo somehow handle answer from worker
|
|
707
|
+
|
|
708
|
+
//maybe use mesage library to communicate with worker
|
|
117
709
|
}
|
|
710
|
+
|
|
711
|
+
|
|
712
|
+
|
|
713
|
+
|
|
714
|
+
// let worker = new Worker('./appRequestWorker.js');
|
|
715
|
+
|
|
716
|
+
|
|
717
|
+
// worker.postMessage({ type: 'init', gudhubSerialized: this.gudhub.serialized });
|
|
718
|
+
|
|
719
|
+
// Send the main data to be processed
|
|
720
|
+
// const mainData = { /* your data here */ };
|
|
721
|
+
// this.appRequestAndProcessWorker.postMessage({ type: 'processData', id: id });
|
|
722
|
+
|
|
723
|
+
// let self = this;
|
|
724
|
+
|
|
725
|
+
// worker.onmessage = function(e) {
|
|
726
|
+
|
|
727
|
+
|
|
728
|
+
// if (id == e.data.id) {
|
|
729
|
+
// self.gudhub.itemProcessor.handleDiff(e.data.id, e.data.compareRes);
|
|
730
|
+
// }
|
|
731
|
+
|
|
732
|
+
|
|
733
|
+
|
|
734
|
+
// // worker.terminate();
|
|
735
|
+
|
|
736
|
+
// // this.postMessage({id: e.data.id, compareRes: comparison});
|
|
737
|
+
|
|
738
|
+
|
|
739
|
+
// // console.log('Data processed by worker:', e.data);
|
|
740
|
+
// };
|
|
741
|
+
|
|
742
|
+
// worker.onerror = function(e) {
|
|
743
|
+
// // worker.terminate();
|
|
744
|
+
|
|
745
|
+
|
|
746
|
+
// // console.error('Error in worker:', e);
|
|
747
|
+
// };
|
|
748
|
+
|
|
749
|
+
|
|
750
|
+
// return getFromDBPrms;
|
|
751
|
+
|
|
752
|
+
|
|
753
|
+
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
|
|
757
|
+
//TODO page isnt loaded when indexeddb empty. Investigate getApp in IndexedDBAppService here
|
|
758
|
+
|
|
759
|
+
async getCached(id) {//TODO -> getFromStore?
|
|
760
|
+
|
|
761
|
+
|
|
762
|
+
return this.storeManager.getApp(id); //TODO investigate method name
|
|
763
|
+
|
|
764
|
+
let self = this;
|
|
765
|
+
|
|
766
|
+
let pr = new Promise(async (resolve, reject) => {
|
|
767
|
+
try {
|
|
768
|
+
await self.openDatabase();
|
|
769
|
+
|
|
770
|
+
const transaction = self.db.transaction(self.store, "readonly");
|
|
771
|
+
const store = transaction.objectStore(self.store);
|
|
772
|
+
|
|
773
|
+
const storeRequest = store.get(id);
|
|
774
|
+
|
|
775
|
+
storeRequest.onsuccess = (e) => {
|
|
776
|
+
|
|
777
|
+
let cachedData = e.target.result;
|
|
778
|
+
|
|
779
|
+
if (
|
|
780
|
+
!cachedData
|
|
781
|
+
) {
|
|
782
|
+
reject();
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
if (
|
|
786
|
+
cachedData
|
|
787
|
+
) {
|
|
788
|
+
resolve(cachedData);
|
|
789
|
+
}
|
|
790
|
+
};
|
|
791
|
+
|
|
792
|
+
storeRequest.onerror = reject;
|
|
793
|
+
} catch (error) {
|
|
794
|
+
reject();
|
|
795
|
+
}
|
|
796
|
+
});
|
|
797
|
+
|
|
798
|
+
return pr;
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
async has(id) {
|
|
802
|
+
|
|
803
|
+
try {
|
|
804
|
+
|
|
805
|
+
return this.storeManager.hasApp(id);
|
|
806
|
+
} catch (error) {
|
|
807
|
+
debugger
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
// try {
|
|
811
|
+
// let cached = await this.getCached(id);
|
|
812
|
+
|
|
813
|
+
// if (!cached) return false;
|
|
814
|
+
|
|
815
|
+
// return true;
|
|
816
|
+
// } catch(e) {
|
|
817
|
+
// //todo check error type and then rethrow maybe here
|
|
818
|
+
|
|
819
|
+
// return false;
|
|
820
|
+
// }
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
async putApp(id, data) { //TODO -> put?
|
|
824
|
+
return this.storeManager.putApp(id, data);
|
|
825
|
+
|
|
826
|
+
// try {
|
|
827
|
+
// const db = await this.openDatabase();
|
|
828
|
+
|
|
829
|
+
// const transaction = db.transaction(this.store, "readwrite");
|
|
830
|
+
// const store = transaction.objectStore(this.store);
|
|
831
|
+
|
|
832
|
+
// store.put(data, id);
|
|
833
|
+
// } catch (error) {
|
|
834
|
+
|
|
835
|
+
// }
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
//todo openDatabase only once and then preserve it for further usage
|
|
839
|
+
// async openDatabase() {
|
|
840
|
+
// if (this.db) return this.db;
|
|
841
|
+
|
|
842
|
+
// return new Promise((resolve, reject) => {
|
|
843
|
+
// const request = indexedDB.open(this.dbName, this.dbVersion);
|
|
844
|
+
|
|
845
|
+
// request.onsuccess = event => {
|
|
846
|
+
// this.db = event.target.result;
|
|
847
|
+
// resolve(this.db);
|
|
848
|
+
// };
|
|
849
|
+
// request.onerror = event => {
|
|
850
|
+
// reject(event.target.error);
|
|
851
|
+
// };
|
|
852
|
+
// });
|
|
853
|
+
// }
|
|
118
854
|
}
|