From 98181bebd90407d99a267b0df22140895c1ccce3 Mon Sep 17 00:00:00 2001 From: Barry Chen Date: Tue, 17 Jul 2018 14:25:29 -0500 Subject: [PATCH 1/3] Wait to fetch image data a few times in Watchdog. (#4612) --- server/src/watchdog.js | 55 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 47 insertions(+), 8 deletions(-) diff --git a/server/src/watchdog.js b/server/src/watchdog.js index 3105f28b3e..97d4ceec80 100644 --- a/server/src/watchdog.js +++ b/server/src/watchdog.js @@ -107,14 +107,53 @@ exports.submit = function(shot) { const imageId = imageUrl.split("/").pop(); const form = new FormData(); - Shot.getRawBytesForClip( - imageId - ).then((obj) => { - if (obj === null) { - const err = new Error("Unable to fetch image for Watchdog submission."); - err.imageId = String(imageId); - throw err; - } + // When this is called the shot has been successfully saved to the database, + // but the image data is not necessarily on S3 as the save to S3 is not + // awaited. Awaiting the S3 upload will affect the responsiveness of saving a + // shot with the addon. + // + // We'll give the S3 upload a head start and try a few times to fetch the + // image data. This is called for every shot saved, so let's keep it simple + // and minimal. + + const getImageRawBytes = function() { + const MAX_ATTEMPTS = 3; + const DELAY = 1000; // milliseconds + let attemptCount = 1; + + const delay = function(waitInMs) { + return new Promise((resolve) => { + setTimeout(() => resolve(), waitInMs); + }); + }; + const getRawBytesPromise = function(timeToWait) { + return delay(timeToWait).then(() => Shot.getRawBytesForClip(imageId)); + }; + + return new Promise((resolve, reject) => { + const tryGetBytes = function() { + getRawBytesPromise(DELAY).then(obj => { + if (obj === null) { + const err = new Error("Shot image expired, blocked, or not found."); + err.imageId = String(imageId); + reject(err); + } else { + resolve(obj); + } + }).catch(e => { + if (attemptCount >= MAX_ATTEMPTS) { + reject(e); + } else { + attemptCount++; + tryGetBytes(); + } + }); + }; + tryGetBytes(); + }); + }; + + getImageRawBytes().then((obj) => { form.append("image", obj.data, { filename: imageId, contentType: obj.contentType From 9415e478bcc72650836c5976a38e90a7c79b1636 Mon Sep 17 00:00:00 2001 From: Barry Chen Date: Tue, 24 Jul 2018 16:11:48 -0500 Subject: [PATCH 2/3] move functions up in scope --- server/src/watchdog.js | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/server/src/watchdog.js b/server/src/watchdog.js index 97d4ceec80..bd632b12e3 100644 --- a/server/src/watchdog.js +++ b/server/src/watchdog.js @@ -116,20 +116,21 @@ exports.submit = function(shot) { // image data. This is called for every shot saved, so let's keep it simple // and minimal. + const delay = function(waitInMs) { + return new Promise((resolve) => { + setTimeout(() => resolve(), waitInMs); + }); + }; + + const getRawBytesPromise = function(timeToWait) { + return delay(timeToWait).then(() => Shot.getRawBytesForClip(imageId)); + }; + const getImageRawBytes = function() { const MAX_ATTEMPTS = 3; const DELAY = 1000; // milliseconds let attemptCount = 1; - const delay = function(waitInMs) { - return new Promise((resolve) => { - setTimeout(() => resolve(), waitInMs); - }); - }; - const getRawBytesPromise = function(timeToWait) { - return delay(timeToWait).then(() => Shot.getRawBytesForClip(imageId)); - }; - return new Promise((resolve, reject) => { const tryGetBytes = function() { getRawBytesPromise(DELAY).then(obj => { From 839f2ccc79a00420cae38f4d6cc395308b2ce811 Mon Sep 17 00:00:00 2001 From: Barry Chen Date: Thu, 26 Jul 2018 10:10:07 -0500 Subject: [PATCH 3/3] Replace counter with multiple calls. (#4612) --- server/src/watchdog.js | 51 ++++++++++++++++++------------------------ 1 file changed, 22 insertions(+), 29 deletions(-) diff --git a/server/src/watchdog.js b/server/src/watchdog.js index bd632b12e3..fa88778838 100644 --- a/server/src/watchdog.js +++ b/server/src/watchdog.js @@ -122,39 +122,32 @@ exports.submit = function(shot) { }); }; - const getRawBytesPromise = function(timeToWait) { - return delay(timeToWait).then(() => Shot.getRawBytesForClip(imageId)); - }; - - const getImageRawBytes = function() { - const MAX_ATTEMPTS = 3; - const DELAY = 1000; // milliseconds - let attemptCount = 1; - + const getRawBytesPromise = function(timeToWait, retry) { return new Promise((resolve, reject) => { - const tryGetBytes = function() { - getRawBytesPromise(DELAY).then(obj => { - if (obj === null) { - const err = new Error("Shot image expired, blocked, or not found."); - err.imageId = String(imageId); - reject(err); - } else { - resolve(obj); - } - }).catch(e => { - if (attemptCount >= MAX_ATTEMPTS) { - reject(e); - } else { - attemptCount++; - tryGetBytes(); - } - }); - }; - tryGetBytes(); + delay(timeToWait) + .then(() => Shot.getRawBytesForClip(imageId)) + .then(obj => { + if (obj === null) { + const err = new Error("Shot image expired, blocked, or not found."); + err.imageId = String(imageId); + reject(err); + } else { + resolve(obj); + } + }) + .catch(e => { + if (!retry) { + reject(e); + } + resolve(null); + }); }); }; - getImageRawBytes().then((obj) => { + getRawBytesPromise(1000, true) + .then(bytes => bytes || getRawBytesPromise(1000, true)) + .then(bytes => bytes || getRawBytesPromise(1000)) + .then((obj) => { form.append("image", obj.data, { filename: imageId, contentType: obj.contentType