feat: sync snapshot obj with incoming changes
This commit is contained in:
parent
827039cd41
commit
996ba34235
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
|
||||||
|
* Copyright (c) 2023 Michal Szczepanski.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
import { BrowserStorage } from '@pinmenote/browser-api';
|
||||||
|
import { ICommand } from '../../../model/shared/common.dto';
|
||||||
|
import { ObjectStoreKeys } from '../../../keys/object.store.keys';
|
||||||
|
import { SegmentData } from '@pinmenote/page-compute';
|
||||||
|
import { fnConsoleLog } from '../../../fn/fn-console';
|
||||||
|
|
||||||
|
export class PageSegmentAddRefCommand implements ICommand<Promise<boolean>> {
|
||||||
|
constructor(private hash: string) {}
|
||||||
|
|
||||||
|
async execute(): Promise<boolean> {
|
||||||
|
const key = `${ObjectStoreKeys.CONTENT_HASH}:${this.hash}`;
|
||||||
|
const has = await BrowserStorage.get(key);
|
||||||
|
if (!has) return false;
|
||||||
|
await this.incrementCount();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
async incrementCount(): Promise<void> {
|
||||||
|
const key = `${ObjectStoreKeys.CONTENT_HASH_COUNT}:${this.hash}`;
|
||||||
|
let count = (await BrowserStorage.get<number | undefined>(key)) || 0;
|
||||||
|
count++;
|
||||||
|
fnConsoleLog('PageSegmentAddRefCommand->incrementCount', count);
|
||||||
|
await BrowserStorage.set(key, count);
|
||||||
|
}
|
||||||
|
}
|
@ -21,12 +21,12 @@ import { SegmentData } from '@pinmenote/page-compute';
|
|||||||
import { fnConsoleLog } from '../../../fn/fn-console';
|
import { fnConsoleLog } from '../../../fn/fn-console';
|
||||||
|
|
||||||
export class PageSegmentAddCommand<T> implements ICommand<Promise<void>> {
|
export class PageSegmentAddCommand<T> implements ICommand<Promise<void>> {
|
||||||
constructor(private content: SegmentData<T>) {}
|
constructor(private content: SegmentData<T>, private ref = true) {}
|
||||||
|
|
||||||
async execute(): Promise<void> {
|
async execute(): Promise<void> {
|
||||||
const key = `${ObjectStoreKeys.CONTENT_HASH}:${this.content.hash}`;
|
const key = `${ObjectStoreKeys.CONTENT_HASH}:${this.content.hash}`;
|
||||||
await BrowserStorage.set<SegmentData<T>>(key, this.content);
|
await BrowserStorage.set<SegmentData<T>>(key, this.content);
|
||||||
await this.incrementCount();
|
if (this.ref) await this.incrementCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
async incrementCount(): Promise<void> {
|
async incrementCount(): Promise<void> {
|
||||||
|
@ -32,6 +32,7 @@ export class ObjectStoreKeys {
|
|||||||
static readonly UPDATED_DT = 'o:dt:u';
|
static readonly UPDATED_DT = 'o:dt:u';
|
||||||
|
|
||||||
static readonly TX_ID = 'tx:id';
|
static readonly TX_ID = 'tx:id';
|
||||||
|
static readonly SERVER_ID = 'sv:id';
|
||||||
|
|
||||||
// INDEX
|
// INDEX
|
||||||
static readonly SEARCH_INDEX = 's:i';
|
static readonly SEARCH_INDEX = 's:i';
|
||||||
@ -48,6 +49,7 @@ export class ObjectStoreKeys {
|
|||||||
// SYNC
|
// SYNC
|
||||||
static readonly SYNC_INTERVAL = 'sync:interval';
|
static readonly SYNC_INTERVAL = 'sync:interval';
|
||||||
static readonly SYNC_PROGRESS = 'sync:progress';
|
static readonly SYNC_PROGRESS = 'sync:progress';
|
||||||
|
static readonly SYNC_IN = 'sync:obj:in';
|
||||||
static readonly SYNC_TX = 'sync:tx';
|
static readonly SYNC_TX = 'sync:tx';
|
||||||
|
|
||||||
// SETTINGS
|
// SETTINGS
|
||||||
|
@ -26,7 +26,6 @@ export class LinkHrefStore {
|
|||||||
|
|
||||||
static async add(url: ObjUrlDto, id: number): Promise<void> {
|
static async add(url: ObjUrlDto, id: number): Promise<void> {
|
||||||
// Update hrefs
|
// Update hrefs
|
||||||
fnConsoleLog('LinkHrefStore->addHrefOriginId', url.href);
|
|
||||||
const hrefIds = await this.hrefIds(url.href);
|
const hrefIds = await this.hrefIds(url.href);
|
||||||
hrefIds.push(id);
|
hrefIds.push(id);
|
||||||
await BrowserStorage.set(`${this.OBJ_HREF}:${url.href}`, hrefIds);
|
await BrowserStorage.set(`${this.OBJ_HREF}:${url.href}`, hrefIds);
|
||||||
@ -48,7 +47,6 @@ export class LinkHrefStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static async hrefIds(url: string): Promise<number[]> {
|
static async hrefIds(url: string): Promise<number[]> {
|
||||||
fnConsoleLog('LinkHrefStore->hrefIds', url);
|
|
||||||
const key = `${this.OBJ_HREF}:${url}`;
|
const key = `${this.OBJ_HREF}:${url}`;
|
||||||
const value = await BrowserStorage.get<number[] | undefined>(key);
|
const value = await BrowserStorage.get<number[] | undefined>(key);
|
||||||
return value || [];
|
return value || [];
|
||||||
|
@ -46,14 +46,13 @@ export class LinkOriginStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static async originIds(keyPrefix: string, url: string): Promise<number[]> {
|
static async originIds(keyPrefix: string, url: string): Promise<number[]> {
|
||||||
fnConsoleLog('LinkOriginStore->originIds', url);
|
// fnConsoleLog('LinkOriginStore->originIds', url);
|
||||||
const key = `${keyPrefix}:${url}`;
|
const key = `${keyPrefix}:${url}`;
|
||||||
const value = await BrowserStorage.get<number[] | undefined>(key);
|
const value = await BrowserStorage.get<number[] | undefined>(key);
|
||||||
return value || [];
|
return value || [];
|
||||||
}
|
}
|
||||||
|
|
||||||
static async originList(): Promise<string[]> {
|
static async originList(): Promise<string[]> {
|
||||||
fnConsoleLog('LinkOriginStore->list');
|
|
||||||
const value = await BrowserStorage.get<string[] | undefined>(this.ORIGIN_LIST);
|
const value = await BrowserStorage.get<string[] | undefined>(this.ORIGIN_LIST);
|
||||||
return value || [];
|
return value || [];
|
||||||
}
|
}
|
||||||
|
@ -15,10 +15,6 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
import { ObjTypeDto } from '../../../../common/model/obj/obj.dto';
|
import { ObjTypeDto } from '../../../../common/model/obj/obj.dto';
|
||||||
import { ObjPinDto } from '../../../../common/model/obj/obj-pin.dto';
|
|
||||||
import { ObjCommentDto } from '../../../../common/model/obj/obj-comment.dto';
|
|
||||||
import { ObjDrawDto } from '../../../../common/model/obj/obj-draw.dto';
|
|
||||||
import { ObjVideoDataDto } from '../../../../common/model/obj/page-snapshot.dto';
|
|
||||||
|
|
||||||
export interface BeginTxResponse {
|
export interface BeginTxResponse {
|
||||||
tx: string;
|
tx: string;
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { ApiCallBase } from '../../api-call.base';
|
import { ApiCallBase } from '../../api-call.base';
|
||||||
import { ObjTypeDto } from '../../../../../common/model/obj/obj.dto';
|
|
||||||
import { ICommand, ServerErrorDto } from '../../../../../common/model/shared/common.dto';
|
import { ICommand, ServerErrorDto } from '../../../../../common/model/shared/common.dto';
|
||||||
import { ApiErrorCode } from '../../../../../common/model/shared/api.error-code';
|
import { ApiErrorCode } from '../../../../../common/model/shared/api.error-code';
|
||||||
import { FetchService } from '@pinmenote/fetch-service';
|
import { FetchService } from '@pinmenote/fetch-service';
|
||||||
|
@ -21,7 +21,7 @@ import { fnConsoleLog } from '../../../../../common/fn/fn-console';
|
|||||||
import { ObjChangesResponse } from '../api-store.model';
|
import { ObjChangesResponse } from '../api-store.model';
|
||||||
|
|
||||||
export class ApiObjGetChangesCommand extends ApiCallBase implements ICommand<Promise<ObjChangesResponse | undefined>> {
|
export class ApiObjGetChangesCommand extends ApiCallBase implements ICommand<Promise<ObjChangesResponse | undefined>> {
|
||||||
constructor() {
|
constructor(private serverId?: number) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
async execute(): Promise<ObjChangesResponse | undefined> {
|
async execute(): Promise<ObjChangesResponse | undefined> {
|
||||||
@ -29,7 +29,7 @@ export class ApiObjGetChangesCommand extends ApiCallBase implements ICommand<Pro
|
|||||||
if (!this.storeUrl) return;
|
if (!this.storeUrl) return;
|
||||||
try {
|
try {
|
||||||
const resp = await FetchService.fetch<ObjChangesResponse>(
|
const resp = await FetchService.fetch<ObjChangesResponse>(
|
||||||
`${this.storeUrl}/api/v1/obj/changes`,
|
`${this.storeUrl}/api/v1/obj/changes?serverId=${this.serverId || 0}`,
|
||||||
{ headers: this.getAuthHeaders() },
|
{ headers: this.getAuthHeaders() },
|
||||||
this.refreshParams()
|
this.refreshParams()
|
||||||
);
|
);
|
||||||
|
@ -36,10 +36,10 @@ export class ApiSegmentGetChildrenCommand
|
|||||||
{ headers: this.getAuthHeaders() },
|
{ headers: this.getAuthHeaders() },
|
||||||
this.refreshParams()
|
this.refreshParams()
|
||||||
);
|
);
|
||||||
fnConsoleLog('ApiSegmentGetChildrenCommand->response', resp);
|
|
||||||
return resp.data;
|
return resp.data;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
fnConsoleLog('ApiSegmentGetChildrenCommand->Error', e);
|
fnConsoleLog('ApiSegmentGetChildrenCommand->Error', e);
|
||||||
}
|
}
|
||||||
|
throw new Error('ApiSegmentGetChildrenCommand->execute');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
import { ApiCallBase } from '../../api-call.base';
|
import { ApiCallBase } from '../../api-call.base';
|
||||||
import { FetchService } from '@pinmenote/fetch-service';
|
import { FetchService } from '@pinmenote/fetch-service';
|
||||||
import { ICommand } from '../../../../../common/model/shared/common.dto';
|
import { ICommand } from '../../../../../common/model/shared/common.dto';
|
||||||
import { ObjSingleChange, SegmentHashListResponse } from '../api-store.model';
|
|
||||||
import { fnConsoleLog } from '../../../../../common/fn/fn-console';
|
import { fnConsoleLog } from '../../../../../common/fn/fn-console';
|
||||||
|
|
||||||
export class ApiSegmentGetCommand extends ApiCallBase implements ICommand<Promise<Blob | undefined>> {
|
export class ApiSegmentGetCommand extends ApiCallBase implements ICommand<Promise<Blob | undefined>> {
|
||||||
@ -37,5 +36,6 @@ export class ApiSegmentGetCommand extends ApiCallBase implements ICommand<Promis
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
fnConsoleLog('ApiSegmentGetCommand->Error', e);
|
fnConsoleLog('ApiSegmentGetCommand->Error', e);
|
||||||
}
|
}
|
||||||
|
throw new Error('ApiSegmentGetCommand->execute');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,10 @@ import { ObjectStoreKeys } from '../../../../common/keys/object.store.keys';
|
|||||||
import { LinkHrefStore } from '../../../../common/store/link-href.store';
|
import { LinkHrefStore } from '../../../../common/store/link-href.store';
|
||||||
import { ObjAddIdCommand } from '../../../../common/command/obj/id/obj-add-id.command';
|
import { ObjAddIdCommand } from '../../../../common/command/obj/id/obj-add-id.command';
|
||||||
import { PageSegmentAddCommand } from '../../../../common/command/snapshot/segment/page-segment-add.command';
|
import { PageSegmentAddCommand } from '../../../../common/command/snapshot/segment/page-segment-add.command';
|
||||||
|
import { ObjNextIdCommand } from '../../../../common/command/obj/id/obj-next-id.command';
|
||||||
|
import { PageSegmentAddRefCommand } from '../../../../common/command/snapshot/segment/page-segment-add-ref.command';
|
||||||
|
import { fnSleep } from '../../../../common/fn/fn-sleep';
|
||||||
|
import { fnConsoleLog } from '../../../../common/fn/fn-console';
|
||||||
|
|
||||||
interface HashDataElement {
|
interface HashDataElement {
|
||||||
hash: SegmentSingleHash;
|
hash: SegmentSingleHash;
|
||||||
@ -40,11 +44,26 @@ interface HashDataElement {
|
|||||||
type HashData = { [key: string]: HashDataElement };
|
type HashData = { [key: string]: HashDataElement };
|
||||||
type HashType = { [key: string]: string[] };
|
type HashType = { [key: string]: string[] };
|
||||||
|
|
||||||
export class SyncObjIncomingHashCommand implements ICommand<Promise<void>> {
|
export class SyncObjIncomingHashCommand implements ICommand<Promise<boolean>> {
|
||||||
constructor(private change: ObjSingleChange) {}
|
constructor(private change: ObjSingleChange) {}
|
||||||
async execute(): Promise<void> {
|
// TODO store progress in ObjectStoreKeys.SYNC_IN
|
||||||
|
async execute(): Promise<boolean> {
|
||||||
|
try {
|
||||||
|
const result = await this.syncHashList();
|
||||||
|
if (!result) {
|
||||||
|
fnConsoleLog('PROBLEM syncHashList !!!!!!!!!!!!!!!!!!!', result);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return await this.toDto(result.hashMap, result.hashType);
|
||||||
|
} catch (e) {
|
||||||
|
fnConsoleLog('PROBLEM 222222222222 SyncObjIncomingHashCommand->syncHashList', e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private syncHashList = async (): Promise<{ hashType: HashType; hashMap: HashData } | undefined> => {
|
||||||
const hashList = await new ApiSegmentGetChildrenCommand(this.change.hash).execute();
|
const hashList = await new ApiSegmentGetChildrenCommand(this.change.hash).execute();
|
||||||
if (!hashList) return;
|
if (!hashList) return undefined;
|
||||||
hashList.children.sort((a, b) => {
|
hashList.children.sort((a, b) => {
|
||||||
if (a.type > b.type) return 1;
|
if (a.type > b.type) return 1;
|
||||||
if (a.type < b.type) return -1;
|
if (a.type < b.type) return -1;
|
||||||
@ -59,6 +78,8 @@ export class SyncObjIncomingHashCommand implements ICommand<Promise<void>> {
|
|||||||
if (child.type.toString() === SyncHashType.Img) {
|
if (child.type.toString() === SyncHashType.Img) {
|
||||||
const src = await UrlFactory.toDataUri(data);
|
const src = await UrlFactory.toDataUri(data);
|
||||||
const content: SegmentImg = { src };
|
const content: SegmentImg = { src };
|
||||||
|
const has = new PageSegmentAddRefCommand(child.hash);
|
||||||
|
if (has) continue;
|
||||||
await new PageSegmentAddCommand({ type: SegmentType.IMG, hash: child.hash, content }).execute();
|
await new PageSegmentAddCommand({ type: SegmentType.IMG, hash: child.hash, content }).execute();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -67,12 +88,16 @@ export class SyncObjIncomingHashCommand implements ICommand<Promise<void>> {
|
|||||||
const content = new TextDecoder().decode(bytes);
|
const content = new TextDecoder().decode(bytes);
|
||||||
|
|
||||||
if (child.type.toString() === SyncHashType.Css) {
|
if (child.type.toString() === SyncHashType.Css) {
|
||||||
|
const has = new PageSegmentAddRefCommand(child.hash);
|
||||||
|
if (has) continue;
|
||||||
await new PageSegmentAddCommand({
|
await new PageSegmentAddCommand({
|
||||||
type: SegmentType.CSS,
|
type: SegmentType.CSS,
|
||||||
hash: child.hash,
|
hash: child.hash,
|
||||||
content: JSON.parse(content)
|
content: JSON.parse(content)
|
||||||
}).execute();
|
}).execute();
|
||||||
} else if (child.type.toString() === SyncHashType.IFrame) {
|
} else if (child.type.toString() === SyncHashType.IFrame) {
|
||||||
|
const has = new PageSegmentAddRefCommand(child.hash);
|
||||||
|
if (has) continue;
|
||||||
await new PageSegmentAddCommand({
|
await new PageSegmentAddCommand({
|
||||||
type: SegmentType.IFRAME,
|
type: SegmentType.IFRAME,
|
||||||
hash: child.hash,
|
hash: child.hash,
|
||||||
@ -84,65 +109,81 @@ export class SyncObjIncomingHashCommand implements ICommand<Promise<void>> {
|
|||||||
hashMap[child.hash] = { hash: child, data: JSON.parse(content) };
|
hashMap[child.hash] = { hash: child, data: JSON.parse(content) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.log('hashList', hashList, 'hashMap', hashMap, 'hashType', hashType);
|
return { hashMap, hashType };
|
||||||
await this.toDto(hashMap, hashType);
|
};
|
||||||
}
|
|
||||||
|
|
||||||
private toDto = async (hashData: HashData, type: HashType) => {
|
private toDto = async (hashData: HashData, type: HashType) => {
|
||||||
switch (this.change.type) {
|
switch (this.change.type) {
|
||||||
case ObjTypeDto.PageSnapshot:
|
case ObjTypeDto.PageSnapshot:
|
||||||
case ObjTypeDto.PageElementSnapshot: {
|
case ObjTypeDto.PageElementSnapshot: {
|
||||||
const key = `${ObjectStoreKeys.OBJECT_ID}:${this.change.serverId}`;
|
return await this.saveSnapshotDto(hashData, type);
|
||||||
const stored = await BrowserStorage.get(key);
|
|
||||||
if (stored) return;
|
|
||||||
const snapshot: PageSnapshotDto = {
|
|
||||||
data: hashData[type[SyncHashType.PageSnapshotDataDto][0]].data,
|
|
||||||
info: hashData[type[SyncHashType.PageSnapshotInfoDto][0]].data,
|
|
||||||
hash: this.change.hash,
|
|
||||||
segment: type[SyncHashType.PageSnapshotFirstHash][0]
|
|
||||||
};
|
|
||||||
const data: ObjPageDto = {
|
|
||||||
snapshot: snapshot,
|
|
||||||
comments: { data: [] }
|
|
||||||
};
|
|
||||||
const id = this.change.serverId;
|
|
||||||
const dt = Date.now();
|
|
||||||
// Add createdAt, updatedAt, VERSION ----> TO SERVER
|
|
||||||
const obj: ObjDto<ObjPageDto> = {
|
|
||||||
id,
|
|
||||||
data,
|
|
||||||
server: { id: this.change.serverId },
|
|
||||||
version: OBJ_DTO_VERSION,
|
|
||||||
createdAt: dt,
|
|
||||||
updatedAt: dt,
|
|
||||||
type: this.change.type,
|
|
||||||
local: {
|
|
||||||
visible: true,
|
|
||||||
drawVisible: false
|
|
||||||
}
|
|
||||||
};
|
|
||||||
await SwTaskStore.addTask(SwTaskType.WORDS_ADD_INDEX, {
|
|
||||||
words: snapshot.info.words,
|
|
||||||
objectId: id
|
|
||||||
});
|
|
||||||
await BrowserStorage.set(key, obj);
|
|
||||||
await LinkHrefStore.add(snapshot.info.url, id);
|
|
||||||
if (type[SyncHashType.PageSnapshotFirstHash]) {
|
|
||||||
for (const hash of type[SyncHashType.PageSnapshotFirstHash]) {
|
|
||||||
console.log('ADDDD !!!!!!!!!!!!!!!!', hash);
|
|
||||||
await new PageSegmentAddCommand({
|
|
||||||
type: SegmentType.SNAPSHOT,
|
|
||||||
content: hashData[hash].data,
|
|
||||||
hash: hash
|
|
||||||
}).execute();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
await new ObjAddIdCommand({ id, dt }, ObjectStoreKeys.OBJECT_LIST).execute();
|
|
||||||
console.log('AAAAAAAAAAAAAAAAAAAAAA');
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
throw new Error(`Unsupported type ${this.change.type}`);
|
throw new Error(`Unsupported type ${this.change.type}`);
|
||||||
}
|
}
|
||||||
|
await fnSleep(100);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
private saveSnapshotDto = async (hashData: HashData, type: HashType): Promise<boolean> => {
|
||||||
|
const stored = await BrowserStorage.get(`${ObjectStoreKeys.SERVER_ID}:${this.change.serverId}`);
|
||||||
|
if (stored) return true;
|
||||||
|
|
||||||
|
const segmentArray = type[SyncHashType.PageSnapshotFirstHash];
|
||||||
|
let segment = undefined;
|
||||||
|
if (segmentArray && segmentArray.length === 1) {
|
||||||
|
segment = segmentArray[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
const snapshot: PageSnapshotDto = {
|
||||||
|
data: hashData[type[SyncHashType.PageSnapshotDataDto][0]].data,
|
||||||
|
info: hashData[type[SyncHashType.PageSnapshotInfoDto][0]].data,
|
||||||
|
hash: this.change.hash,
|
||||||
|
segment
|
||||||
|
};
|
||||||
|
// TODO - sync incoming comments !!!!!!!!!!!
|
||||||
|
const data: ObjPageDto = {
|
||||||
|
snapshot: snapshot,
|
||||||
|
comments: { data: [] }
|
||||||
|
};
|
||||||
|
const id = await new ObjNextIdCommand().execute();
|
||||||
|
const dt = Date.now();
|
||||||
|
// Add createdAt, updatedAt, VERSION ----> TO SERVER
|
||||||
|
const obj: ObjDto<ObjPageDto> = {
|
||||||
|
id,
|
||||||
|
data,
|
||||||
|
server: { id: this.change.serverId },
|
||||||
|
version: OBJ_DTO_VERSION,
|
||||||
|
createdAt: dt,
|
||||||
|
updatedAt: dt,
|
||||||
|
type: this.change.type,
|
||||||
|
local: {
|
||||||
|
visible: true,
|
||||||
|
drawVisible: false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
await SwTaskStore.addTask(SwTaskType.WORDS_ADD_INDEX, {
|
||||||
|
words: snapshot.info.words,
|
||||||
|
objectId: id
|
||||||
|
});
|
||||||
|
|
||||||
|
if (segment) {
|
||||||
|
for (const hash of type[SyncHashType.PageSnapshotFirstHash]) {
|
||||||
|
const has = new PageSegmentAddRefCommand(hash);
|
||||||
|
if (has) continue;
|
||||||
|
await new PageSegmentAddCommand({
|
||||||
|
type: SegmentType.SNAPSHOT,
|
||||||
|
content: hashData[hash].data,
|
||||||
|
hash
|
||||||
|
}).execute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await BrowserStorage.set(`${ObjectStoreKeys.OBJECT_ID}:${id}`, obj);
|
||||||
|
await BrowserStorage.set(`${ObjectStoreKeys.SERVER_ID}:${this.change.serverId}`, id);
|
||||||
|
await LinkHrefStore.add(snapshot.info.url, id);
|
||||||
|
await new ObjAddIdCommand({ id, dt }, ObjectStoreKeys.OBJECT_LIST).execute();
|
||||||
|
|
||||||
|
return true;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
import { BrowserStorage } from '@pinmenote/browser-api';
|
||||||
import { ICommand, ServerErrorDto } from '../../../../common/model/shared/common.dto';
|
import { ICommand, ServerErrorDto } from '../../../../common/model/shared/common.dto';
|
||||||
import { ObjDto } from '../../../../common/model/obj/obj.dto';
|
import { ObjDto } from '../../../../common/model/obj/obj.dto';
|
||||||
import { fnConsoleLog } from '../../../../common/fn/fn-console';
|
import { fnConsoleLog } from '../../../../common/fn/fn-console';
|
||||||
@ -21,6 +22,7 @@ import { ApiObjAddCommand, ObjAddResponse } from '../../api/store/obj/api-obj-ad
|
|||||||
import { BeginTxResponse, ObjSingleChange } from '../../api/store/api-store.model';
|
import { BeginTxResponse, ObjSingleChange } from '../../api/store/api-store.model';
|
||||||
import { ApiErrorCode } from '../../../../common/model/shared/api.error-code';
|
import { ApiErrorCode } from '../../../../common/model/shared/api.error-code';
|
||||||
import { ApiObjGetByHashCommand } from '../../api/store/obj/api-obj-get-by-hash.command';
|
import { ApiObjGetByHashCommand } from '../../api/store/obj/api-obj-get-by-hash.command';
|
||||||
|
import { ObjectStoreKeys } from '../../../../common/keys/object.store.keys';
|
||||||
|
|
||||||
export class SyncObjectCommand implements ICommand<Promise<void>> {
|
export class SyncObjectCommand implements ICommand<Promise<void>> {
|
||||||
constructor(private obj: ObjDto, private hash: string, private tx: BeginTxResponse) {}
|
constructor(private obj: ObjDto, private hash: string, private tx: BeginTxResponse) {}
|
||||||
@ -46,10 +48,9 @@ export class SyncObjectCommand implements ICommand<Promise<void>> {
|
|||||||
fnConsoleLog('SyncObjectCommand->setByHash');
|
fnConsoleLog('SyncObjectCommand->setByHash');
|
||||||
throw new Error('PROBLEM !!!!!!!!!!!!!!!');
|
throw new Error('PROBLEM !!!!!!!!!!!!!!!');
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line @typescript-eslint/require-await
|
|
||||||
private async saveServerId(serverId: number): Promise<void> {
|
private async saveServerId(serverId: number): Promise<void> {
|
||||||
this.obj.server = { id: serverId };
|
this.obj.server = { id: serverId };
|
||||||
fnConsoleLog('SyncObjectCommand->saveServerId', serverId, 'objId', this.obj.id);
|
await BrowserStorage.set(`${ObjectStoreKeys.OBJECT_ID}:${this.obj.id}`, this.obj);
|
||||||
//BrowserStorage.set(`${ObjectStoreKeys.OBJECT_ID}:${this.obj.id}`, this.obj);
|
await BrowserStorage.set(`${ObjectStoreKeys.SERVER_ID}:${serverId}`, this.obj.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,6 @@ import { ObjDto } from '../../../../common/model/obj/obj.dto';
|
|||||||
import { ObjPinDataDto, ObjPinDescription, ObjPinDto } from '../../../../common/model/obj/obj-pin.dto';
|
import { ObjPinDataDto, ObjPinDescription, ObjPinDto } from '../../../../common/model/obj/obj-pin.dto';
|
||||||
import { SyncObjectCommand } from './sync-object.command';
|
import { SyncObjectCommand } from './sync-object.command';
|
||||||
import { SyncObjectStatus } from '../sync.model';
|
import { SyncObjectStatus } from '../sync.model';
|
||||||
import { fnConsoleLog } from '../../../../common/fn/fn-console';
|
|
||||||
import { BeginTxResponse, SyncHashType } from '../../api/store/api-store.model';
|
import { BeginTxResponse, SyncHashType } from '../../api/store/api-store.model';
|
||||||
import { ApiSegmentAddCommand } from '../../api/store/segment/api-segment-add.command';
|
import { ApiSegmentAddCommand } from '../../api/store/segment/api-segment-add.command';
|
||||||
import { PinGetCommentCommand } from '../../../../common/command/pin/comment/pin-get-comment.command';
|
import { PinGetCommentCommand } from '../../../../common/command/pin/comment/pin-get-comment.command';
|
||||||
|
@ -39,7 +39,7 @@ export class SyncResetProgressCommand implements ICommand<Promise<void>> {
|
|||||||
|
|
||||||
async resetObjects(): Promise<void> {
|
async resetObjects(): Promise<void> {
|
||||||
let listId = await BrowserStorage.get<number>(ObjectStoreKeys.OBJECT_LIST_ID);
|
let listId = await BrowserStorage.get<number>(ObjectStoreKeys.OBJECT_LIST_ID);
|
||||||
console.log('SyncResetProgressCommand->start !!!!', listId);
|
fnConsoleLog('SyncResetProgressCommand->start !!!!', listId);
|
||||||
const a = Date.now();
|
const a = Date.now();
|
||||||
|
|
||||||
const toSortSet: Set<string> = new Set<string>();
|
const toSortSet: Set<string> = new Set<string>();
|
||||||
@ -50,6 +50,7 @@ export class SyncResetProgressCommand implements ICommand<Promise<void>> {
|
|||||||
const obj = await BrowserStorage.get<ObjDto>(`${ObjectStoreKeys.OBJECT_ID}:${id}`);
|
const obj = await BrowserStorage.get<ObjDto>(`${ObjectStoreKeys.OBJECT_ID}:${id}`);
|
||||||
|
|
||||||
if (obj.server) {
|
if (obj.server) {
|
||||||
|
await BrowserStorage.remove(`${ObjectStoreKeys.SERVER_ID}:${obj.server.id}`);
|
||||||
delete obj['server'];
|
delete obj['server'];
|
||||||
await BrowserStorage.set(`${ObjectStoreKeys.OBJECT_ID}:${id}`, obj);
|
await BrowserStorage.set(`${ObjectStoreKeys.OBJECT_ID}:${id}`, obj);
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
import { ObjDto, ObjRemovedDto, ObjTypeDto } from '../../../common/model/obj/obj.dto';
|
import { ObjDto, ObjRemovedDto, ObjTypeDto } from '../../../common/model/obj/obj.dto';
|
||||||
import { ObjNoteDto, ObjPageNoteDto } from '../../../common/model/obj/obj-note.dto';
|
import { ObjNoteDto, ObjPageNoteDto } from '../../../common/model/obj/obj-note.dto';
|
||||||
import { ICommand } from '../../../common/model/shared/common.dto';
|
import { ICommand } from '../../../common/model/shared/common.dto';
|
||||||
import { ObjDateIndex } from '../../../common/command/obj/index/obj-update-index-add.command';
|
|
||||||
import { ObjGetCommand } from '../../../common/command/obj/obj-get.command';
|
import { ObjGetCommand } from '../../../common/command/obj/obj-get.command';
|
||||||
import { ObjPageDto } from '../../../common/model/obj/obj-page.dto';
|
import { ObjPageDto } from '../../../common/model/obj/obj-page.dto';
|
||||||
import { ObjPdfDto } from '../../../common/model/obj/obj-pdf.dto';
|
import { ObjPdfDto } from '../../../common/model/obj/obj-pdf.dto';
|
||||||
@ -30,13 +29,8 @@ import { SyncObjectStatus, SyncProgress } from './sync.model';
|
|||||||
import { SyncRemovedCommand } from './outgoing/sync-removed.command';
|
import { SyncRemovedCommand } from './outgoing/sync-removed.command';
|
||||||
import { SyncSnapshotCommand } from './outgoing/sync-snapshot.command';
|
import { SyncSnapshotCommand } from './outgoing/sync-snapshot.command';
|
||||||
import { fnConsoleLog } from '../../../common/fn/fn-console';
|
import { fnConsoleLog } from '../../../common/fn/fn-console';
|
||||||
import { fnSleep } from '../../../common/fn/fn-sleep';
|
|
||||||
import { BeginTxResponse } from '../api/store/api-store.model';
|
import { BeginTxResponse } from '../api/store/api-store.model';
|
||||||
|
|
||||||
export interface SyncIndex extends ObjDateIndex {
|
|
||||||
status: SyncObjectStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class SyncIndexCommand implements ICommand<Promise<SyncObjectStatus>> {
|
export class SyncIndexCommand implements ICommand<Promise<SyncObjectStatus>> {
|
||||||
constructor(private progress: SyncProgress, private tx: BeginTxResponse, private id: number) {}
|
constructor(private progress: SyncProgress, private tx: BeginTxResponse, private id: number) {}
|
||||||
|
|
||||||
@ -46,43 +40,33 @@ export class SyncIndexCommand implements ICommand<Promise<SyncObjectStatus>> {
|
|||||||
fnConsoleLog('SyncObjectCommand->syncObject EMPTY', this.id);
|
fnConsoleLog('SyncObjectCommand->syncObject EMPTY', this.id);
|
||||||
return SyncObjectStatus.OBJECT_NOT_EXISTS;
|
return SyncObjectStatus.OBJECT_NOT_EXISTS;
|
||||||
}
|
}
|
||||||
let status = SyncObjectStatus.OK;
|
|
||||||
// Skip for now for those with index
|
// Skip for now for those with index
|
||||||
if (obj.server?.id) return status;
|
if (obj.server?.id) return SyncObjectStatus.OK;
|
||||||
|
|
||||||
switch (obj.type) {
|
switch (obj.type) {
|
||||||
case ObjTypeDto.PageSnapshot:
|
case ObjTypeDto.PageSnapshot:
|
||||||
case ObjTypeDto.PageElementSnapshot: {
|
case ObjTypeDto.PageElementSnapshot: {
|
||||||
status = await new SyncSnapshotCommand(obj as ObjDto<ObjPageDto>, this.tx).execute();
|
return await new SyncSnapshotCommand(obj as ObjDto<ObjPageDto>, this.tx).execute();
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case ObjTypeDto.PageElementPin: {
|
case ObjTypeDto.PageElementPin: {
|
||||||
status = await new SyncPinCommand(obj as ObjDto<ObjPinDto>, this.tx).execute();
|
return await new SyncPinCommand(obj as ObjDto<ObjPinDto>, this.tx).execute();
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case ObjTypeDto.Pdf: {
|
case ObjTypeDto.Pdf: {
|
||||||
status = await new SyncPdfCommand(obj as ObjDto<ObjPdfDto>, this.tx).execute();
|
return await new SyncPdfCommand(obj as ObjDto<ObjPdfDto>, this.tx).execute();
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case ObjTypeDto.Note: {
|
case ObjTypeDto.Note: {
|
||||||
status = await new SyncNoteCommand(obj as ObjDto<ObjNoteDto>, this.tx).execute();
|
return await new SyncNoteCommand(obj as ObjDto<ObjNoteDto>, this.tx).execute();
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case ObjTypeDto.PageNote: {
|
case ObjTypeDto.PageNote: {
|
||||||
status = await new SyncPageNoteCommand(obj as ObjDto<ObjPageNoteDto>, this.tx).execute();
|
return await new SyncPageNoteCommand(obj as ObjDto<ObjPageNoteDto>, this.tx).execute();
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case ObjTypeDto.Removed: {
|
case ObjTypeDto.Removed: {
|
||||||
await new SyncRemovedCommand(obj as ObjDto<ObjRemovedDto>, this.tx).execute();
|
return await new SyncRemovedCommand(obj as ObjDto<ObjRemovedDto>, this.tx).execute();
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
fnConsoleLog('SyncObjectCommand->PROBLEM', obj, 'index', this.id);
|
fnConsoleLog('SyncObjectCommand->PROBLEM', obj, 'index', this.id);
|
||||||
break;
|
return SyncObjectStatus.SERVER_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (status < 0) return status;
|
|
||||||
await fnSleep(100);
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,12 +22,9 @@ import { SyncProgress } from './sync.model';
|
|||||||
import { SyncTxHelper } from './sync-tx.helper';
|
import { SyncTxHelper } from './sync-tx.helper';
|
||||||
import { fnConsoleLog } from '../../../common/fn/fn-console';
|
import { fnConsoleLog } from '../../../common/fn/fn-console';
|
||||||
import { fnDateKeyFormat } from '../../../common/fn/fn-date-format';
|
import { fnDateKeyFormat } from '../../../common/fn/fn-date-format';
|
||||||
import { TokenStorageGetCommand } from '../../../common/command/server/token/token-storage-get.command';
|
|
||||||
import jwtDecode from 'jwt-decode';
|
|
||||||
import { TokenDataDto } from '../../../common/model/shared/token.dto';
|
|
||||||
import { ApiObjGetChangesCommand } from '../api/store/obj/api-obj-get-changes.command';
|
import { ApiObjGetChangesCommand } from '../api/store/obj/api-obj-get-changes.command';
|
||||||
import { SyncObjIncomingHashCommand } from './incoming/sync-obj-incoming-hash.command';
|
import { SyncObjIncomingHashCommand } from './incoming/sync-obj-incoming-hash.command';
|
||||||
import { SyncResetProgressCommand } from './progress/sync-reset-progress.command';
|
import { SyncSetProgressCommand } from './progress/sync-set-progress.command';
|
||||||
|
|
||||||
export class SyncServerCommand implements ICommand<Promise<void>> {
|
export class SyncServerCommand implements ICommand<Promise<void>> {
|
||||||
private static isInSync = false;
|
private static isInSync = false;
|
||||||
@ -38,8 +35,8 @@ export class SyncServerCommand implements ICommand<Promise<void>> {
|
|||||||
try {
|
try {
|
||||||
// await new SyncResetProgressCommand().execute();
|
// await new SyncResetProgressCommand().execute();
|
||||||
|
|
||||||
const token = await new TokenStorageGetCommand().execute();
|
/*const token = await new TokenStorageGetCommand().execute();
|
||||||
if (token) console.log(jwtDecode<TokenDataDto>(token.access_token));
|
if (token) console.log(jwtDecode<TokenDataDto>(token.access_token));*/
|
||||||
|
|
||||||
SyncServerCommand.isInSync = true;
|
SyncServerCommand.isInSync = true;
|
||||||
|
|
||||||
@ -56,16 +53,21 @@ export class SyncServerCommand implements ICommand<Promise<void>> {
|
|||||||
|
|
||||||
private async syncIncoming(progress: SyncProgress): Promise<void> {
|
private async syncIncoming(progress: SyncProgress): Promise<void> {
|
||||||
fnConsoleLog('SyncServerCommand->syncIncoming');
|
fnConsoleLog('SyncServerCommand->syncIncoming');
|
||||||
const changesResp = await new ApiObjGetChangesCommand().execute();
|
const changesResp = await new ApiObjGetChangesCommand(progress.serverId).execute();
|
||||||
if (!changesResp) return;
|
if (!changesResp) return;
|
||||||
for (const change of changesResp.data) {
|
for (let i = 0; i < changesResp.data.length; i++) {
|
||||||
await new SyncObjIncomingHashCommand(change).execute();
|
const change = changesResp.data[i];
|
||||||
break;
|
if (progress.serverId > change.serverId) continue;
|
||||||
|
const result = await new SyncObjIncomingHashCommand(change).execute();
|
||||||
|
fnConsoleLog('syncIncoming', result, 'serverId', change.serverId, 'localId', change.localId);
|
||||||
|
if (result) {
|
||||||
|
progress.serverId = change.serverId;
|
||||||
|
await new SyncSetProgressCommand(progress).execute();
|
||||||
|
} else {
|
||||||
|
fnConsoleLog('SyncServerCommand->syncIncoming->ERROR !!!!!!!!!!!!!!!!!!!!1');
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const token = await new TokenStorageGetCommand().execute();
|
|
||||||
if (!token) return;
|
|
||||||
const tokenData = jwtDecode(token.access_token);
|
|
||||||
console.log('tokenData', tokenData);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async syncOutgoing(progress: SyncProgress): Promise<void> {
|
private async syncOutgoing(progress: SyncProgress): Promise<void> {
|
||||||
|
@ -19,12 +19,13 @@ import { IndexWordsAddCommand } from '../command/task/index-words-add.command';
|
|||||||
import { IndexWordsRemoveCommand } from '../command/task/index-words-remove.command';
|
import { IndexWordsRemoveCommand } from '../command/task/index-words-remove.command';
|
||||||
import { SwTaskStore } from '../../common/store/sw-task.store';
|
import { SwTaskStore } from '../../common/store/sw-task.store';
|
||||||
import { fnConsoleLog } from '../../common/fn/fn-console';
|
import { fnConsoleLog } from '../../common/fn/fn-console';
|
||||||
|
import { fnSleep } from '../../common/fn/fn-sleep';
|
||||||
|
|
||||||
export class TaskExecutor {
|
export class TaskExecutor {
|
||||||
private static runningTask?: string;
|
private static runningTask?: string;
|
||||||
static async dequeue() {
|
static async dequeue() {
|
||||||
fnConsoleLog('TaskExecutor.dequeue');
|
|
||||||
const queue = await SwTaskStore.getQueue();
|
const queue = await SwTaskStore.getQueue();
|
||||||
|
fnConsoleLog('TaskExecutor.dequeue', queue.length);
|
||||||
await this.execute(queue);
|
await this.execute(queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,6 +53,11 @@ export class TaskExecutor {
|
|||||||
queue.shift();
|
queue.shift();
|
||||||
await SwTaskStore.saveQueue(queue);
|
await SwTaskStore.saveQueue(queue);
|
||||||
this.runningTask = undefined;
|
this.runningTask = undefined;
|
||||||
|
// Try empty queue
|
||||||
|
if (queue.length > 0) {
|
||||||
|
await fnSleep(1000);
|
||||||
|
await this.dequeue();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static updateTask = async (task: SwTaskData): Promise<void> => {
|
private static updateTask = async (task: SwTaskData): Promise<void> => {
|
||||||
|
Loading…
Reference in New Issue
Block a user