Pause/Disable Backups during background tasks

Hi. I’m writing an add-on that generates audio files and uses an external Python script. Since Anki creates a new backup every 5 minutes and opens a modal window (“Creating backup”), the add-on window completely loses focus, making it impossible to cancel the queue even if I want to. And the best part is that the backup window just stays there indefinitely.

I’m curious if there’s a way to pause backups while the add-on is running.

The default is 30 minutes, not 5 minutes – Backups - Anki Manual . And you should only see a “Creating backup” message if something has caused an undue delay in the process.

Are you sure this isn’t another add-on interfering?

It doesn’t matter what time period is set or what add-ons are enabled either. I just punched 9999 in there, disabled everything and still got the same pop-up.

I don’t know if it matters that I use QueryOP:

`generate = QueryOp(
    parent=self,
    op=lambda col: generate_audio_batch(
        col,
        self.note_ids[self.tracking :],
        self.cancel_event,
        processed=self.note_processed.emit,
    ),
    success=on_success,
)`

and inside generate_audio_batch call mw.col.update_note() every time a new audio is generated.

It’s a wild guess, but I’m passing all the notes from the browser window to QueryOP. If I feed it one note at a time instead, that might fix the issue with the backup window hanging.

I had this issue with HyperTTS: Add Audio causes Anki to "Creating Backup..." when switching focus · Issue #228 · Vocab-Apps/anki-hyper-tts · GitHub

I believe it’s an Anki bug. I was planning to look into it some day.

3 Likes

I’m guessing that QueryOp and whatever triggers the backup dialog share the same thread, so when I put all 3000 notes in the queue, the latter was politely waiting while QueryOp was doing its magic.

Now when I’m doing one note at a time, “Creating backup“ pops up, waits for QueryOp to finish and disappears right after.

def _generate_audio(self):    
    note_id = self.note_ids[self.tracking]

    print(
        f"\n✓ Processing {note_id}: {self.tracking + 1} out of {len(self.note_ids)}"
    )

    generate = QueryOp(
        parent=self,
        op=lambda col: generate_audio_batch(
            col,
            self.note_ids[self.tracking],
            self.cancel_event,
            processed=self.note_processed.emit,
        ),
        success=self._generate_success,
    )

    generate.failure(self._generate_failure).run_in_background()

def _generate_next(self):
    if self.tracking < len(self.note_ids):
        self.is_running = True
        self.ui.tbl_audio_gen.selectRow(self.tracking)
        self._generate_audio()
    else:
        print("\n✓ We're done. No notes to process!")
        self.is_finished = True
        self.is_running = False

def _generate_success(self, return_code: int) -> None:
    if return_code == 0:
        print("\n✓ Audio generation successful.")
        self._generate_next()
    elif return_code is None:
        print("\n⚠ Skipping: Note contains missing or invalid fields.")
        self._generate_next()
    else:
        self.is_finished = False
        self.is_running = False
        self._toggle_ui_busy(False)
        print("\n✖ Background task terminated unexpectedly.")

def _generate_failure(self, result: Exception | int):
    self.is_running = False
    self._toggle_ui_busy(False)

    if isinstance(result, Exception):
        showCritical(f"\n✖ Generation failed: {str(result)}")

def _on_cancel(self):
    print("\n✖ Terminating background operations...")
    self.ui.tabSettings.setDisabled(False)
    self.cancel_event.set()
1 Like
2 Likes