Skip to content

Commit

Permalink
Add an attachment.sharedMediaDir config option
Browse files Browse the repository at this point in the history
This directory is used as an exchange point in a multi-container environment
  • Loading branch information
davidmz committed Feb 14, 2025
1 parent 8453505 commit 9a9034e
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 3 deletions.
16 changes: 13 additions & 3 deletions app/models/attachment.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ export function addModel(dbAdapter) {
}

static async create(filePath, fileName, user, postId = null) {
const attCfg = currentConfig().attachments;

let sanitized = SANITIZE_NONE;

if (user.preferences.sanitizeMediaMetadata) {
Expand All @@ -137,7 +139,7 @@ export function addModel(dbAdapter) {

if (mediaData.meta?.inProgress) {
// How many of user's media are currently being processed?
const limit = currentConfig().attachments.userMediaProcessingLimit;
const limit = attCfg.userMediaProcessingLimit;
const inProgressMedia = await dbAdapter.getInProgressAttachmentsNumber(user.id);

if (inProgressMedia >= limit) {
Expand Down Expand Up @@ -166,8 +168,16 @@ export function addModel(dbAdapter) {
const object = await dbAdapter.getAttachmentById(id);

if (object.meta.inProgress) {
let origPath = files['original'].path;

if (attCfg.sharedMediaDir) {
origPath = join(attCfg.sharedMediaDir, `${id}.orig`);
debug(`moving ${files['original'].path} to ${origPath} for further processing`);
await mvAsync(files['original'].path, origPath);
}

debug(`creating ATTACHMENT_PREPARE_VIDEO job for ${id}`);
await createPrepareVideoJob({ attId: id, filePath: files['original'].path });
await createPrepareVideoJob({ attId: id, filePath: origPath });
delete files['original'];
}

Expand Down Expand Up @@ -255,8 +265,8 @@ export function addModel(dbAdapter) {
* @returns {Promise<void>}
*/
async _placeFiles(files) {
debug(`placing files for ${this.id} to ${storageConfig.type}`, files);
const storageConfig = currentConfig().attachments.storage;
debug(`placing files for ${this.id} to ${storageConfig.type}`, files);
await Promise.all(
Object.entries(files).map(async ([variant, { path, ext }]) => {
if (storageConfig.type === 's3') {
Expand Down
5 changes: 5 additions & 0 deletions config/default.js
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,11 @@ config.attachments = {
url: defer((cfg) => cfg.media.url),
storage: defer((cfg) => cfg.media.storage),
path: 'attachments/', // must have trailing slash
// Temporary directory for delayed media files processing. Leave null to use default uploaded
// files location. It should not be null in multi-container mode. In that case this directory
// should be shared with other containers and the media files will be moved to this directory
// before delayed processing.
sharedMediaDir: null,
fileSizeLimitByType: {
// Limits for each file type
video: 500 * 1024 * 1024,
Expand Down
59 changes: 59 additions & 0 deletions test/integration/models/attachment.js
Original file line number Diff line number Diff line change
Expand Up @@ -727,6 +727,65 @@ describe('Attachments', () => {
});
expect(att.meta, 'to equal', { animatedImage: true, silent: true });
});

describe('The sharedMediaDir config option', () => {
withModifiedConfig(() => {
// Just reuse tmpdir
return { attachments: { sharedMediaDir: tmpdir() } };
});

it('should create a small h264 video attachment', async () => {
const att = await createAttachment(testFiles.mov, post, user);
// At first, we should have a stub file
expect(att, 'to satisfy', {
mediaType: 'video',
fileName: 'test-quicktime-video.tmp',
fileExtension: 'tmp',
mimeType: 'text/plain',
fileSize: 29,
previews: expect.it('to equal', {}),
meta: expect.it('to equal', { silent: true, inProgress: true }),
width: 1572,
height: 710,
duration: 2.9815,
});

// Now execute the job
await jobManager.fetchAndProcess();

// The video should have been processed
const att2 = await dbAdapter.getAttachmentById(att.id);
expect(att2, 'to satisfy', {
mediaType: 'video',
fileName: 'test-quicktime-video.mp4',
fileExtension: 'mp4',
mimeType: 'video/mp4',
previews: expect.it('to equal', {
video: {
'': { h: 710, w: 1572, ext: 'mp4' },
v1: { h: 480, w: 1062, ext: 'mp4' },
},
image: {
p1: { h: 233, w: 515, ext: 'webp' },
p2: { h: 425, w: 941, ext: 'webp' },
p3: { h: 710, w: 1572, ext: 'webp' },
thumbnails: { h: 175, w: 387, ext: 'webp' },
thumbnails2: { h: 350, w: 775, ext: 'webp' },
},
}),
meta: expect.it('to equal', { silent: true }),
width: 1572,
height: 710,
duration: 2.9815,
});

// All files should exist
await checkAttachmentFiles(att2);

// The stub file should have been deleted
await filesMustExist(att, false);
});
});
});

describe('Async processing limits', () => {
Expand Down
1 change: 1 addition & 0 deletions types/config.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ declare module 'config' {
url: string;
storage: MediaStorage;
path: string;
sharedMediaDir: string | null;
fileSizeLimit: number;
fileSizeLimitByType: {
image?: number;
Expand Down

0 comments on commit 9a9034e

Please sign in to comment.