Skip to content

Commit fdc6a2d

Browse files
authored
feat(master): implement periodic gob state backup functionality to enhance data persistence
1 parent b742fe8 commit fdc6a2d

File tree

1 file changed

+37
-5
lines changed

1 file changed

+37
-5
lines changed

internal/master.go

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ type Master struct {
8080
notifyChannel chan *InstanceEvent // 事件通知通道
8181
tcpingSem chan struct{} // TCPing并发控制
8282
startTime time.Time // 启动时间
83+
backupDone chan struct{} // 备份停止信号
8384
}
8485

8586
// Instance 实例信息
@@ -314,6 +315,7 @@ func NewMaster(parsedURL *url.URL, tlsCode string, tlsConfig *tls.Config, logger
314315
notifyChannel: make(chan *InstanceEvent, semaphoreLimit),
315316
tcpingSem: make(chan struct{}, tcpingSemLimit),
316317
startTime: time.Now(),
318+
backupDone: make(chan struct{}),
317319
}
318320
master.tunnelTCPAddr = host
319321

@@ -323,6 +325,9 @@ func NewMaster(parsedURL *url.URL, tlsCode string, tlsConfig *tls.Config, logger
323325
// 启动事件分发器
324326
go master.startEventDispatcher()
325327

328+
// 启动定期备份
329+
go master.startPeriodicBackup()
330+
326331
return master
327332
}
328333

@@ -516,6 +521,9 @@ func (m *Master) Shutdown(ctx context.Context) error {
516521

517522
wg.Wait()
518523

524+
// 关闭定期备份
525+
close(m.backupDone)
526+
519527
// 关闭事件通知通道,停止事件分发器
520528
close(m.notifyChannel)
521529

@@ -535,6 +543,11 @@ func (m *Master) Shutdown(ctx context.Context) error {
535543

536544
// saveState 保存实例状态到文件
537545
func (m *Master) saveState() error {
546+
return m.saveStateToPath(m.statePath)
547+
}
548+
549+
// saveStateToPath 保存实例状态到指定路径
550+
func (m *Master) saveStateToPath(filePath string) error {
538551
if !m.stateMu.TryLock() {
539552
return nil
540553
}
@@ -553,20 +566,20 @@ func (m *Master) saveState() error {
553566
// 如果没有实例,直接返回
554567
if len(persistentData) == 0 {
555568
// 如果状态文件存在,删除它
556-
if _, err := os.Stat(m.statePath); err == nil {
557-
return os.Remove(m.statePath)
569+
if _, err := os.Stat(filePath); err == nil {
570+
return os.Remove(filePath)
558571
}
559572
return nil
560573
}
561574

562575
// 确保目录存在
563-
if err := os.MkdirAll(filepath.Dir(m.statePath), 0755); err != nil {
576+
if err := os.MkdirAll(filepath.Dir(filePath), 0755); err != nil {
564577
m.logger.Error("Create state dir failed: %v", err)
565578
return err
566579
}
567580

568581
// 创建临时文件
569-
tempFile, err := os.CreateTemp(filepath.Dir(m.statePath), "np-*.tmp")
582+
tempFile, err := os.CreateTemp(filepath.Dir(filePath), "np-*.tmp")
570583
if err != nil {
571584
m.logger.Error("Create temp failed: %v", err)
572585
return err
@@ -597,7 +610,7 @@ func (m *Master) saveState() error {
597610
}
598611

599612
// 原子地替换文件
600-
if err := os.Rename(tempPath, m.statePath); err != nil {
613+
if err := os.Rename(tempPath, filePath); err != nil {
601614
m.logger.Error("Rename temp failed: %v", err)
602615
removeTemp()
603616
return err
@@ -606,6 +619,25 @@ func (m *Master) saveState() error {
606619
return nil
607620
}
608621

622+
// startPeriodicBackup 启动定期备份
623+
func (m *Master) startPeriodicBackup() {
624+
for {
625+
select {
626+
case <-time.After(ReloadInterval):
627+
// 固定备份文件名
628+
backupPath := fmt.Sprintf("%s.backup", m.statePath)
629+
630+
if err := m.saveStateToPath(backupPath); err != nil {
631+
m.logger.Error("Backup state failed: %v", err)
632+
} else {
633+
m.logger.Info("State backup saved: %v", backupPath)
634+
}
635+
case <-m.backupDone:
636+
return
637+
}
638+
}
639+
}
640+
609641
// loadState 从文件加载实例状态
610642
func (m *Master) loadState() {
611643
// 检查文件是否存在

0 commit comments

Comments
 (0)