Skip to content

Commit af0f746

Browse files
committed
variable retry delay
mac specific variable backoff queue baSED ATTEMPT try a retry delay
1 parent 6d1f80f commit af0f746

File tree

1 file changed

+78
-70
lines changed

1 file changed

+78
-70
lines changed

src/js/tabs/onboard_logging.js

Lines changed: 78 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -477,83 +477,91 @@ onboard_logging.initialize = function (callback) {
477477
}
478478

479479
function flash_save_begin() {
480-
if (GUI.connected_to) {
481-
self.blockSize = self.BLOCK_SIZE;
482-
483-
// Begin by refreshing the occupied size in case it changed while the tab was open
484-
flash_update_summary(function () {
485-
const maxBytes = FC.DATAFLASH.usedSize;
486-
487-
let openedFile;
488-
prepare_file(function (fileWriter) {
489-
let nextAddress = 0;
490-
let totalBytesCompressed = 0;
491-
492-
show_saving_dialog();
480+
if (!GUI.connected_to) return;
481+
482+
self.blockSize = self.BLOCK_SIZE;
483+
484+
flash_update_summary(async () => {
485+
const maxBytes = FC.DATAFLASH.usedSize;
486+
let openedFile;
487+
let totalBytesCompressed = 0;
488+
show_saving_dialog();
489+
490+
const MAX_SIMPLE_RETRIES = 5;
491+
const BASE_RETRY_BACKOFF_MS = 30; // starting backoff
492+
const INTER_BLOCK_DELAY_MS = 2; // small delay between successful blocks
493+
const startTime = new Date().getTime();
494+
495+
prepare_file(async (fileWriter) => {
496+
openedFile = await FileSystem.openFile(fileWriter);
497+
let nextAddress = 0;
498+
499+
async function readNextBlock() {
500+
if (saveCancelled || nextAddress >= maxBytes) {
501+
mark_saving_dialog_done(startTime, nextAddress, totalBytesCompressed);
502+
await FileSystem.closeFile(openedFile);
503+
return;
504+
}
493505

494-
// START PATCH: minimal retry for null/missing blocks
495-
const MAX_SIMPLE_RETRIES = 5;
496506
let simpleRetryCount = 0;
497507

498-
const startTime = new Date().getTime(); // Start timestamp
499-
500-
function onChunkRead(chunkAddress, chunkDataView, bytesCompressed) {
501-
if (chunkDataView && chunkDataView.byteLength > 0) {
502-
// Reset retry counter after a good block
503-
simpleRetryCount = 0;
504-
505-
// --- ORIGINAL BLOCK WRITE LOGIC ---
506-
const blob = new Blob([chunkDataView]);
507-
FileSystem.writeChunk(openedFile, blob);
508-
509-
nextAddress += chunkDataView.byteLength;
510-
511-
if (typeof bytesCompressed === "number") {
512-
if (totalBytesCompressed == null) totalBytesCompressed = 0;
513-
totalBytesCompressed += bytesCompressed;
514-
}
515-
516-
$(".dataflash-saving progress").attr("value", (nextAddress / maxBytes) * 100);
517-
518-
if (saveCancelled || nextAddress >= maxBytes) {
519-
mark_saving_dialog_done(startTime, nextAddress, totalBytesCompressed);
520-
FileSystem.closeFile(openedFile);
521-
} else {
522-
mspHelper.dataflashRead(nextAddress, self.blockSize, onChunkRead);
523-
}
524-
// --- END ORIGINAL LOGIC ---
525-
} else if (chunkDataView && chunkDataView.byteLength === 0) {
526-
// Zero-length block → EOF
527-
mark_saving_dialog_done(startTime, nextAddress, totalBytesCompressed);
528-
FileSystem.closeFile(openedFile);
529-
} else {
530-
// Null/missing block
531-
if (simpleRetryCount < MAX_SIMPLE_RETRIES) {
532-
simpleRetryCount++;
533-
if (simpleRetryCount % 2 === 1) {
534-
console.warn(`Null/missing block at ${nextAddress}, retry ${simpleRetryCount}`);
508+
async function attemptRead() {
509+
mspHelper.dataflashRead(
510+
nextAddress,
511+
self.blockSize,
512+
async (chunkAddress, chunkDataView, bytesCompressed) => {
513+
if (chunkDataView && chunkDataView.byteLength > 0) {
514+
// Reset retry counter
515+
simpleRetryCount = 0;
516+
517+
// Write and await completion to prevent Mac buffer stalls
518+
const blob = new Blob([chunkDataView]);
519+
await FileSystem.writeChunk(openedFile, blob);
520+
521+
nextAddress += chunkDataView.byteLength;
522+
if (typeof bytesCompressed === "number") {
523+
totalBytesCompressed = (totalBytesCompressed || 0) + bytesCompressed;
524+
}
525+
526+
$(".dataflash-saving progress").attr("value", (nextAddress / maxBytes) * 100);
527+
528+
// Small delay between blocks to reduce Mac Chrome hangs
529+
setTimeout(readNextBlock, INTER_BLOCK_DELAY_MS);
530+
} else if (chunkDataView && chunkDataView.byteLength === 0) {
531+
// EOF
532+
mark_saving_dialog_done(startTime, nextAddress, totalBytesCompressed);
533+
await FileSystem.closeFile(openedFile);
534+
} else {
535+
// Null/missing block
536+
if (simpleRetryCount < MAX_SIMPLE_RETRIES) {
537+
simpleRetryCount++;
538+
const backoff = BASE_RETRY_BACKOFF_MS * simpleRetryCount;
539+
if (simpleRetryCount % 2 === 1) {
540+
console.warn(
541+
`Null/missing block at ${nextAddress}, retry ${simpleRetryCount}, backoff ${backoff}ms`,
542+
);
543+
}
544+
setTimeout(attemptRead, backoff);
545+
} else {
546+
console.error(
547+
`Skipping null block at ${nextAddress} after ${MAX_SIMPLE_RETRIES} retries`,
548+
);
549+
nextAddress += self.blockSize;
550+
readNextBlock();
551+
}
535552
}
536-
mspHelper.dataflashRead(nextAddress, self.blockSize, onChunkRead);
537-
} else {
538-
console.error(
539-
`Skipping null block at ${nextAddress} after ${MAX_SIMPLE_RETRIES} retries`,
540-
);
541-
nextAddress += self.blockSize; // Move to next block only after retries exhausted
542-
simpleRetryCount = 0;
543-
mspHelper.dataflashRead(nextAddress, self.blockSize, onChunkRead);
544-
}
545-
}
553+
},
554+
);
546555
}
547556

548-
// Fetch the initial block
549-
FileSystem.openFile(fileWriter).then((file) => {
550-
openedFile = file;
551-
mspHelper.dataflashRead(nextAddress, self.blockSize, onChunkRead);
552-
});
553-
});
557+
attemptRead();
558+
}
559+
560+
// Start reading the first block
561+
readNextBlock();
554562
});
555-
}
556-
}
563+
});
564+
} // end of flash_save_begin
557565

558566
function prepare_file(onComplete) {
559567
const prefix = "BLACKBOX_LOG";

0 commit comments

Comments
 (0)