Skip to content

Commit

Permalink
fix: avoid override files that has not changed
Browse files Browse the repository at this point in the history
  • Loading branch information
JoanVicens committed Mar 27, 2024
1 parent 2f3a28c commit d334e17
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 15 deletions.
1 change: 1 addition & 0 deletions src/apps/fuse/callbacks/FuseCallback.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ export abstract class FuseCallback<T> {

protected left(error: FuseError | unknown): Either<FuseError, T> {
if (error instanceof FuseError) {
Logger.error(`${this.name} ${error}`);
return left(error);
}

Expand Down
2 changes: 1 addition & 1 deletion src/apps/fuse/callbacks/RenameOrMoveCallback.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export class RenameOrMoveCallback extends NotifyFuseCallback {
virtual: VirtualDriveDependencyContainer,
offline: OfflineDriveDependencyContainer
) {
super('Rename Or Move');
super('Rename Or Move', { input: true, output: true });

this.updateFile = new RenameOrMoveFile(virtual);
this.updateFolder = new RenameOrMoveFolder(virtual);
Expand Down
42 changes: 38 additions & 4 deletions src/apps/fuse/callbacks/UploadOnRename.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { FileStatuses } from '../../../context/virtual-drive/files/domain/FileSt
import { Either, right } from '../../../context/shared/domain/Either';
import { FuseError } from './FuseErrors';
import Logger from 'electron-log';
import { File } from '../../../context/virtual-drive/files/domain/File';
import { OfflineFile } from '../../../context/offline-drive/files/domain/OfflineFile';

type Result = 'no-op' | 'success';

Expand All @@ -15,14 +17,40 @@ export class UploadOnRename {
private readonly virtual: VirtualDriveDependencyContainer
) {}

private async differs(virtual: File, offline: OfflineFile): Promise<boolean> {
if (virtual.size !== offline.size.value) {
return true;
}

try {
const filePath = this.virtual.relativePathToAbsoluteConverter.run(
virtual.contentsId
);

const areEqual =
await this.offline.offlineContentsByteByByteComparator.run(
filePath,
offline
);

Logger.info(`Contents of <${virtual.path}> did not change`);

return !areEqual;
} catch (err) {
Logger.error(err);
}

return false;
}

async run(src: string, dest: string): Promise<Either<FuseError, Result>> {
const virtualFile = await this.virtual.filesSearcher.run({
const fileToOverride = await this.virtual.filesSearcher.run({
path: dest,
status: FileStatuses.EXISTS,
});

if (!virtualFile) {
Logger.debug('[UPLOAD ON RENAME] virtual file not found', dest);
if (!fileToOverride) {
Logger.debug('[UPLOAD ON RENAME] file to override not found', dest);
return right(UploadOnRename.NO_OP);
}

Expand All @@ -35,10 +63,16 @@ export class UploadOnRename {
return right(UploadOnRename.NO_OP);
}

const differs = await this.differs(fileToOverride, offlineFile);

if (!differs) {
return right(UploadOnRename.SUCCESS);
}

await this.offline.offlineContentsUploader.run(
offlineFile.id,
offlineFile.path,
virtualFile.contentsId
fileToOverride.contentsId
);

return right(UploadOnRename.SUCCESS);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { OfflineContentsCreator } from '../../../../../context/offline-drive/con
import { OfflineContentsUploader } from '../../../../../context/offline-drive/contents/application/OfflineContentsUploader';
import { AuxiliarOfflineContentsChucksReader } from '../../../../../context/offline-drive/contents/application/auxiliar/AuxiliarOfflineContentsChucksReader';
import { AuxiliarOfflineContentsDeleter } from '../../../../../context/offline-drive/contents/application/auxiliar/AuxiliarOfflineContentsDeleter';
import { OfflineContentsByteByByteComparator } from '../../../../../context/offline-drive/contents/application/OfflineContentsByteByByteComparator';

export interface OfflineContentsDependencyContainer {
offlineContentsCreator: OfflineContentsCreator;
Expand All @@ -14,4 +15,5 @@ export interface OfflineContentsDependencyContainer {
offlineContentsCacheCleaner: OfflineContentsCacheCleaner;
auxiliarOfflineContentsChucksReader: AuxiliarOfflineContentsChucksReader;
auxiliarOfflineContentsDeleter: AuxiliarOfflineContentsDeleter;
offlineContentsByteByByteComparator: OfflineContentsByteByByteComparator;
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { DependencyInjectionInxtEnvironment } from '../../common/inxt-environmen
import { DependencyInjectionUserProvider } from '../../common/user';
import { OfflineFilesContainer } from '../OfflineFiles/OfflineFilesContainer';
import { OfflineContentsDependencyContainer } from './OfflineDriveDependencyContainer';
import { OfflineContentsByteByByteComparator } from '../../../../../context/offline-drive/contents/application/OfflineContentsByteByByteComparator';

export async function buildOfflineContentsContainer(
offlineFilesContainer: OfflineFilesContainer
Expand Down Expand Up @@ -60,6 +61,9 @@ export async function buildOfflineContentsContainer(
repository
);

const offlineContentsByteByByteComparator =
new OfflineContentsByteByByteComparator(repository);

const auxiliarOfflineContentsChucksReader =
new AuxiliarOfflineContentsChucksReader(repository);

Expand All @@ -73,6 +77,7 @@ export async function buildOfflineContentsContainer(
offlineContentsUploader,
contentsChunkReader,
offlineContentsCacheCleaner,
offlineContentsByteByByteComparator,
auxiliarOfflineContentsChucksReader,
auxiliarOfflineContentsDeleter,
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import fs, { createReadStream, unlink, watch } from 'fs';
import fs, { closeSync, createReadStream, readSync, unlink, watch } from 'fs';
import { readFile, stat as statPromises } from 'fs/promises';
import { OfflineContentsRepository } from '../domain/OfflineContentsRepository';
import { OfflineFile } from '../../files/domain/OfflineFile';
import { LocalFileContentsDirectoryProvider } from '../../../virtual-drive/shared/domain/LocalFileContentsDirectoryProvider';
import { basename, dirname, join } from 'path';
import Logger from 'electron-log';
import { Readable } from 'stream';
import { Readable, Stream } from 'stream';
import { OfflineContents } from '../domain/OfflineContents';
import { OfflineContentsName } from '../domain/OfflineContentsName';
import { OfflineFileId } from '../../files/domain/OfflineFileId';
Expand All @@ -24,7 +24,7 @@ export class NodeFSOfflineContentsRepository
return join(location, this.subfolder);
}

private async filePath(name: OfflineContentsName): Promise<string> {
async filePath(name: OfflineContentsName): Promise<string> {
const folder = await this.folderPath();

return join(folder, name.value);
Expand Down Expand Up @@ -68,10 +68,10 @@ export class NodeFSOfflineContentsRepository
}

async createEmptyFile(id: OfflineFile['id']): Promise<void> {
const file = await this.filePath(id);
const path = await this.filePath(id);

return new Promise((resolve) => {
fs.writeFile(file, '', (err) => {
fs.writeFile(path, '', (err) => {
if (err) {
Logger.error('[FSOfflineFileFileSystem] ', err);
throw new Error(`could not create empty file for id: ${id}`);
Expand All @@ -82,16 +82,16 @@ export class NodeFSOfflineContentsRepository
});
}

async getAbsolutePath(id: OfflineFile['id']): Promise<string> {
async getAbsolutePath(id: OfflineFileId): Promise<string> {
return this.filePath(id);
}

async createStream(offlineContentsName: OfflineContentsName): Promise<{
async createStream(id: OfflineContentsName): Promise<{
contents: OfflineContents;
stream: Readable;
abortSignal: AbortSignal;
}> {
const absoluteFilePath = await this.getAbsolutePath(offlineContentsName);
const absoluteFilePath = await this.getAbsolutePath(id);

const { readable, controller } =
this.createAbortableStream(absoluteFilePath);
Expand All @@ -118,7 +118,7 @@ export class NodeFSOfflineContentsRepository
});

const contents = OfflineContents.from({
name: offlineContentsName.value,
name: id.value,
size,
modifiedTime: mtimeMs,
birthTime: birthtimeMs,
Expand Down
8 changes: 7 additions & 1 deletion src/context/offline-drive/files/domain/OfflineFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export type OfflineFileAttributes = {
export class OfflineFile extends AggregateRoot {
private static readonly TEMPORAL_EXTENSION = 'tmp';
private static readonly LOCK_FILE_NAME_PREFIX = '.~lock.';
private static readonly OUTPUT_STREAM_NAME_PREFIX = '.~lock.';

private constructor(
private _id: OfflineFileId,
Expand Down Expand Up @@ -69,8 +70,9 @@ export class OfflineFile extends AggregateRoot {
isAuxiliary(): boolean {
const isLockFile = this.isLockFile();
const isTemporal = this.isTemporal();
const isOutputStream = this.isOutputStream();

return isLockFile || isTemporal;
return isLockFile || isTemporal || isOutputStream;
}

isLockFile(): boolean {
Expand All @@ -81,6 +83,10 @@ export class OfflineFile extends AggregateRoot {
return this.extension === OfflineFile.TEMPORAL_EXTENSION;
}

isOutputStream(): boolean {
return this.name.startsWith(OfflineFile.OUTPUT_STREAM_NAME_PREFIX);
}

attributes(): OfflineFileAttributes {
return {
id: this._id.value,
Expand Down

0 comments on commit d334e17

Please sign in to comment.