Skip to content

Commit

Permalink
Merge branch 'feat/2-0-8-features' into feat/retry-sync-post-logout
Browse files Browse the repository at this point in the history
  • Loading branch information
ArceDanielShok authored Apr 30, 2024
2 parents 400cce0 + 356f723 commit 1f4086f
Show file tree
Hide file tree
Showing 10 changed files with 91 additions and 30 deletions.
8 changes: 7 additions & 1 deletion src/apps/main/background-processes/sync-engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import Logger from 'electron-log';
import eventBus from '../event-bus';
import nodeSchedule from 'node-schedule';
import * as Sentry from '@sentry/electron/main';
import { checkSyncEngineInProcess } from '../remote-sync/handlers';

let worker: BrowserWindow | null = null;
let workerIsRunning = false;
Expand All @@ -26,6 +27,7 @@ ipcMain.on('SYNC_ENGINE_PROCESS_SETUP_FAILED', () => {
async function healthCheck() {
const responsePromise = new Promise<void>((resolve, reject) => {
ipcMain.once('SYNC_ENGINE:PONG', () => {
Logger.debug('Health check PONG resolved');
resolve();
});

Expand Down Expand Up @@ -70,7 +72,11 @@ function scheduleHeathCheck() {
});

healthCheckSchedule = nodeSchedule.scheduleJob('*/30 * * * * *', async () => {
await relaunchOnFail();
const workerIsPending = checkSyncEngineInProcess(5_000);
Logger.debug('Health check', workerIsPending ? 'Worker is pending' : 'Worker is running');
if(!workerIsPending) {
await relaunchOnFail();
}
});
}

Expand Down
13 changes: 7 additions & 6 deletions src/apps/main/fordwardToWindows.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { broadcastToWindows } from './windows';
import { ipcMainDrive } from './ipcs/mainDrive';
import { ipcMainSyncEngine } from './ipcs/ipcMainSyncEngine';
import { FileErrorInfo } from '../shared/IPC/events/drive';
import { setIsProcessing } from './remote-sync/handlers';

ipcMainDrive.on('FILE_DELETED', (_, payload) => {
const { nameWithExtension } = payload;
Expand All @@ -14,7 +15,7 @@ ipcMainDrive.on('FILE_DELETED', (_, payload) => {

ipcMainDrive.on('FILE_DOWNLOADING', (_, payload) => {
const { nameWithExtension, processInfo } = payload;

setIsProcessing(true);
broadcastToWindows('sync-info-update', {
action: 'DOWNLOADING',
name: nameWithExtension,
Expand All @@ -24,7 +25,7 @@ ipcMainDrive.on('FILE_DOWNLOADING', (_, payload) => {

ipcMainDrive.on('FILE_PREPARING', (_, payload) => {
const { nameWithExtension, processInfo } = payload;

setIsProcessing(true);
broadcastToWindows('sync-info-update', {
action: 'PREPARING',
name: nameWithExtension,
Expand All @@ -34,7 +35,7 @@ ipcMainDrive.on('FILE_PREPARING', (_, payload) => {

ipcMainDrive.on('FILE_DOWNLOADED', (_, payload) => {
const { nameWithExtension } = payload;

setIsProcessing(false);
broadcastToWindows('sync-info-update', {
action: 'DOWNLOADED',
name: nameWithExtension,
Expand All @@ -61,7 +62,7 @@ ipcMainDrive.on('FILE_OVERWRITED', (_, payload) => {

ipcMainDrive.on('FILE_RENAMING', (_, payload) => {
const { nameWithExtension, oldName } = payload;

setIsProcessing(true);
broadcastToWindows('sync-info-update', {
action: 'RENAMING',
name: nameWithExtension,
Expand All @@ -71,7 +72,7 @@ ipcMainDrive.on('FILE_RENAMING', (_, payload) => {

ipcMainDrive.on('FILE_RENAMED', (_, payload) => {
const { nameWithExtension } = payload;

setIsProcessing(false);
broadcastToWindows('sync-info-update', {
action: 'RENAMED',
name: nameWithExtension,
Expand All @@ -89,7 +90,7 @@ ipcMainDrive.on('FILE_CLONNED', (_, payload) => {

ipcMainDrive.on('FILE_UPLOADING', (_, payload) => {
const { nameWithExtension, processInfo } = payload;

setIsProcessing(true);
broadcastToWindows('sync-info-update', {
action: 'UPLOADING',
name: nameWithExtension,
Expand Down
15 changes: 11 additions & 4 deletions src/apps/main/remote-sync/RemoteSyncManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export class RemoteSyncManager {
private totalFilesUnsynced: string[] = [];
private totalFoldersSynced = 0;
private lastSyncingFinishedTimestamp: Date | null = null;
private _isProcessRunning = false;

constructor(
private db: {
Expand Down Expand Up @@ -165,6 +166,16 @@ export class RemoteSyncManager {

return true;
}

set isProcessRunning(value: boolean) {
if (value) {
this.changeStatus('SYNCING');
} else {
this.checkRemoteSyncStatus();
}
this._isProcessRunning = value;
}

private changeStatus(newStatus: RemoteSyncStatus) {
this.addLastSyncingFinishedTimestamp();
if (newStatus === this.status) return;
Expand All @@ -183,10 +194,6 @@ export class RemoteSyncManager {
}

private checkRemoteSyncStatus() {
if (this._placeholdersStatus === 'SYNCING') {
this.changeStatus('SYNCING');
return;
}
// placeholders are still sync-pending
if (this._placeholdersStatus === 'SYNC_PENDING') {
this.changeStatus('SYNC_PENDING');
Expand Down
18 changes: 17 additions & 1 deletion src/apps/main/remote-sync/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,17 @@ export async function fallbackRemoteSync(): Promise<void> {
fallbackSyncEngine();
}

export function checkSyncEngineInProcess (milliSeconds: number) {
const syncingStatus: RemoteSyncStatus = 'SYNCING';
const isSyncing = remoteSyncManager.getSyncStatus() === syncingStatus;
const recentlySyncing = remoteSyncManager.recentlyWasSyncing(milliSeconds);
return isSyncing || recentlySyncing; // syncing or recently was syncing
};

export function setIsProcessing(isProcessing: boolean) {
remoteSyncManager.isProcessRunning = isProcessing;
}

ipcMain.handle('SYNC_MANUALLY', async () => {
Logger.info('[Manual Sync] Received manual sync event');
await updateRemoteSync();
Expand Down Expand Up @@ -159,9 +170,14 @@ ipcMain.on('CHECK_SYNC_CHANGE_STATUS', async (_, placeholderStates) => {
remoteSyncManager.placeholderStatus = placeholderStates;
});

ipcMain.handle('CHECK_SYNC_IN_PROGRESS', async (_, milliSeconds: number) => {
export async function checkSyncInProgress(milliSeconds: number) {
const syncingStatus: RemoteSyncStatus = 'SYNCING';
const isSyncing = remoteSyncManager.getSyncStatus() === syncingStatus;
const recentlySyncing = remoteSyncManager.recentlyWasSyncing(milliSeconds);
return isSyncing || recentlySyncing; // syncing or recently was syncing
}

ipcMain.handle('CHECK_SYNC_IN_PROGRESS', async (_, milliSeconds: number) => {
return await checkSyncInProgress(milliSeconds);
});

6 changes: 4 additions & 2 deletions src/apps/shared/fs/write-readable-to-file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ export class WriteReadableToFile {
resolve();
return;
}
if (size !== expectedSize) {
const tolerance = 1; // set the tolerance value to 1 byte
if (Math.abs(size - expectedSize) <= tolerance) {
resolve();
} else {
reject(new Error('Wried file does not have expected size'));
return;
}

resolve();
Expand Down
17 changes: 9 additions & 8 deletions src/apps/sync-engine/BindingManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { ipcRenderer } from 'electron';
import { ServerFileStatus } from '../../context/shared/domain/ServerFile';
import { ServerFolderStatus } from '../../context/shared/domain/ServerFolder';
import * as Sentry from '@sentry/electron/renderer';
import { runner } from '../utils/runner';

export type CallbackDownload = (
success: boolean,
Expand Down Expand Up @@ -117,8 +118,8 @@ export class BindingsManager {
callback: CallbackDownload
) => {
try {
Logger.debug('[Fetch Data Callback] Donwloading begins');
const path = await controllers.downloadFile.execute(contentsId);
Logger.debug('[Fetch Data Callback] Donwloading begins',);
const path = await controllers.downloadFile.execute(contentsId, callback);
const file = controllers.downloadFile.fileFinderByContentsId(
contentsId
.replace(
Expand Down Expand Up @@ -210,6 +211,7 @@ export class BindingsManager {
Logger.debug('validateDataCallback');
},
cancelFetchDataCallback: () => {
// TODO: clean up temp file, free up space of placeholder
Logger.debug('cancelFetchDataCallback');
},
fetchPlaceholdersCallback: () => {
Expand Down Expand Up @@ -248,9 +250,12 @@ export class BindingsManager {

await this.container.virtualDrive.connectSyncRoot();

await this.load();
// run in order the following functions
await runner([
this.load.bind(this),
this.polling.bind(this),
]);

await this.polling();
}

watch() {
Expand All @@ -265,9 +270,6 @@ export class BindingsManager {
async cleanUp() {
await VirtualDrive.unregisterSyncRoot(this.paths.root);

const itemsSearcher = new ItemsSearcher();
const remainingItems = itemsSearcher.listFilesAndFolders(this.paths.root);

const files = await this.container.retrieveAllFiles.run();
const folders = await this.container.retrieveAllFolders.run();

Expand All @@ -285,7 +287,6 @@ export class BindingsManager {
);
});

Logger.debug('remainingItems', remainingItems);
Logger.debug('win32AbsolutePaths', win32AbsolutePaths);

// find all common string in remainingItems and win32AbsolutePaths
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { ContentsDownloader } from '../../../../context/virtual-drive/contents/a
import { FileFinderByContentsId } from '../../../../context/virtual-drive/files/application/FileFinderByContentsId';
import { FilePlaceholderId } from '../../../../context/virtual-drive/files/domain/PlaceholderId';
import { CallbackController } from './CallbackController';
import { CallbackDownload } from '../../BindingManager';

export class DownloadFileController extends CallbackController {
constructor(
Expand All @@ -12,21 +13,22 @@ export class DownloadFileController extends CallbackController {
super();
}

private async action(id: string): Promise<string> {
private async action(id: string, callback: CallbackDownload): Promise<string> {
const file = this.fileFinder.run(id);
return await this.downloader.run(file);
Logger.info('[Begin] Download: ', file.path);
return await this.downloader.run(file, callback);
}

fileFinderByContentsId(contentsId: string) {
return this.fileFinder.run(contentsId);
}

async execute(filePlaceholderId: FilePlaceholderId): Promise<string> {
async execute(filePlaceholderId: FilePlaceholderId, callback: CallbackDownload): Promise<string> {
const trimmedId = this.trim(filePlaceholderId);

try {
const [_, contentsId] = trimmedId.split(':');
return await this.action(contentsId);
return await this.action(contentsId, callback);
} catch (error: unknown) {
Logger.error(
'Error downloading a file, going to refresh and retry: ',
Expand All @@ -37,7 +39,7 @@ export class DownloadFileController extends CallbackController {
setTimeout(async () => {
try {
const [_, contentsId] = trimmedId.split(':');
const result = await this.action(contentsId);
const result = await this.action(contentsId, callback);
resolve(result);
} catch (error) {
reject(error);
Expand Down
1 change: 1 addition & 0 deletions src/apps/sync-engine/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ async function setUp() {
});

ipcRenderer.on('SYNC_ENGINE:PING', (event) => {
Logger.info('[SYNC ENGINE] Sending Pong');
event.sender.send('SYNC_ENGINE:PONG');
});

Expand Down
11 changes: 11 additions & 0 deletions src/apps/utils/runner.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* Run a list of async functions in sequence
* @param steps - List of async functions
* @returns void
*/
export async function runner( steps: Array<() => Promise<void>> ) {
for ( const step of steps ) {
// run step by step
await step();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@ import { LocalFileWriter } from '../domain/LocalFileWriter';
import { ContentFileDownloader } from '../domain/contentHandlers/ContentFileDownloader';
import { TemporalFolderProvider } from './temporalFolderProvider';
import * as fs from 'fs';
import { CallbackDownload } from '../../../../apps/sync-engine/BindingManager';

export class ContentsDownloader {
private readableDownloader: Readable | null;
private WAIT_TO_SEND_PROGRESS = 20000;
private progressAt: Date | null = null;
constructor(
private readonly managerFactory: ContentsManagersFactory,
private readonly localWriter: LocalFileWriter,
Expand All @@ -24,13 +27,14 @@ export class ContentsDownloader {
this.readableDownloader = null;
}

private async registerEvents(downloader: ContentFileDownloader, file: File) {
private async registerEvents(downloader: ContentFileDownloader, file: File, callback: CallbackDownload) {
const location = await this.temporalFolderProvider();
ensureFolderExists(location);

const filePath = path.join(location, file.nameWithExtension);

downloader.on('start', () => {
this.progressAt = new Date();
this.ipc.send('FILE_DOWNLOADING', {
name: file.name,
extension: file.type,
Expand All @@ -47,6 +51,8 @@ export class ContentsDownloader {
const fileSizeInBytes = stats.size;
const progress = fileSizeInBytes / file.size;

await this.waitToCb(callback, filePath);

this.ipc.send('FILE_DOWNLOADING', {
name: file.name,
extension: file.type,
Expand All @@ -60,6 +66,7 @@ export class ContentsDownloader {
});

downloader.on('error', (error: Error) => {
Logger.error('[Server] Error downloading file', error);
this.ipc.send('FILE_DOWNLOAD_ERROR', {
name: file.name,
extension: file.type,
Expand All @@ -75,10 +82,17 @@ export class ContentsDownloader {
});
}

async run(file: File): Promise<string> {
private async waitToCb(callback: CallbackDownload, filePath: string) {
if ( this.progressAt && (new Date().getTime() - this.progressAt.getTime()) > this.WAIT_TO_SEND_PROGRESS) {
await callback(true, filePath);
this.progressAt = new Date();
}
}

async run(file: File, callback: CallbackDownload): Promise<string> {
const downloader = this.managerFactory.downloader();

await this.registerEvents(downloader, file);
await this.registerEvents(downloader, file, callback);

const readable = await downloader.download(file);
this.readableDownloader = readable;
Expand Down

0 comments on commit 1f4086f

Please sign in to comment.