Skip to content

Commit

Permalink
chore: simplify upload use case
Browse files Browse the repository at this point in the history
  • Loading branch information
JoanVicens committed Jan 29, 2024
1 parent 64b7211 commit 5e1dbe6
Show file tree
Hide file tree
Showing 10 changed files with 122 additions and 148 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { OfflineContentsAppender } from '../../../../../context/offline-drive/contents/application/OfflineContentsAppender';
import { OfflineContentsCreator } from '../../../../../context/offline-drive/contents/application/OfflineContentsCreator';
import { OfflineContentsPathCalculator } from '../../../../../context/offline-drive/contents/application/OfflineContentsPathCalculator';
import { OfflineContentsUploader } from '../../../../../context/offline-drive/contents/application/OfflineContentsUploader';
import { EnvironmentOfflineContentsManagersFactory } from '../../../../../context/offline-drive/contents/infrastructure/EnvironmentRemoteFileContentsManagersFactory';
import { NodeFSOfflineContentsRepository } from '../../../../../context/offline-drive/contents/infrastructure/NodeFSOfflineContentsRepository';
Expand Down Expand Up @@ -36,18 +35,16 @@ export async function buildOfflineContentsContainer(
repository
);

const offlineContentsPathCalculator = new OfflineContentsPathCalculator(
repository
);

const environmentOfflineContentsManagersFactory =
new EnvironmentOfflineContentsManagersFactory(environment, user.bucket);
new EnvironmentOfflineContentsManagersFactory(
environment,
user.bucket,
tracker
);

const offlineContentsUploader = new OfflineContentsUploader(
offlineContentsPathCalculator,
environmentOfflineContentsManagersFactory,
repository,
tracker,
environmentOfflineContentsManagersFactory,
eventBus
);

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,91 +1,36 @@
import { UploadProgressTracker } from '../../../shared/domain/UploadProgressTracker';
import { EventBus } from '../../../virtual-drive/shared/domain/EventBus';
import {
OfflineContentUploader,
OfflineContentsManagersFactory,
} from '../domain/OfflineContentsManagersFactory';
import { OfflineContentsManagersFactory } from '../domain/OfflineContentsManagersFactory';
import { OfflineContentsRepository } from '../domain/OfflineContentsRepository';
import Logger from 'electron-log';
import { OfflineContentsPathCalculator } from './OfflineContentsPathCalculator';
import { OfflineContentsUploadedDomainEvent } from '../domain/events/OfflineContentsUploadedDomainEvent';
import { FilePath } from '../../../virtual-drive/files/domain/FilePath';
import { OfflineFileId } from '../../files/domain/OfflineFileId';
import { OfflineContentsName } from '../domain/OfflineContentsName';

export class OfflineContentsUploader {
constructor(
private readonly offlineContentsPathCalculator: OfflineContentsPathCalculator,
private readonly contentsManagersFactory: OfflineContentsManagersFactory,
private readonly repository: OfflineContentsRepository,
private readonly progressTracker: UploadProgressTracker,
private readonly contentsManagersFactory: OfflineContentsManagersFactory,
private readonly eventBus: EventBus
) {}

private registerEvents(
path: FilePath,
size: number,
uploader: OfflineContentUploader
) {
uploader.on('start', () => {
this.progressTracker.uploadStarted(path.name(), path.extension(), size, {
elapsedTime: uploader.elapsedTime(),
});
Logger.debug('FILE_UPLOADING', {
processInfo: { elapsedTime: uploader.elapsedTime() },
});
});

uploader.on('progress', (progress: number) => {
this.progressTracker.uploadProgress(path.name(), path.extension(), size, {
elapsedTime: uploader.elapsedTime(),
progress,
});
Logger.debug('FILE_UPLOADING', {
processInfo: { elapsedTime: uploader.elapsedTime(), progress },
});
});

uploader.on('error', (error: Error) => {
this.progressTracker.uploadError(
path.name(),
path.extension(),
error.message
);
Logger.debug('FILE_UPLOAD_ERROR', {
error: error.message,
});
});

uploader.on('finish', () => {
this.progressTracker.uploadCompleted(
path.name(),
path.extension(),
size,
{
elapsedTime: uploader.elapsedTime(),
}
);
});
}

async run(name: OfflineFileId, path: FilePath): Promise<string> {
const absolutePath = await this.offlineContentsPathCalculator.run(name);

const {
contents: readable,
abortSignal,
size,
} = await this.repository.provide(absolutePath);

const uploader = this.contentsManagersFactory.uploader(size, abortSignal);
async run(name: OfflineContentsName, path: FilePath): Promise<string> {
const { contents, stream, abortSignal } = await this.repository.read(name);

this.registerEvents(path, size, uploader);
const uploader = this.contentsManagersFactory.uploader(
stream,
contents,
{
name: path.name(),
extension: path.extension(),
},
abortSignal
);

const contentsId = await uploader.upload(readable, size);
const contentsId = await uploader();

const contentsUploadedEvent = new OfflineContentsUploadedDomainEvent({
aggregateId: contentsId,
offlineContentsPath: absolutePath,
size,
offlineContentsPath: contents.absolutePath,
size: contents.size,
path: path.value,
});

Expand Down
32 changes: 9 additions & 23 deletions src/context/offline-drive/contents/domain/OfflineContents.ts
Original file line number Diff line number Diff line change
@@ -1,39 +1,26 @@
import { Readable } from 'stream';
import { AggregateRoot } from '../../../shared/domain/AggregateRoot';
import { OfflineContentsName } from './OfflineContentsName';
import { OfflineContentsSize } from './OfflineContentsSize';

export type LocalFileContentsAttributes = {
name: string;
extension: string;
size: number;
birthTime: number;
modifiedTime: number;
contents: Readable;
absolutePath: string;
};

export class OfflineContents extends AggregateRoot {
private constructor(
private readonly _name: string,
private readonly _extension: string,
private _name: OfflineContentsName,
private readonly _size: OfflineContentsSize,
private readonly _birthTime: number,
private readonly _modifiedTime: number,
public readonly stream: Readable
public readonly absolutePath: string
) {
super();
}

public get name(): string {
return this._name;
}
public get extension(): string {
return this._extension;
}

public get nameWithExtension(): string {
return this.name + (this.extension.length >= 0 ? '.' + this.extension : '');
}

public get size(): number {
return this._size.value;
}
Expand All @@ -48,24 +35,23 @@ export class OfflineContents extends AggregateRoot {

static from(attributes: LocalFileContentsAttributes): OfflineContents {
const remoteContents = new OfflineContents(
attributes.name,
attributes.extension,
new OfflineContentsName(attributes.name),
new OfflineContentsSize(attributes.size),
attributes.birthTime,
attributes.modifiedTime,
attributes.contents
attributes.absolutePath
);

return remoteContents;
}

attributes(): Omit<LocalFileContentsAttributes, 'contents'> {
attributes(): LocalFileContentsAttributes {
return {
name: this.name,
extension: this.extension,
name: this._name.value,
size: this.size,
birthTime: this.birthTime,
modifiedTime: this.modifiedTime,
absolutePath: this.absolutePath,
};
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Readable } from 'stream';
import { OfflineContents } from './OfflineContents';

type ContentsId = string;

Expand All @@ -9,17 +10,16 @@ export type OfflineContentsUploadEvents = {
error: (error: Error) => void;
};

export interface OfflineContentUploader {
upload(contents: Readable, size: number): Promise<ContentsId>;

on(
event: keyof OfflineContentsUploadEvents,
fn: OfflineContentsUploadEvents[keyof OfflineContentsUploadEvents]
): void;

elapsedTime(): number;
}
export type OfflineContentUploader = () => Promise<string>;

export interface OfflineContentsManagersFactory {
uploader(size: number, abortSignal?: AbortSignal): OfflineContentUploader;
uploader(
readable: Readable,
contents: OfflineContents,
desiredPathElements: {
name: string;
extension: string;
},
abortSignal?: AbortSignal
): OfflineContentUploader;
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import { Uuid } from '../../../shared/domain/value-objects/Uuid';

export class OfflineContentsId extends Uuid {}
export class OfflineContentsName extends Uuid {}
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import { Readable } from 'stream';
import { OfflineFile } from '../../files/domain/OfflineFile';
import { OfflineContents } from './OfflineContents';
import { OfflineContentsName } from './OfflineContentsName';

export interface OfflineContentsRepository {
writeToFile(id: OfflineFile['id'], buffer: Buffer): Promise<void>;

createEmptyFile(id: OfflineFile['id']): Promise<void>;

getAbsolutePath(id: OfflineFile['id']): Promise<string>;
getAbsolutePath(id: OfflineContentsName): Promise<string>;

provide: (path: string) => Promise<{
contents: Readable;
size: number;
read: (offlineContentsName: OfflineContentsName) => Promise<{
contents: OfflineContents;
stream: Readable;
abortSignal: AbortSignal;
}>;
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
import { UploadStrategyFunction } from '@internxt/inxt-js/build/lib/core/upload/strategy';
import { EventEmitter, Readable } from 'stream';
import { Stopwatch } from '../../../../apps/shared/types/Stopwatch';
import {
OfflineContentUploader,
OfflineContentsUploadEvents,
} from '../domain/OfflineContentsManagersFactory';
import { OfflineContentsUploadEvents } from '../domain/OfflineContentsManagersFactory';

export class EnvironmentOfflineContentsUploader
implements OfflineContentUploader
{
export class EnvironmentOfflineContentsUploader {
private eventEmitter: EventEmitter;
private stopwatch: Stopwatch;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import {
OfflineContentsManagersFactory,
} from '../domain/OfflineContentsManagersFactory';
import { EnvironmentOfflineContentsUploader } from './EnvironmentOfflineContentsUploader';
import { OfflineContents } from '../domain/OfflineContents';
import { UploadProgressTracker } from '../../../shared/domain/UploadProgressTracker';
import { Readable } from 'stream';

export class EnvironmentOfflineContentsManagersFactory
implements OfflineContentsManagersFactory
Expand All @@ -12,17 +15,57 @@ export class EnvironmentOfflineContentsManagersFactory

constructor(
private readonly environment: Environment,
private readonly bucket: string
private readonly bucket: string,
private readonly progressTracker: UploadProgressTracker
) {}

uploader(size: number, abortSignal?: AbortSignal): OfflineContentUploader {
size;
uploader(
stream: Readable,
contents: OfflineContents,
{
name,
extension,
}: {
name: string;
extension: string;
},
abortSignal?: AbortSignal
): OfflineContentUploader {
const fn =
size >
contents.size >
EnvironmentOfflineContentsManagersFactory.MULTIPART_UPLOAD_SIZE_THRESHOLD
? this.environment.uploadMultipartFile
: this.environment.upload;

return new EnvironmentOfflineContentsUploader(fn, this.bucket, abortSignal);
const uploader = new EnvironmentOfflineContentsUploader(
fn,
this.bucket,
abortSignal
);

uploader.on('start', () => {
this.progressTracker.uploadStarted(name, extension, contents.size, {
elapsedTime: uploader.elapsedTime(),
});
});

uploader.on('progress', (progress: number) => {
this.progressTracker.uploadProgress(name, extension, contents.size, {
elapsedTime: uploader.elapsedTime(),
progress,
});
});

uploader.on('error', (error: Error) => {
this.progressTracker.uploadError(name, extension, error.message);
});

uploader.on('finish', () => {
this.progressTracker.uploadCompleted(name, extension, contents.size, {
elapsedTime: uploader.elapsedTime(),
});
});

return () => uploader.upload(stream, contents.size);
}
}
Loading

0 comments on commit 5e1dbe6

Please sign in to comment.