Skip to content

Commit

Permalink
Merge feat/2-0-8-features into feat/debounce-remote-manager-sync
Browse files Browse the repository at this point in the history
  • Loading branch information
miguelsw committed Apr 30, 2024
2 parents 85898c5 + 877053f commit ac33aa4
Show file tree
Hide file tree
Showing 22 changed files with 150 additions and 31 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "internxt-drive",
"version": "2.0.7",
"version": "2.0.8",
"author": "Internxt <[email protected]>",
"description": "Internxt Drive client UI",
"license": "AGPL-3.0",
Expand Down
2 changes: 1 addition & 1 deletion release/app/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "internxt-drive",
"version": "2.0.7",
"version": "2.0.8",
"description": "Internxt Drive client UI",
"main": "./dist/main/main.js",
"author": "Internxt <[email protected]>",
Expand Down
45 changes: 32 additions & 13 deletions src/apps/main/background-processes/sync-engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,19 @@ let worker: BrowserWindow | null = null;
let workerIsRunning = false;
let startingWorker = false;
let healthCheckSchedule: nodeSchedule.Job | null = null;
let attemptsAlreadyStarting = 0;

ipcMain.once('SYNC_ENGINE_PROCESS_SETUP_SUCCESSFUL', () => {
Logger.debug('[MAIN] SYNC ENGINE RUNNING');
workerIsRunning = true;
startingWorker = false;
});

ipcMain.on('SYNC_ENGINE_PROCESS_SETUP_FAILED', () => {
Logger.debug('[MAIN] SYNC ENGINE FAILED');
workerIsRunning = false;
startingWorker = false;
});

async function healthCheck() {
const responsePromise = new Promise<void>((resolve, reject) => {
Expand Down Expand Up @@ -48,6 +61,11 @@ function scheduleHeathCheck() {
Sentry.captureMessage(warning);
workerIsRunning = false;
worker?.destroy();
if (attemptsAlreadyStarting >= 3) {
attemptsAlreadyStarting = 0;
startingWorker = false;
return;
}
spawnSyncEngineWorker();

Check warning on line 69 in src/apps/main/background-processes/sync-engine.ts

View workflow job for this annotation

GitHub Actions / 🧪 Lint and test

'spawnSyncEngineWorker' was used before it was defined
});

Expand All @@ -59,6 +77,7 @@ function scheduleHeathCheck() {
function spawnSyncEngineWorker() {
if (startingWorker) {
Logger.info('[MAIN] Worker is already starting');
attemptsAlreadyStarting++;
return;
}
if (workerIsRunning) {
Expand Down Expand Up @@ -100,18 +119,6 @@ function spawnSyncEngineWorker() {
spawnSyncEngineWorker();
}
});

ipcMain.once('SYNC_ENGINE_PROCESS_SETUP_SUCCESSFUL', () => {
Logger.debug('[MAIN] SYNC ENGINE RUNNING');
workerIsRunning = true;
startingWorker = false;
});

ipcMain.on('SYNC_ENGINE_PROCESS_SETUP_FAILED', () => {
Logger.debug('[MAIN] SYNC ENGINE NOT RUNNING');
workerIsRunning = false;
startingWorker = false;
});
}

export async function stopSyncEngineWatcher() {
Expand Down Expand Up @@ -219,14 +226,26 @@ async function stopAndClearSyncEngineWatcher() {

export function updateSyncEngine() {
try {
worker?.webContents.send('UPDATE_SYNC_ENGINE_PROCESS');
if ( worker && worker?.webContents && !worker.isDestroyed() ) {
worker?.webContents.send('UPDATE_SYNC_ENGINE_PROCESS');
}
} catch (err) {
// TODO: handle error
Logger.error(err);
Sentry.captureException(err);
}
}

export function fallbackSyncEngine() {
try {
if ( worker && worker?.webContents && !worker.isDestroyed() ) {
worker?.webContents.send('FALLBACK_SYNC_ENGINE_PROCESS');
}
} catch (err) {
Logger.error(err);
}
}

eventBus.on('USER_LOGGED_OUT', stopAndClearSyncEngineWatcher);
eventBus.on('USER_WAS_UNAUTHORIZED', stopAndClearSyncEngineWatcher);
eventBus.on('INITIAL_SYNC_READY', spawnSyncEngineWorker);
2 changes: 2 additions & 0 deletions src/apps/main/preload.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,5 +167,7 @@ declare interface Window {
startRemoteSync: () => Promise<void>;
openUrl: (url: string) => Promise<void>;
getPreferredAppLanguage: () => Promise<Array<string>>;
syncManually: () => Promise<void>;
getRecentlywasSyncing: () => Promise<boolean>;
};
}
8 changes: 8 additions & 0 deletions src/apps/main/preload.js
Original file line number Diff line number Diff line change
Expand Up @@ -296,5 +296,13 @@ contextBridge.exposeInMainWorld('electron', {
getPreferredAppLanguage() {
return ipcRenderer.invoke('APP:PREFERRED_LANGUAGE');
},
syncManually() {
return ipcRenderer.invoke('SYNC_MANUALLY');
},
getRecentlywasSyncing() {
const FIVE_SECONDS = 5000;
return ipcRenderer.invoke('CHECK_SYNC_IN_PROGRESS', FIVE_SECONDS);
},

path,
});
7 changes: 4 additions & 3 deletions src/apps/main/remote-sync/RemoteSyncManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
RemoteSyncedFile,
SyncConfig,
SYNC_OFFSET_MS,
WAITING_AFTER_SYNCING
WAITING_AFTER_SYNCING_DEFAULT
} from './helpers';
import { reportError } from '../bug-report/service';

Expand Down Expand Up @@ -72,10 +72,11 @@ export class RemoteSyncManager {
* Consult if recently the RemoteSyncManager was syncing
* @returns True if the RemoteSyncManager was syncing recently
* @returns False if the RemoteSyncManager was not syncing recently
* @param milliseconds Time in milliseconds to check if the RemoteSyncManager was syncing
*/
recentlyWasSyncing() {
recentlyWasSyncing( milliseconds: number) {
const passedTime = Date.now() - ( this.getLastSyncingFinishedTimestamp()?.getTime() ?? Date.now() );
return passedTime < WAITING_AFTER_SYNCING;
return passedTime < ( milliseconds ?? WAITING_AFTER_SYNCING_DEFAULT );
}

resetRemoteSync() {
Expand Down
28 changes: 23 additions & 5 deletions src/apps/main/remote-sync/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { ipcMain } from 'electron';
import { reportError } from '../bug-report/service';
import { sleep } from '../util';
import { broadcastToWindows } from '../windows';
import { updateSyncEngine } from '../background-processes/sync-engine';
import { updateSyncEngine,fallbackSyncEngine} from '../background-processes/sync-engine';
import { debounce } from 'lodash';

const SYNC_DEBOUNCE_DELAY = 3_000;
Expand Down Expand Up @@ -80,9 +80,27 @@ ipcMain.handle('get-remote-sync-status', () =>
remoteSyncManager.getSyncStatus()
);

const debouncedSynchronization = debounce(async () => {
export async function updateRemoteSync(): Promise<void> {
// Wait before checking for updates, could be possible
// that we received the notification, but if we check
// for new data we don't receive it
await sleep(2_000);
await startRemoteSync();
updateSyncEngine();
}
export async function fallbackRemoteSync(): Promise<void> {
await sleep(2_000);
fallbackSyncEngine();
}

ipcMain.handle('SYNC_MANUALLY', async () => {
Logger.info('[Manual Sync] Received manual sync event');
await updateRemoteSync();
await fallbackRemoteSync();
});

const debouncedSynchronization = debounce(async () => {
await updateRemoteSync();
}, SYNC_DEBOUNCE_DELAY);

eventBus.on('RECEIVED_REMOTE_CHANGES', async () => {
Expand Down Expand Up @@ -118,9 +136,9 @@ ipcMain.on('CHECK_SYNC_CHANGE_STATUS', async (_, placeholderStates) => {
remoteSyncManager.placeholderStatus = placeholderStates;
});

ipcMain.handle('CHECK_SYNC_IN_PROGRESS', async () => {
ipcMain.handle('CHECK_SYNC_IN_PROGRESS', async (_, milliSeconds : number) => {
const syncingStatus: RemoteSyncStatus = 'SYNCING';
const isSyncing = remoteSyncManager.getSyncStatus() === syncingStatus;
const recentlySyncing = remoteSyncManager.recentlyWasSyncing();
return isSyncing || recentlySyncing; // If it's syncing or recently was syncing
const recentlySyncing = remoteSyncManager.recentlyWasSyncing(milliSeconds);
return isSyncing || recentlySyncing; // syncing or recently was syncing
});
2 changes: 1 addition & 1 deletion src/apps/main/remote-sync/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ export type SyncConfig = {
};

export const SYNC_OFFSET_MS = 0;
export const WAITING_AFTER_SYNCING = 1000 * 60 * 3; // 5 minutes
export const WAITING_AFTER_SYNCING_DEFAULT = 1000 * 60 * 3;

export const lastSyncedAtIsNewer = (
itemUpdatedAt: Date,
Expand Down
1 change: 1 addition & 0 deletions src/apps/renderer/localize/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@
},
"dropdown": {
"preferences": "Preferences",
"sync": "Sync",
"issues": "Issues",
"send-feedback": "Send feedback",
"support": "Support",
Expand Down
1 change: 1 addition & 0 deletions src/apps/renderer/localize/locales/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@
},
"dropdown": {
"preferences": "Preferencias",
"sync": "Sincronizar",
"issues": "Lista de errores",
"send-feedback": "Enviar feedback",
"support": "Ayuda",
Expand Down
1 change: 1 addition & 0 deletions src/apps/renderer/localize/locales/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@
},
"dropdown": {
"preferences": "Préférences",
"sync": "Synchroniser",
"issues": "Liste d'erreurs",
"support": "Aide",
"logout": "Déconnecter",
Expand Down
25 changes: 25 additions & 0 deletions src/apps/renderer/pages/Widget/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import useUsage from '../../hooks/useUsage';
import useVirtualDriveStatus from '../../hooks/VirtualDriveStatus';
import { reportError } from '../../utils/sentry';


export default function Header() {
const { translate } = useTranslationContext();
const { virtualDriveCanBeOpened } = useVirtualDriveStatus();
Expand Down Expand Up @@ -45,6 +46,19 @@ export default function Header() {
window.electron.quit();
}

const wasSyncing = () => {
return window.electron.getRecentlywasSyncing();
};

async function onSyncClick() {
const notAllowed = await wasSyncing();
if (notAllowed) {
return;
}
window.electron.syncManually();
}


const handleOpenURL = async (URL: string) => {
try {
await window.electron.openUrl(URL);
Expand Down Expand Up @@ -195,6 +209,17 @@ export default function Header() {
</div>
)}
</Menu.Item>
<Menu.Item>
{({active}) => {

return (<div>
<DropdownItem active={active} onClick={onSyncClick} >
<span>{translate('widget.header.dropdown.sync')}</span>
</DropdownItem>
</div>);
}
}
</Menu.Item>
<Menu.Item>
{({ active }) => (
<div>
Expand Down
3 changes: 2 additions & 1 deletion src/apps/sync-engine/BindingManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -334,13 +334,14 @@ export class BindingsManager {
return this.container.pollingMonitorStart.run(this.polling.bind(this));
}

private async polling(): Promise<void> {
async polling(): Promise<void> {
try {
Logger.info('[SYNC ENGINE] Monitoring polling...');

const fileInPendingPaths =
(await this.container.virtualDrive.getPlaceholderWithStatePending()) as Array<string>;
Logger.info('[SYNC ENGINE] fileInPendingPaths', fileInPendingPaths);

await this.container.fileSyncOrchestrator.run(fileInPendingPaths);
ipcRenderer.send('CHECK_SYNC');
} catch (error) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { FilePlaceholderConverter } from '../../../../context/virtual-drive/file
import { FileSyncStatusUpdater } from '../../../../context/virtual-drive/files/application/FileSyncStatusUpdater';
import { FileCheckerStatusInRoot } from '../../../../context/virtual-drive/files/application/FileCheckerStatusInRoot';
import { FilesPlaceholderDeleter } from '../../../../context/virtual-drive/files/application/FilesPlaceholderDeleter';
import { FileIdentityUpdater } from '../../../../context/virtual-drive/files/application/FileIndetityUpdater';

export interface FilesContainer {
fileFinderByContentsId: FileFinderByContentsId;
Expand All @@ -34,4 +35,5 @@ export interface FilesContainer {
filePlaceholderConverter: FilePlaceholderConverter;
fileSyncStatusUpdater: FileSyncStatusUpdater;
filesCheckerStatusInRoot: FileCheckerStatusInRoot;
fileIdentityUpdater: FileIdentityUpdater;
}
5 changes: 5 additions & 0 deletions src/apps/sync-engine/dependency-injection/files/builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import { FileSyncStatusUpdater } from '../../../../context/virtual-drive/files/a
import { FileContentsUpdater } from '../../../../context/virtual-drive/files/application/FileContentsUpdater';
import { FileCheckerStatusInRoot } from '../../../../context/virtual-drive/files/application/FileCheckerStatusInRoot';
import { FilesPlaceholderDeleter } from '../../../../context/virtual-drive/files/application/FilesPlaceholderDeleter';
import { FileIdentityUpdater } from '../../../../context/virtual-drive/files/application/FileIndetityUpdater';

export async function buildFilesContainer(
folderContainer: FoldersContainer,
Expand Down Expand Up @@ -144,10 +145,13 @@ export async function buildFilesContainer(
remoteFileSystem
);

const fileIdentityUpdater = new FileIdentityUpdater(localFileSystem);

const fileSyncronizer = new FileSyncronizer(
repository,
fileSyncStatusUpdater,
filePlaceholderConverter,
fileIdentityUpdater,
fileCreator,
sharedContainer.absolutePathToRelativeConverter,
folderContainer.folderCreator,
Expand Down Expand Up @@ -176,6 +180,7 @@ export async function buildFilesContainer(
filePlaceholderConverter,
fileSyncStatusUpdater,
filesCheckerStatusInRoot,
fileIdentityUpdater,
};

return { container, subscribers: [] };
Expand Down
8 changes: 8 additions & 0 deletions src/apps/sync-engine/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,14 @@ async function setUp() {
Logger.info('[SYNC ENGINE] sync engine updated successfully');
});

ipcRenderer.on('FALLBACK_SYNC_ENGINE_PROCESS', async () => {
Logger.info('[SYNC ENGINE] Fallback sync engine');

await bindings.polling();

Logger.info('[SYNC ENGINE] sync engine fallback successfully');
});

ipcRenderer.on('STOP_AND_CLEAR_SYNC_ENGINE_PROCESS', async (event) => {
Logger.info('[SYNC ENGINE] Stopping and clearing sync engine');

Expand Down
10 changes: 10 additions & 0 deletions src/context/virtual-drive/files/application/FileIndetityUpdater.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { File } from '../domain/File';
import { LocalFileSystem } from '../domain/file-systems/LocalFileSystem';

export class FileIdentityUpdater {
constructor(private readonly localFileSystem: LocalFileSystem) {}

async run(file: File) {
await this.localFileSystem.updateFileIdentity(file.path, file.placeholderId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { File } from '../domain/File';
import { FileSyncStatusUpdater } from './FileSyncStatusUpdater';
import { FilePlaceholderConverter } from './FIlePlaceholderConverter';
import { FileContentsUpdater } from './FileContentsUpdater';
import { FileIdentityUpdater } from './FileIndetityUpdater';

export class FileSyncronizer {
// queue of files to be uploaded
Expand All @@ -23,6 +24,7 @@ export class FileSyncronizer {
private readonly repository: FileRepository,
private readonly fileSyncStatusUpdater: FileSyncStatusUpdater,
private readonly filePlaceholderConverter: FilePlaceholderConverter,
private readonly fileIdentityUpdater: FileIdentityUpdater,
private readonly fileCreator: FileCreator,
private readonly absolutePathToRelativeConverter: AbsolutePathToRelativeConverter,
private readonly folderCreator: FolderCreator,
Expand Down Expand Up @@ -148,6 +150,7 @@ export class FileSyncronizer {
private async convertAndUpdateSyncStatus(file: File) {
await Promise.all([
this.filePlaceholderConverter.run(file),
this.fileIdentityUpdater.run(file),
this.fileSyncStatusUpdater.run(file),
]);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,9 @@ export interface LocalFileSystem {
getPlaceholderStateByRelativePath(
relativePath: string
): Promise<PlaceholderState>;

updateFileIdentity(
path: File['path'],
newIdentity: string
): Promise<void>;
}
Loading

0 comments on commit ac33aa4

Please sign in to comment.