⭐️ Put back preview service (#75)
* Put back the preview service * Fix imports linter
This commit is contained in:
@@ -13,6 +13,12 @@ import {
|
||||
ExecutionContext,
|
||||
} from "../../../core/platform/framework/api/crud-service";
|
||||
import gr from "../../global-resolver";
|
||||
import {
|
||||
PreviewClearMessageQueueRequest,
|
||||
PreviewMessageQueueRequest,
|
||||
} from "../../../services/previews/types";
|
||||
import { PreviewFinishedProcessor } from "./preview";
|
||||
import _ from "lodash";
|
||||
|
||||
export class FileServiceImpl {
|
||||
version: "1";
|
||||
@@ -23,6 +29,9 @@ export class FileServiceImpl {
|
||||
async init(): Promise<this> {
|
||||
try {
|
||||
await Promise.all([(this.repository = await gr.database.getRepository<File>("files", File))]);
|
||||
gr.platformServices.messageQueue.processor.addHandler(
|
||||
new PreviewFinishedProcessor(this, this.repository),
|
||||
);
|
||||
} catch (err) {
|
||||
logger.error("Error while initializing files service", err);
|
||||
}
|
||||
@@ -106,6 +115,60 @@ export class FileServiceImpl {
|
||||
if (entity.upload_data.chunks === 1 && totalUploadedSize) {
|
||||
entity.upload_data.size = totalUploadedSize;
|
||||
await this.repository.save(entity, context);
|
||||
|
||||
/** Send preview generation task */
|
||||
if (entity.upload_data.size < this.max_preview_file_size) {
|
||||
const document: PreviewMessageQueueRequest["document"] = {
|
||||
id: JSON.stringify(_.pick(entity, "id", "company_id")),
|
||||
provider: gr.platformServices.storage.getConnectorType(),
|
||||
|
||||
path: getFilePath(entity),
|
||||
encryption_algo: this.algorithm,
|
||||
encryption_key: entity.encryption_key,
|
||||
chunks: entity.upload_data.chunks,
|
||||
|
||||
filename: entity.metadata.name,
|
||||
mime: entity.metadata.mime,
|
||||
};
|
||||
const output = {
|
||||
provider: gr.platformServices.storage.getConnectorType(),
|
||||
path: `${getFilePath(entity)}/thumbnails/`,
|
||||
encryption_algo: this.algorithm,
|
||||
encryption_key: entity.encryption_key,
|
||||
pages: 10,
|
||||
};
|
||||
|
||||
entity.metadata.thumbnails_status = "waiting";
|
||||
await this.repository.save(entity, context);
|
||||
|
||||
if (!options?.ignoreThumbnails) {
|
||||
try {
|
||||
await gr.platformServices.messageQueue.publish<PreviewMessageQueueRequest>(
|
||||
"services:preview",
|
||||
{
|
||||
data: { document, output },
|
||||
},
|
||||
);
|
||||
|
||||
if (options.waitForThumbnail) {
|
||||
entity = await gr.services.files.getFile(
|
||||
{
|
||||
id: entity.id,
|
||||
company_id: context.company.id,
|
||||
},
|
||||
context,
|
||||
{ waitForThumbnail: true },
|
||||
);
|
||||
}
|
||||
} catch (err) {
|
||||
entity.metadata.thumbnails_status = "error";
|
||||
await this.repository.save(entity, context);
|
||||
|
||||
logger.warn({ err }, "Previewing - Error while sending ");
|
||||
}
|
||||
}
|
||||
}
|
||||
/** End preview generation task generation */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -227,6 +290,22 @@ export class FileServiceImpl {
|
||||
totalChunks: fileToDelete.upload_data.chunks,
|
||||
});
|
||||
|
||||
if (fileToDelete.thumbnails.length > 0) {
|
||||
await gr.platformServices.messageQueue.publish<PreviewClearMessageQueueRequest>(
|
||||
"services:preview:clear",
|
||||
{
|
||||
data: {
|
||||
document: {
|
||||
id: JSON.stringify(_.pick(fileToDelete, "id", "company_id")),
|
||||
provider: gr.platformServices.storage.getConnectorType(),
|
||||
path: `${path}/thumbnails/`,
|
||||
thumbnails_number: fileToDelete.thumbnails.length,
|
||||
},
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return new DeleteResult("files", fileToDelete, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
import { logger, TdriveContext } from "../../../core/platform/framework";
|
||||
import { PreviewMessageQueueCallback } from "../../../../src/services/previews/types";
|
||||
import Repository from "../../../../src/core/platform/services/database/services/orm/repository/repository";
|
||||
import { File } from "../entities/file";
|
||||
import { FileServiceImpl } from "./index";
|
||||
import { MessageQueueHandler } from "../../../core/platform/services/message-queue/api";
|
||||
import { ExecutionContext } from "../../../core/platform/framework/api/crud-service";
|
||||
|
||||
/**
|
||||
* Update the file metadata and upload the thumbnails in storage
|
||||
*/
|
||||
export class PreviewFinishedProcessor
|
||||
implements MessageQueueHandler<PreviewMessageQueueCallback, string>
|
||||
{
|
||||
constructor(readonly service: FileServiceImpl, private repository: Repository<File>) {}
|
||||
|
||||
async init(_context?: TdriveContext): Promise<this> {
|
||||
return this;
|
||||
}
|
||||
|
||||
readonly topics = {
|
||||
in: "services:preview:callback",
|
||||
};
|
||||
|
||||
readonly options = {
|
||||
unique: true,
|
||||
ack: true,
|
||||
};
|
||||
|
||||
name = "FilePreviewProcessor";
|
||||
|
||||
validate(message: PreviewMessageQueueCallback): boolean {
|
||||
return !!(message && message.document);
|
||||
}
|
||||
|
||||
async process(message: PreviewMessageQueueCallback, context?: ExecutionContext): Promise<string> {
|
||||
logger.info(
|
||||
`${this.name} - Updating file metadata with preview generation ${message.thumbnails.length}`,
|
||||
);
|
||||
|
||||
const pk: { company_id: string; id: string } = JSON.parse(message.document.id);
|
||||
const entity = await this.repository.findOne(pk, {}, context);
|
||||
|
||||
if (!entity) {
|
||||
logger.info(`This file ${message.document.id} does not exists anymore.`);
|
||||
return;
|
||||
}
|
||||
|
||||
entity.thumbnails = (message.thumbnails || []).map((thumb, index) => {
|
||||
return {
|
||||
index,
|
||||
id: thumb.path.split("/").pop(),
|
||||
size: thumb.size,
|
||||
type: thumb.type,
|
||||
width: thumb.width,
|
||||
height: thumb.height,
|
||||
url: `/internal/services/files/v1/companies/${entity.company_id}/files/${entity.id}/thumbnails/${index}`,
|
||||
};
|
||||
});
|
||||
|
||||
if (!entity.metadata) entity.metadata = {};
|
||||
entity.metadata.thumbnails_status = "done";
|
||||
|
||||
await this.repository.save(entity, context);
|
||||
return "done";
|
||||
}
|
||||
}
|
||||
@@ -5,4 +5,5 @@ export type UploadOptions = {
|
||||
totalChunks: number;
|
||||
chunkNumber: number;
|
||||
waitForThumbnail: boolean;
|
||||
ignoreThumbnails: boolean;
|
||||
};
|
||||
|
||||
@@ -28,6 +28,7 @@ export class FileController {
|
||||
filename: q.resumableFilename || q.filename || file?.filename || undefined,
|
||||
type: q.resumableType || q.type || file?.mimetype || undefined,
|
||||
waitForThumbnail: q.thumbnail_sync,
|
||||
ignoreThumbnails: q.ignore_thumbnails,
|
||||
};
|
||||
|
||||
const id = request.params.id;
|
||||
|
||||
Reference in New Issue
Block a user