mirror of https://github.com/halo-dev/halo
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 unionpull/1890/head
parent
f40aed9a63
commit
de28811549
|
@ -8,7 +8,10 @@ import static run.halo.app.utils.FileUtils.checkDirectoryTraversal;
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.type.TypeReference;
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.zaxxer.hikari.HikariDataSource;
|
||||||
|
import com.zaxxer.hikari.pool.HikariPool;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.NoSuchFileException;
|
import java.nio.file.NoSuchFileException;
|
||||||
|
@ -28,6 +31,10 @@ import java.util.stream.Stream;
|
||||||
import java.util.zip.ZipOutputStream;
|
import java.util.zip.ZipOutputStream;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
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.context.ApplicationEventPublisher;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.core.io.UrlResource;
|
import org.springframework.core.io.UrlResource;
|
||||||
|
@ -177,6 +184,8 @@ public class BackupServiceImpl implements BackupService {
|
||||||
|
|
||||||
private final ApplicationEventPublisher eventPublisher;
|
private final ApplicationEventPublisher eventPublisher;
|
||||||
|
|
||||||
|
private final ApplicationContext appContext;
|
||||||
|
|
||||||
public BackupServiceImpl(AttachmentService attachmentService, CategoryService categoryService,
|
public BackupServiceImpl(AttachmentService attachmentService, CategoryService categoryService,
|
||||||
CommentBlackListService commentBlackListService, JournalService journalService,
|
CommentBlackListService commentBlackListService, JournalService journalService,
|
||||||
JournalCommentService journalCommentService, LinkService linkService, LogService logService,
|
JournalCommentService journalCommentService, LinkService linkService, LogService logService,
|
||||||
|
@ -189,7 +198,7 @@ public class BackupServiceImpl implements BackupService {
|
||||||
SheetCommentService sheetCommentService, SheetMetaService sheetMetaService,
|
SheetCommentService sheetCommentService, SheetMetaService sheetMetaService,
|
||||||
TagService tagService, ThemeSettingService themeSettingService, UserService userService,
|
TagService tagService, ThemeSettingService themeSettingService, UserService userService,
|
||||||
OneTimeTokenService oneTimeTokenService, HaloProperties haloProperties,
|
OneTimeTokenService oneTimeTokenService, HaloProperties haloProperties,
|
||||||
ApplicationEventPublisher eventPublisher) {
|
ApplicationEventPublisher eventPublisher, ApplicationContext appContext) {
|
||||||
this.attachmentService = attachmentService;
|
this.attachmentService = attachmentService;
|
||||||
this.categoryService = categoryService;
|
this.categoryService = categoryService;
|
||||||
this.commentBlackListService = commentBlackListService;
|
this.commentBlackListService = commentBlackListService;
|
||||||
|
@ -216,6 +225,7 @@ public class BackupServiceImpl implements BackupService {
|
||||||
this.oneTimeTokenService = oneTimeTokenService;
|
this.oneTimeTokenService = oneTimeTokenService;
|
||||||
this.haloProperties = haloProperties;
|
this.haloProperties = haloProperties;
|
||||||
this.eventPublisher = eventPublisher;
|
this.eventPublisher = eventPublisher;
|
||||||
|
this.appContext = appContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -246,6 +256,26 @@ public class BackupServiceImpl implements BackupService {
|
||||||
}
|
}
|
||||||
Path haloZipPath = Files.createFile(haloZipFilePath);
|
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
|
// Zip halo
|
||||||
run.halo.app.utils.FileUtils
|
run.halo.app.utils.FileUtils
|
||||||
.zip(Paths.get(this.haloProperties.getWorkDir()), haloZipPath,
|
.zip(Paths.get(this.haloProperties.getWorkDir()), haloZipPath,
|
||||||
|
@ -260,6 +290,16 @@ public class BackupServiceImpl implements BackupService {
|
||||||
return false;
|
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
|
// Build backup dto
|
||||||
return buildBackupDto(BACKUP_RESOURCE_BASE_URI, haloZipPath);
|
return buildBackupDto(BACKUP_RESOURCE_BASE_URI, haloZipPath);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
|
Loading…
Reference in New Issue