temporarily stop database connection while backing up database files (#1867)

* fix backup

* limit the scope of modification to Windows system and h2 database

* Code style union

* Code style union
pull/1890/head
anshangPro 2022-04-22 10:40:10 +08:00 committed by GitHub
parent f40aed9a63
commit de28811549
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 41 additions and 1 deletions

View File

@ -8,7 +8,10 @@ import static run.halo.app.utils.FileUtils.checkDirectoryTraversal;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zaxxer.hikari.HikariDataSource;
import com.zaxxer.hikari.pool.HikariPool;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
@ -28,6 +31,10 @@ import java.util.stream.Stream;
import java.util.zip.ZipOutputStream;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.SystemUtils;
import org.apache.logging.log4j.core.util.ReflectionUtil;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
@ -177,6 +184,8 @@ public class BackupServiceImpl implements BackupService {
private final ApplicationEventPublisher eventPublisher;
private final ApplicationContext appContext;
public BackupServiceImpl(AttachmentService attachmentService, CategoryService categoryService,
CommentBlackListService commentBlackListService, JournalService journalService,
JournalCommentService journalCommentService, LinkService linkService, LogService logService,
@ -189,7 +198,7 @@ public class BackupServiceImpl implements BackupService {
SheetCommentService sheetCommentService, SheetMetaService sheetMetaService,
TagService tagService, ThemeSettingService themeSettingService, UserService userService,
OneTimeTokenService oneTimeTokenService, HaloProperties haloProperties,
ApplicationEventPublisher eventPublisher) {
ApplicationEventPublisher eventPublisher, ApplicationContext appContext) {
this.attachmentService = attachmentService;
this.categoryService = categoryService;
this.commentBlackListService = commentBlackListService;
@ -216,6 +225,7 @@ public class BackupServiceImpl implements BackupService {
this.oneTimeTokenService = oneTimeTokenService;
this.haloProperties = haloProperties;
this.eventPublisher = eventPublisher;
this.appContext = appContext;
}
@Override
@ -246,6 +256,26 @@ public class BackupServiceImpl implements BackupService {
}
Path haloZipPath = Files.createFile(haloZipFilePath);
boolean dbClosed = false;
if (options.contains("db") && SystemUtils.IS_OS_WINDOWS) {
try {
HikariDataSource dataSource = appContext.getBean(HikariDataSource.class);
if (dataSource.getDriverClassName().equals("org.h2.Driver")) {
try {
Field poolField = HikariDataSource.class.getDeclaredField(
"pool");
HikariPool pool =
(HikariPool) ReflectionUtil.getFieldValue(poolField, dataSource);
pool.shutdown();
dbClosed = true;
} catch (InterruptedException | NoSuchFieldException e) {
throw new ServiceException("Failed to close H2 database", e);
}
}
} catch (NoSuchBeanDefinitionException e) {
throw new ServiceException("Bean HikariDataSource doesn't exists");
}
}
// Zip halo
run.halo.app.utils.FileUtils
.zip(Paths.get(this.haloProperties.getWorkDir()), haloZipPath,
@ -260,6 +290,16 @@ public class BackupServiceImpl implements BackupService {
return false;
});
if (dbClosed) {
try {
Field poolField = HikariDataSource.class.getDeclaredField(
"pool");
HikariDataSource dataSource = appContext.getBean(HikariDataSource.class);
ReflectionUtil.setFieldValue(poolField, dataSource, new HikariPool(dataSource));
} catch (NoSuchFieldException e) {
throw new ServiceException("Failed to reopen H2 database", e);
}
}
// Build backup dto
return buildBackupDto(BACKUP_RESOURCE_BASE_URI, haloZipPath);
} catch (IOException e) {