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:
parent
ad9083d0fd
commit
e0cc3d8fab
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue