From 55614c245fd2ab65a5de86c9b5c6d84a261c7e84 Mon Sep 17 00:00:00 2001 From: Scott Nonnenberg Date: Tue, 14 Nov 2017 11:46:54 -0800 Subject: [PATCH] Poll for well-formed messages.json for five minutes, fail if not (#1764) Previously we just waited 5 or 10 seconds, and if it didn't work out, then we just noted in the log. Now we check for longer, and if any conversations are still not well-formed after that long, we fail the export. --- js/backup.js | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/js/backup.js b/js/backup.js index 2a535fefeb..1a54e6ab8b 100644 --- a/js/backup.js +++ b/js/backup.js @@ -389,22 +389,36 @@ }); } - // Because apparently we sometimes create malformed JSON files. Let's double-check them. - function checkConversation(conversationId, dir) { - conversations += 1; + // When we write files to disk, those writes sometimes take a while to appear on disk, + // even if the Chrome file-writing APIs tell us that the write is complete. So, to + // ensure that the export is really complete, we repeatedly check the messages.json + // file for well-formed JSON, trying for up to five minutes. + var CHECK_MAX = 60; + function checkConversation(conversationId, dir, count) { return delay(5000).then(function() { - console.log('Verifying messages.json produced for conversation', conversationId); + console.log( + 'Verifying messages.json produced for conversation', + conversationId, + 'attempt number', + count + ); return readFileAsText(dir, 'messages.json'); }).then(function(contents) { JSON.parse(contents); }).catch(function(error) { - failedConversations += 1; console.log( 'Export of conversation', conversationId, 'may be malformed:', error && error.stack ? error.stack : error ); + + if (count >= CHECK_MAX) { + failedConversations += 1; + return; + } + + return checkConversation(conversationId, dir, count + 1); }); } @@ -489,9 +503,12 @@ cursor.continue(); } else { var promise = stream.write(']}'); + + conversations += 1; + promiseChain = promiseChain .then(promise) - .then(checkConversation.bind(null, name, dir)); + .then(checkConversation.bind(null, name, dir, 0)); return promiseChain.then(function() { console.log('done exporting conversation', name); @@ -777,6 +794,9 @@ if (failedAttachments) { throw new Error('Export failed, one or more attachments failed'); } + if (failedConversations) { + throw new Error('Export failed, one or more conversations failed'); + } return path; }, function(error) { printAttachmentStats();