Skip to content

Commit

Permalink
Support restarting Halo (#4361)
Browse files Browse the repository at this point in the history
#### What type of PR is this?

/kind feature
/area core
/milestone 2.9.x

#### What this PR does / why we need it:

Support restarting Halo and enable restart endpoint by default.

Restart endpoint detail:

request uri: `/actuator/restart`
request method: `POST`

Please note that memory usage may slightly increase after restarting Halo.

#### Does this PR introduce a user-facing change?

```release-note
支持在线重启 Halo。
```
  • Loading branch information
JohnNiang committed Aug 9, 2023
1 parent b9b663e commit 1172f4a
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 17 deletions.
2 changes: 0 additions & 2 deletions application/build.gradle
Expand Up @@ -52,8 +52,6 @@ dependencies {
annotationProcessor "org.springframework.boot:spring-boot-configuration-processor"
annotationProcessor "org.springframework:spring-context-indexer"

developmentOnly 'org.springframework.boot:spring-boot-devtools'

testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
testImplementation 'io.projectreactor:reactor-test'
Expand Down
@@ -0,0 +1,77 @@
package run.halo.app.actuator;

import java.io.Closeable;
import java.io.IOException;
import java.util.Collections;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.actuate.endpoint.annotation.WriteOperation;
import org.springframework.boot.actuate.endpoint.web.annotation.WebEndpoint;
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.stereotype.Component;
import run.halo.app.Application;

@WebEndpoint(id = "restart")
@Component
@Slf4j
public class RestartEndpoint implements ApplicationListener<ApplicationStartedEvent> {

private SpringApplication application;

private String[] args;

private ConfigurableApplicationContext context;

@WriteOperation
public Object restart() {
var threadGroup = new ThreadGroup("RestartGroup");
var thread = new Thread(threadGroup, this::doRestart, "restartMain");
thread.setDaemon(false);
thread.setContextClassLoader(Application.class.getClassLoader());
thread.start();
return Collections.singletonMap("message", "Restarting");
}

private synchronized void doRestart() {
log.info("Restarting...");
if (this.context != null) {
try {
closeRecursively(this.context);
var shutdownHandlers = SpringApplication.getShutdownHandlers();
if (shutdownHandlers instanceof Runnable runnable) {
// clear closedContext in org.springframework.boot.SpringApplicationShutdownHook
runnable.run();
}
this.context = this.application.run(args);
log.info("Restarted");
} catch (Throwable t) {
log.error("Failed to restart.", t);
}
}
}

private static void closeRecursively(ApplicationContext ctx) {
while (ctx != null) {
if (ctx instanceof Closeable closeable) {
try {
closeable.close();
} catch (IOException e) {
log.error("Cannot close context: {}", ctx.getId(), e);
}
}
ctx = ctx.getParent();
}
}

@Override
public void onApplicationEvent(ApplicationStartedEvent event) {
if (this.context == null) {
this.application = event.getSpringApplication();
this.args = event.getArgs();
this.context = event.getApplicationContext();
}
}
}
2 changes: 1 addition & 1 deletion application/src/main/resources/application.yaml
Expand Up @@ -64,7 +64,7 @@ management:
endpoints:
web:
exposure:
include: ["health", "info", "startup", "globalinfo", "logfile", "shutdown"]
include: ["health", "info", "startup", "globalinfo", "logfile", "shutdown", "restart"]
endpoint:
shutdown:
enabled: true
Expand Down
8 changes: 4 additions & 4 deletions console/src/locales/en.yaml
Expand Up @@ -1003,9 +1003,9 @@ core:
description: Are you sure you want to delete the backup?
restore:
title: Restore successfully
description: After successful restore, you need to restart Halo to load the system resources normally. After clicking OK, we will automatically stop running Halo.
shutdown:
toast_success: Requested to shutdown operation
description: After successful restore, you need to restart Halo to load the system resources normally. After clicking OK, we will automatically restart Halo.
restart:
toast_success: Requested to restart
list:
phases:
pending: Pending
Expand All @@ -1018,7 +1018,7 @@ core:
tips:
first: 1. The restore process may last for a long time, please do not refresh the page during this period.
second: 2. During the restore process, although the existing data will not be cleaned up, if there is a conflict, the data will be overwritten.
third: 3. After the restore is completed, you will be prompted to stop running Halo, and you may need to run it manually after stopping.
third: 3. After the restore is completed, you need to restart Halo to load the system resources normally.
complete: Restore completed, waiting for restart...
start: Start restore
exception:
Expand Down
8 changes: 4 additions & 4 deletions console/src/locales/zh-CN.yaml
Expand Up @@ -1003,9 +1003,9 @@ core:
description: 确定要删除该备份吗?
restore:
title: 恢复成功
description: 恢复成功之后,需要重启一下 Halo 才能够正常加载系统资源,点击确定之后我们会自动停止运行 Halo
shutdown:
toast_success: 已请求停止运行
description: 恢复成功之后,需要重启一下 Halo 才能够正常加载系统资源,点击确定之后我们会自动重启 Halo
restart:
toast_success: 已请求重启
list:
phases:
pending: 准备中
Expand All @@ -1018,7 +1018,7 @@ core:
tips:
first: 1. 恢复过程可能会持续较长时间,期间请勿刷新页面。
second: 2. 在恢复的过程中,虽然已有的数据不会被清理掉,但如果有冲突的数据将被覆盖。
third: 3. 恢复完成之后会提示停止运行 Halo,停止之后可能需要手动运行
third: 3. 恢复完成之后需要重启 Halo 才能够正常加载系统资源
complete: 恢复完成,等待重启...
start: 开始恢复
exception:
Expand Down
8 changes: 4 additions & 4 deletions console/src/locales/zh-TW.yaml
Expand Up @@ -1003,9 +1003,9 @@ core:
description: 確定要刪除此備份嗎?
restore:
title: 還原成功
description: 還原成功後,需要重新啟動 Halo 才能正常載入系統資源,點擊確定後我們會自動停止運行 Halo。
shutdown:
toast_success: 已請求停止運行
description: 還原成功後,需要重新啟動 Halo 才能正常載入系統資源,點擊確定之後,我們會自動重啟 Halo。
restart:
toast_success: 已請求重啟
list:
phases:
pending: 準備中
Expand All @@ -1018,7 +1018,7 @@ core:
tips:
first: 1. 還原過程可能需要較長時間,期間請勿重新整理頁面。
second: 2. 在還原過程中,雖然已有的資料不會被清除,但若有衝突的資料將被覆蓋。
third: 3. 還原完成後會提示停止運行 Halo,停止後可能需要手動啟動
third: 3. 還原完成後需要重新啟動 Halo 才能正常載入系統資源
complete: 恢復完成,等待重啟...
start: 開始還原
exception:
Expand Down
4 changes: 2 additions & 2 deletions console/src/modules/system/backup/tabs/Restore.vue
Expand Up @@ -25,8 +25,8 @@ const onUploaded = () => {
};
async function handleShutdown() {
await axios.post(`/actuator/shutdown`);
Toast.success(t("core.backup.operations.shutdown.toast_success"));
await axios.post(`/actuator/restart`);
Toast.success(t("core.backup.operations.restart.toast_success"));
setTimeout(() => {
complete.value = true;
Expand Down

0 comments on commit 1172f4a

Please sign in to comment.