From e0cc3d8fab6529d01b388acddf8605908c3d236b Mon Sep 17 00:00:00 2001 From: Daniel Gasienica Date: Tue, 13 Feb 2018 09:07:17 -0500 Subject: [PATCH] Implement attachment process version Instead of keeping track of last normalization (processing) date, we now keep track of an internal processing version that will help us understand what kind of processing has already been completed for a given attachment. This will let us retroactively upgrade existing attachments. As we add more processing steps, we can build a processing pipeline that can convert any attachment processing version into a higher one, e.g. 4 -> 5 -> 6 -> 7. --- js/modules/types/attachment.js | 54 ++++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 13 deletions(-) diff --git a/js/modules/types/attachment.js b/js/modules/types/attachment.js index b168bd2f9f..80dc12a4c8 100644 --- a/js/modules/types/attachment.js +++ b/js/modules/types/attachment.js @@ -2,6 +2,13 @@ const dataURLToBlob = require('blueimp-canvas-to-blob'); const MIME = require('./mime'); +const { autoOrientImage } = require('../auto_orient_image'); + +// Increment this everytime we change how attachments are processed. This allows us to +// retroactively update existing attachments. As we add more processing steps, we could +// design a pipeline that does this incrementally, e.g. from version 0 (unknown) -> 1, +// 1 --> 2, etc., similar to how we do database migrations: +const CURRENT_PROCESS_VERSION = 1; // // Fields // { @@ -36,14 +43,39 @@ const blobToArrayBuffer = blob => const arrayBufferToBlob = (arrayBuffer, mimeType) => new Blob([arrayBuffer], { type: mimeType }); -// Processing steps: -const withLastNormalizedDate = attachment => Object.assign( - {}, - attachment, - {lastNormalized: new Date().toISOString()}, -); +// Middleware +// type ProcessingStep = Attachment -> Promise Attachment -const autoOrientJPEGs = async (attachment) => { +// ProcessingStep -> ProcessVersion -> ProcessingStep +const setProcessVersion = (next, processVersion) => async (attachment) => { + const isAlreadyProcessed = attachment.processVersion >= processVersion; + if (isAlreadyProcessed) { + return attachment; + } + + let processedAttachment; + try { + processedAttachment = await next(attachment); + } catch (error) { + console.error('Attachment.setProcessVersion: error:', error); + processedAttachment = null; + } + + const hasSuccessfullyProcessed = processedAttachment !== null; + if (!hasSuccessfullyProcessed) { + return attachment; + } + + // TODO: Enable `...` object spread operator syntax: + return Object.assign( + {}, + processedAttachment, + { processVersion } + ); +}; + +// Processing steps +const autoOrientJPEG = async (attachment) => { if (!MIME.isJPEG(attachment.contentType)) { return attachment; } @@ -54,7 +86,6 @@ const autoOrientJPEGs = async (attachment) => { const newAttachment = Object.assign({}, attachment, { data: newDataArrayBuffer, size: newDataArrayBuffer.byteLength, - lastNormalized: new Date().toISOString(), }); // `digest` is no longer valid for auto-oriented image data, so we discard it: @@ -64,8 +95,5 @@ const autoOrientJPEGs = async (attachment) => { }; // Public API - -// Attachment -> Promise -exports.normalize = async attachment => - withLastNormalizedDate(await autoOrientJPEGs(attachment)); - +// ProcessingStep +exports.process = setProcessVersion(autoOrientJPEG, CURRENT_PROCESS_VERSION);