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.
This commit is contained in:
Daniel Gasienica 2018-02-13 09:07:17 -05:00
parent ad9083d0fd
commit e0cc3d8fab
1 changed files with 41 additions and 13 deletions

View File

@ -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<Attachment>
exports.normalize = async attachment =>
withLastNormalizedDate(await autoOrientJPEGs(attachment));
// ProcessingStep
exports.process = setProcessVersion(autoOrientJPEG, CURRENT_PROCESS_VERSION);