Skip to content

Commit 6cd7e22

Browse files
committed
✨ Feat: Implement periodic file cleanup and improve date handling.
- Add periodic task to scan and delete expired backup files - Introduce date parsing utility for filenames - Refactor date formatting for better reusability - Update file upload path to use configurable directory
1 parent cbfa8cf commit 6cd7e22

2 files changed

Lines changed: 64 additions & 2 deletions

File tree

fifu-server-backup/src/main/kotlin/fun/fifu/serverbackup/BackupManager.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,14 @@ object BackupManager {
4949
val cacheFileName = "ServerBackupCache"
5050
val keysFileName = "ServerBackupKeys"
5151
var configPojo: ConfigPojo
52+
val dataPatten = "yyyy-MM-dd"
5253

5354
init {
5455
ConfigCenter.makeDefaultConfig(configFileName, ConfigPojo())
5556
configPojo = ConfigCenter.readSnapshot(configFileName, ConfigPojo::class.java)
5657
doBackup = Runnable {
5758
thread(start = true) {
58-
val timeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd")
59+
val timeFormatter = DateTimeFormatter.ofPattern(dataPatten)
5960
val backupName = "./backup_${LocalDateTime.now().format(timeFormatter)}.tar.gz"
6061
createTarGzipByFolder(Paths.get(configPojo.backupServerDirPath), Paths.get(backupName))
6162
println("The compression is complete, and the file is saved in ${backupName}.")

fifu-server-backup/src/main/kotlin/fun/fifu/serverbackup/DataServer.kt

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import dev.samstevens.totp.code.DefaultCodeVerifier
1919
import dev.samstevens.totp.code.HashingAlgorithm
2020
import dev.samstevens.totp.time.SystemTimeProvider
2121
import `fun`.fifu.serverbackup.BackupManager.configPojo
22+
import `fun`.fifu.serverbackup.BackupManager.dataPatten
2223
import io.vertx.core.Vertx
2324
import io.vertx.core.http.HttpServerOptions
2425
import io.vertx.ext.web.Router
@@ -28,7 +29,11 @@ import java.io.File
2829
import java.nio.file.Paths
2930
import java.io.FileReader
3031
import java.io.FileWriter
32+
import java.time.LocalDate
33+
import java.time.format.DateTimeFormatter
34+
import java.time.temporal.ChronoUnit
3135
import java.util.concurrent.ConcurrentHashMap
36+
import java.util.regex.Pattern
3237

3338
object DataServer {
3439
private val vertx = Vertx.vertx()
@@ -46,6 +51,9 @@ object DataServer {
4651

4752
init {
4853
loadCache()
54+
vertx.setPeriodic(12 * 60 * 60 * 1000) {
55+
scanExpiredFilesAndDeleted()
56+
}
4957
}
5058

5159
private fun loadCache() {
@@ -141,7 +149,7 @@ object DataServer {
141149
println("Received file: $fileName (size: $fileSize bytes)")
142150

143151
// Move the file to a permanent location if needed
144-
vertx.fileSystem().move(uploadedFileName, Paths.get("uploads", fileName).toString()) {
152+
vertx.fileSystem().move(uploadedFileName, Paths.get(configPojo.backupServerDirPath, fileName).toString()) {
145153
if (it.succeeded()) {
146154
routingContext.response().end("File uploaded successfully")
147155
} else {
@@ -205,4 +213,57 @@ object DataServer {
205213
}
206214
routingContext.response().setStatusCode(200).end(gson.toJson(responseList))
207215
}
216+
217+
/**
218+
* Parses a date from the given filename and returns it as a LocalDate.
219+
*
220+
* This method attempts to extract a date string from the provided filename using a regular expression.
221+
* If a valid date pattern is found, it parses the date string into a `LocalDate` object using the specified date format.
222+
* If no valid date pattern is found or parsing fails, it returns null.
223+
*
224+
* @param filename The name of the file from which to extract the date.
225+
* @return A `LocalDate` object representing the parsed date, or `null` if no valid date is found.
226+
*
227+
* @see dataPatten The date pattern used for parsing.
228+
*/
229+
fun parseDateFromFilename(filename: String): LocalDate? {
230+
val dateFormatter = DateTimeFormatter.ofPattern(dataPatten)
231+
232+
val datePattern = Pattern.compile("\\d{4}-\\d{2}-\\d{2}")
233+
val matcher = datePattern.matcher(filename)
234+
235+
if (matcher.find()) {
236+
val dateString = matcher.group()
237+
return LocalDate.parse(dateString, dateFormatter)
238+
}
239+
return null
240+
}
241+
242+
/**
243+
* Scans the backup directory for expired files and deletes them.
244+
*
245+
* This method iterates through all files in the specified backup directory,
246+
* checks if each file has exceeded the configured retention period, and deletes
247+
* any files that are older than the retention period. It logs the deletion of
248+
* each expired file and prints a completion message at the end.
249+
*
250+
* @see ConfigPojo.backupServerDirPath The path to the backup directory.
251+
* @see ConfigPojo.backupKeepDay The number of days files should be retained before deletion.
252+
*/
253+
private fun scanExpiredFilesAndDeleted() {
254+
val files = File(configPojo.backupServerDirPath).listFiles()
255+
for (file in files!!) {
256+
if (file.isFile) {
257+
val fileName = file.name
258+
val date = parseDateFromFilename(fileName)
259+
val currentDate = LocalDate.now()
260+
val daysBetween = ChronoUnit.DAYS.between(date, currentDate)
261+
if (daysBetween >= configPojo.backupKeepDay) {
262+
file.delete()
263+
println("Parsed Date: $date, Deleted.")
264+
}
265+
}
266+
}
267+
println("Scan expired files, Done.")
268+
}
208269
}

0 commit comments

Comments
 (0)