-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathScheduledBackupService.java
More file actions
95 lines (84 loc) · 3.89 KB
/
ScheduledBackupService.java
File metadata and controls
95 lines (84 loc) · 3.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package com.github.backup;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import jakarta.annotation.PostConstruct;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
/**
* Service that runs scheduled backups at configured intervals.
* Enabled when backup.mode=daemon.
*/
@Service
@ConditionalOnProperty(name = "backup.mode", havingValue = "daemon")
public class ScheduledBackupService {
private static final Logger log = LoggerFactory.getLogger(ScheduledBackupService.class);
private static final int SEPARATOR_LENGTH = 80;
private final BackupService backupService;
private final List<String> scheduledUsers;
private final long backupIntervalMs;
private final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
public ScheduledBackupService(BackupService backupService,
@Value("${backup.scheduled.users:}") String scheduledUsersConfig,
@Value("${backup.scheduled.interval.ms:86400000}") long backupIntervalMs) {
this.backupService = backupService;
this.backupIntervalMs = backupIntervalMs;
// Parse comma-separated list of users/orgs
this.scheduledUsers = scheduledUsersConfig.isBlank()
? List.of()
: Arrays.stream(scheduledUsersConfig.split(","))
.map(String::trim)
.filter(s -> !s.isEmpty())
.toList();
}
@PostConstruct
public void init() {
if (scheduledUsers.isEmpty()) {
log.warn("No users/organizations configured for scheduled backups.");
log.warn("Set the 'backup.scheduled.users' property with a comma-separated list.");
log.warn("Example: backup.scheduled.users=octocat,github");
} else {
log.info("GitHub Backup Daemon Mode");
log.info("========================");
log.info("Scheduled backups enabled for: {}", String.join(", ", scheduledUsers));
log.info("Backup interval: {} hours", backupIntervalMs / 3600000.0);
log.info("First backup will run immediately, then every {} hours.", backupIntervalMs / 3600000.0);
}
}
/**
* Runs backup for all configured users/organizations.
* Executes on startup and then at the configured interval after each completion.
* Uses fixedDelay to ensure the next backup starts only after the previous one completes.
*/
@Scheduled(fixedDelayString = "${backup.scheduled.interval.ms:86400000}", initialDelay = 0)
public void runScheduledBackup() {
if (scheduledUsers.isEmpty()) {
return;
}
String timestamp = LocalDateTime.now().format(dateTimeFormatter);
log.info("");
log.info("{}", "=".repeat(SEPARATOR_LENGTH));
log.info("Starting scheduled backup at {}", timestamp);
log.info("{}", "=".repeat(SEPARATOR_LENGTH));
for (String userOrOrg : scheduledUsers) {
try {
backupService.backupUserRepositories(userOrOrg);
} catch (IOException e) {
log.error("Error backing up {}: {}", userOrOrg, e.getMessage());
}
}
timestamp = LocalDateTime.now().format(dateTimeFormatter);
log.info("");
log.info("{}", "=".repeat(SEPARATOR_LENGTH));
log.info("Scheduled backup completed at {}", timestamp);
log.info("Next backup will run {} hours after this backup completes.", backupIntervalMs / 3600000.0);
log.info("{}", "=".repeat(SEPARATOR_LENGTH));
log.info("");
}
}