Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/fully sync update #457

Merged
merged 14 commits into from
Feb 22, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion src/apps/main/remote-sync/RemoteSyncManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { DriveFile } from '../database/entities/DriveFile';
export class RemoteSyncManager {
private foldersSyncStatus: RemoteSyncStatus = 'IDLE';
private filesSyncStatus: RemoteSyncStatus = 'IDLE';
private _placeholdersStatus: RemoteSyncStatus = 'IDLE';
private status: RemoteSyncStatus = 'IDLE';
private onStatusChangeCallbacks: Array<
(newStatus: RemoteSyncStatus) => void
Expand All @@ -34,9 +35,14 @@ export class RemoteSyncManager {
fetchFoldersLimitPerRequest: number;
syncFiles: boolean;
syncFolders: boolean;
}
} // , // private chekers: { // fileCheker: FileCheckerStatusInRoot; // }
) {}

set placeholderStatus(status: RemoteSyncStatus) {
this._placeholdersStatus = status;
this.checkRemoteSyncStatus();
}

onStatusChange(callback: (newStatus: RemoteSyncStatus) => void) {
if (typeof callback !== 'function') return;
this.onStatusChangeCallbacks.push(callback);
Expand Down Expand Up @@ -70,6 +76,7 @@ export class RemoteSyncManager {
async startRemoteSync() {
// const start = Date.now();
Logger.info('Starting remote to local sync');
Logger.info('Checking if we are in a valid state to start the sync');

const testPassed = this.smokeTest();

Expand Down Expand Up @@ -151,6 +158,15 @@ 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');
return;
}
// We only syncing files
if (
this.config.syncFiles &&
Expand Down
16 changes: 16 additions & 0 deletions src/apps/main/remote-sync/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,19 @@ eventBus.on('USER_LOGGED_OUT', () => {
remoteSyncManager.resetRemoteSync();
clearRemoteSyncStore();
});

ipcMain.on('CHECK_SYNC', (event) => {
Logger.info('Checking sync');
event.sender.send(
'CHECK_SYNC_ENGINE_RESPONSE',
'Dato obtenido del proceso de sincronización'
);
});

ipcMain.on('CHECK_SYNC_CHANGE_STATUS', async (_, placeholderStates) => {
await sleep(2_000);
Logger.info('[SYNC ENGINE] Changing status');
remoteSyncManager.placeholderStatus = 'SYNCING';
await sleep(7_00);
remoteSyncManager.placeholderStatus = placeholderStates;
});
7 changes: 6 additions & 1 deletion src/apps/main/remote-sync/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,12 @@ export type RemoteSyncedFolder = {
status: string;
};

export type RemoteSyncStatus = 'IDLE' | 'SYNCED' | 'SYNCING' | 'SYNC_FAILED';
export type RemoteSyncStatus =
| 'IDLE'
| 'SYNCED'
| 'SYNCING'
| 'SYNC_FAILED'
| 'SYNC_PENDING';
export type SyncConfig = {
retry: number;
maxRetries: number;
Expand Down
8 changes: 8 additions & 0 deletions src/apps/renderer/hooks/useSyncStatus.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ export default function useSyncStatus(
if (status === 'SYNC_FAILED') {
setSyncStatus('FAILED');
}

if (status === 'SYNC_PENDING') {
setSyncStatus('SYNC PENDING');
}
});

const removeListener = window.electron.onRemoteSyncStatusChange(
Expand All @@ -34,6 +38,10 @@ export default function useSyncStatus(
if (newStatus === 'SYNC_FAILED') {
setSyncStatus('FAILED');
}

if (newStatus === 'SYNC_PENDING') {
setSyncStatus('SYNC PENDING');
}
}
);

Expand Down
3 changes: 2 additions & 1 deletion src/apps/renderer/localize/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,8 @@
"action-description": {
"syncing": "Syncing your files",
"updated": "Fully synced",
"failed": "Sync failed"
"failed": "Sync failed",
"sync-pending": "Sync pending"
},
"errors": {
"lock": "Sync locked by other device",
Expand Down
3 changes: 2 additions & 1 deletion src/apps/renderer/localize/locales/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,8 @@
"action-description": {
"syncing": "Sincronizando tus archivos",
"updated": "Sincronizado",
"failed": "Sincronización fallida"
"failed": "Sincronización fallida",
"sync-pending": "Sincronización pendiente"
},
"errors": {
"lock": "Sincronización bloqueada por otro dispositivo",
Expand Down
3 changes: 2 additions & 1 deletion src/apps/renderer/localize/locales/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,8 @@
"footer": {
"action-description": {
"syncing": "Synchronisation de vos fichiers",
"updated": "Mis à jour il y a quelques instants"
"updated": "Mis à jour il y a quelques instants",
"sync-pending": "Synchronisation en attente"
},
"errors": {
"lock": "Synchronisation bloquée par un autre dispositif"
Expand Down
16 changes: 16 additions & 0 deletions src/apps/renderer/pages/Widget/SyncAction.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { useTranslationContext } from '../../context/LocalContext';
import useVirtualDriveStatus from '../../hooks/VirtualDriveStatus';
import useSyncStatus from '../../hooks/useSyncStatus';
import useUsage from '../../hooks/useUsage';
import { WarningCircle } from 'phosphor-react';

export default function SyncAction(props: { syncStatus: SyncStatus }) {
const { translate } = useTranslationContext();
Expand Down Expand Up @@ -74,6 +75,21 @@ export default function SyncAction(props: { syncStatus: SyncStatus }) {
</span>
</>
)}
{isOnLine && props.syncStatus === 'SYNC PENDING' && (
<>
{/* UP TO DATE */}
<div className="relative z-0 flex w-5 items-center justify-center text-primary before:absolute before:-z-1 before:h-3 before:w-3 before:bg-white">
<WarningCircle
className="shrink-0"
size={22}
weight="fill"
/>
</div>
<span className="truncate">
{translate('widget.footer.action-description.sync-pending')}
</span>
</>
)}
</>
)
) : (
Expand Down
34 changes: 34 additions & 0 deletions src/apps/shared/types/PlaceholderStates.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
export enum SyncState {
/* status that occurs when an error occurs while reading the status*/
Undefined = -1,
NotInSync = 0,
InSync = 1,
}

export enum PinState {
/* The pin state is derived from the state of the parent folder.
* For example new remote files start out in this state, following the state of their parent folder.
* This state is used purely for resetting pin states to their derived value.
* The effective state for an item will never be "Inherited". */
Inherited = 0,

/* The file shall be available and up to date locally. Also known as "pinned".
* Pinned dehydrated files shall be hydrated as soon as possible. */
AlwaysLocal = 1,

/* File shall be a dehydrated placeholder, filled on demand.
* Also known as "unpinned". Unpinned hydrated files shall be dehydrated as soon as possible.
* If a unpinned file becomes hydrated
* (such as due to an implicit hydration where the user requested access to the file's data)
* Its pin state changes to Unspecified. */
OnlineOnly = 2,

/* The user hasn't made a decision.
* The client or platform may hydrate or dehydrate as they see fit.
* New remote files in unspecified directories start unspecified, and dehydrated (which is an arbitrary decision).*/
Unspecified = 3,

/* The file will never be synced to the cloud.
* Useful for ignored files to indicate to the OS the file will never besynced */
Excluded = 4,
}
15 changes: 14 additions & 1 deletion src/apps/sync-engine/BindingManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,18 @@ import { executeControllerWithFallback } from './callbacks-controllers/middlewar
import { DependencyContainer } from './dependency-injection/DependencyContainer';
import { ipcRendererSyncEngine } from './ipcRendererSyncEngine';
import { ProcessIssue } from '../shared/types';
import { ipcRenderer } from 'electron';

export type CallbackDownload = (
success: boolean,
filePath: string
) => Promise<{ finished: boolean; progress: number }>;

export type FileAddedCallback = (
acknowledge: boolean,
id: string
) => Promise<boolean>;

export class BindingsManager {
private static readonly PROVIDER_NAME = 'Internxt';
private progressBuffer = 0;
Expand Down Expand Up @@ -55,6 +62,7 @@ export class BindingsManager {
Logger.error(error);
callback(false);
});
ipcRenderer.send('CHECK_SYNC');
},
notifyDeleteCompletionCallback: () => {
Logger.info('Deletion completed');
Expand All @@ -73,13 +81,15 @@ export class BindingsManager {
),
});
fn(absolutePath, contentsId, callback);
ipcRenderer.send('CHECK_SYNC');
},
notifyFileAddedCallback: (
absolutePath: string,
callback: (acknowledge: boolean, id: string) => boolean
callback: FileAddedCallback
) => {
Logger.debug('Path received from callback', absolutePath);
controllers.addFile.execute(absolutePath, callback);
ipcRenderer.send('CHECK_SYNC');
},
fetchDataCallback: async (
contentsId: FilePlaceholderId,
Expand Down Expand Up @@ -140,6 +150,7 @@ export class BindingsManager {
});

fs.unlinkSync(path);
ipcRenderer.send('CHECK_SYNC');
} catch (error) {
Logger.error(error);
callback(false, '');
Expand All @@ -160,6 +171,7 @@ export class BindingsManager {
process: 'SYNC',
kind: 'LOCAL',
});
ipcRenderer.send('CHECK_SYNC');
} catch (error) {
Logger.error(error);
callback(false);
Expand Down Expand Up @@ -291,6 +303,7 @@ export class BindingsManager {
(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) {
Logger.error('[SYNC ENGINE] Polling', error);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import { PathTypeChecker } from '../../../shared/fs/PathTypeChecker ';
import { CallbackController } from './CallbackController';
import { FolderNotFoundError } from '../../../../context/virtual-drive/folders/domain/errors/FolderNotFoundError';
import { Folder } from '../../../../context/virtual-drive/folders/domain/Folder';

type CreationCallback = (acknowledge: boolean, id: string) => void;
import { ipcRenderer } from 'electron';
import { FileAddedCallback } from '../../BindingManager';

export class AddController extends CallbackController {
// Gets called when:
Expand All @@ -31,14 +31,21 @@ export class AddController extends CallbackController {

private createFile = async (
posixRelativePath: string,
callback: (acknowledge: boolean, id: string) => void,
callback: FileAddedCallback,
attempts = 3
) => {
try {
const contentsId = await this.fileCreationOrchestrator.run(
posixRelativePath
);
callback(true, createFilePlaceholderId(contentsId));
const confirmCreation = await callback(
true,
createFilePlaceholderId(contentsId)
);
if (confirmCreation) {
Logger.info('File created', posixRelativePath);
}
ipcRenderer.send('CHECK_SYNC');
} catch (error: unknown) {
Logger.error('Error when adding a file: ' + posixRelativePath, error);
if (error instanceof FolderNotFoundError) {
Expand All @@ -57,12 +64,19 @@ export class AddController extends CallbackController {

private createFolder = async (
offlineFolder: OfflineFolder,
callback: (acknowledge: boolean, id: string) => void,
callback: FileAddedCallback,
attempts = 3
) => {
try {
await this.folderCreator.run(offlineFolder);
callback(true, createFolderPlaceholderId(offlineFolder.uuid));
const creationConfirm = await callback(
true,
createFolderPlaceholderId(offlineFolder.uuid)
);
if (creationConfirm) {
Logger.info('creationConfirm', creationConfirm);
}
ipcRenderer.send('CHECK_SYNC');
} catch (error: unknown) {
Logger.error('Error creating folder', error);
if (attempts > 0) {
Expand Down Expand Up @@ -128,7 +142,7 @@ export class AddController extends CallbackController {

async execute(
absolutePath: string,
callback: CreationCallback
callback: FileAddedCallback
): Promise<void> {
const win32RelativePath =
this.absolutePathToRelativeConverter.run(absolutePath);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { FileFolderContainerDetector } from '../../../../context/virtual-drive/f
import { FileSyncronizer } from '../../../../context/virtual-drive/files/application/FileSyncronizer';
import { FilePlaceholderConverter } from '../../../../context/virtual-drive/files/application/FIlePlaceholderConverter';
import { FileSyncStatusUpdater } from '../../../../context/virtual-drive/files/application/FileSyncStatusUpdater';
import { FileCheckerStatusInRoot } from '../../../../context/virtual-drive/files/application/FileCheckerStatusInRoot';

export interface FilesContainer {
fileFinderByContentsId: FileFinderByContentsId;
Expand All @@ -30,4 +31,5 @@ export interface FilesContainer {
filesPlaceholderUpdater: FilesPlaceholderUpdater;
filePlaceholderConverter: FilePlaceholderConverter;
fileSyncStatusUpdater: FileSyncStatusUpdater;
filesCheckerStatusInRoot: FileCheckerStatusInRoot;
}
7 changes: 5 additions & 2 deletions src/apps/sync-engine/dependency-injection/files/builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { FileSyncronizer } from '../../../../context/virtual-drive/files/applica
import { FilePlaceholderConverter } from '../../../../context/virtual-drive/files/application/FIlePlaceholderConverter';
import { FileSyncStatusUpdater } from '../../../../context/virtual-drive/files/application/FileSyncStatusUpdater';
import { FileContentsUpdater } from '../../../../context/virtual-drive/files/application/FileContentsUpdater';
import { FileCheckerStatusInRoot } from '../../../../context/virtual-drive/files/application/FileCheckerStatusInRoot';

export async function buildFilesContainer(
folderContainer: FoldersContainer,
Expand Down Expand Up @@ -144,10 +145,11 @@ export async function buildFilesContainer(
sharedContainer.absolutePathToRelativeConverter,
folderContainer.folderCreator,
folderContainer.offline.folderCreator,
fileContentsUpdater,
folderContainer.foldersFatherSyncStatusUpdater
fileContentsUpdater
);

const filesCheckerStatusInRoot = new FileCheckerStatusInRoot(localFileSystem);

const container: FilesContainer = {
fileFinderByContentsId,
fileDeleter,
Expand All @@ -165,6 +167,7 @@ export async function buildFilesContainer(
filesPlaceholderUpdater,
filePlaceholderConverter,
fileSyncStatusUpdater,
filesCheckerStatusInRoot,
};

return { container, subscribers: [] };
Expand Down
9 changes: 9 additions & 0 deletions src/apps/sync-engine/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@ async function setUp() {
icon: iconPath,
});

ipcRenderer.on('CHECK_SYNC_ENGINE_RESPONSE', async (event) => {
Logger.info('[SYNC ENGINE] Checking sync engine response');
const placeholderStatuses = await container.filesCheckerStatusInRoot.run();
const placeholderStates = placeholderStatuses;
event.sender.send('CHECK_SYNC_CHANGE_STATUS', placeholderStates);
});

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

Expand Down Expand Up @@ -72,6 +79,8 @@ async function setUp() {
);

bindings.watch();

ipcRenderer.send('CHECK_SYNC');
}

setUp()
Expand Down
Loading
Loading