3
3
import threading
4
4
from datetime import datetime as dt
5
5
from datetime import timedelta
6
- from typing import Dict , NamedTuple , Optional , Tuple , Union
6
+ from typing import Dict , List , NamedTuple , Optional , Tuple , Union
7
7
8
8
from packaging import version
9
9
from PyQt6 import QtCore , QtDBus
19
19
from vorta .i18n import translate
20
20
from vorta .notifications import VortaNotifications
21
21
from vorta .store .models import BackupProfileModel , EventLogModel
22
- from vorta .utils import borg_compat
22
+ from vorta .utils import borg_compat , get_network_status_monitor
23
23
24
24
logger = logging .getLogger (__name__ )
25
25
@@ -59,6 +59,13 @@ def __init__(self):
59
59
self .qt_timer .setInterval (15 * 60 * 1000 )
60
60
self .qt_timer .start ()
61
61
62
+ # Network backup profiles that are waiting on the network
63
+ self .network_deferred_timer = QTimer ()
64
+ self .network_deferred_timer .timeout .connect (self .create_backup_if_net_up )
65
+ self .network_deferred_timer .setInterval (5 * 1000 ) # Short interval for the network to come up
66
+ # Don't start until its actually needed
67
+ self .network_deferred_profiles : List [str ] = []
68
+
62
69
# connect signals
63
70
self .app .backup_finished_event .connect (lambda res : self .set_timer_for_profile (res ['params' ]['profile_id' ]))
64
71
@@ -81,6 +88,27 @@ def loginSuspendNotify(self, suspend: bool):
81
88
logger .debug ("Got login suspend/resume notification" )
82
89
self .reload_all_timers ()
83
90
91
+ def create_backup_if_net_up (self ):
92
+ nm = get_network_status_monitor ()
93
+ if nm .is_network_active ():
94
+ # Cancel the timer
95
+ self .network_deferred_timer .stop ()
96
+ logger .info ("the network is active, dispatching waiting jobs" )
97
+ # create_backup will add to waiting_network if the network goes down again
98
+ # flip ahead of time here in case that happens
99
+ waiting = self .network_deferred_profiles
100
+ self .network_deferred_profiles = []
101
+ for profile_id in waiting :
102
+ self .create_backup (profile_id )
103
+ else :
104
+ logger .debug ("there are jobs waiting on the network, but it is not yet up" )
105
+
106
+ def defer_backup (self , profile_id ):
107
+ if not self .network_deferred_profiles :
108
+ # Nothing is currently waiting so start the timer
109
+ self .network_deferred_timer .start ()
110
+ self .network_deferred_profiles .append (profile_id )
111
+
84
112
def tr (self , * args , ** kwargs ):
85
113
scope = self .__class__ .__name__
86
114
return translate (scope , * args , ** kwargs )
@@ -397,6 +425,15 @@ def create_backup(self, profile_id):
397
425
logger .info ('Profile not found. Maybe deleted?' )
398
426
return
399
427
428
+ if profile .repo .is_remote_repo () and not get_network_status_monitor ().is_network_active ():
429
+ logger .info (
430
+ 'repo %s is remote and there is no active network connection, deferring backup for %s' ,
431
+ profile .repo .name ,
432
+ profile .name ,
433
+ )
434
+ self .defer_backup (profile_id )
435
+ return
436
+
400
437
# Skip if a job for this profile (repo) is already in progress
401
438
if self .app .jobs_manager .is_worker_running (site = profile .repo .id ):
402
439
logger .debug ('A job for repo %s is already active.' , profile .repo .id )
@@ -521,6 +558,12 @@ def post_backup_tasks(self, profile_id):
521
558
)
522
559
523
560
def remove_job (self , profile_id ):
561
+ if profile_id in self .network_deferred_profiles :
562
+ self .network_deferred_profiles .remove (profile_id )
563
+ # If nothing is waiting cancel the timer
564
+ if not self .network_deferred_profiles :
565
+ self .network_deferred_timer .stop ()
566
+
524
567
if profile_id in self .timers :
525
568
qtimer = self .timers [profile_id ].get ('qtt' )
526
569
if qtimer is not None :
0 commit comments