Files
OpenFlare/internal/apps/flared/heartbeat/service.go
T
ryan 2f60329886 后端与全仓代码质量清理(golangci 扩展集 · 测试质量 · 并发安全 · 文档同步)
代码质量全量清理,零行为变化:golangci 扩展集 13 类 linter(gosec/modernize/perfsprint/canonicalheader/usestdlibvars/wastedassign/intrange/errorlint/forcetypeassert/recvcheck/exhaustive/unparam)全量修复,测试代码质量(testifylint/thelper/usetesting)25→0,frpc 进程生命周期真 bug(进程组击杀)、全仓 go test -race 6 类数据竞争(含 1 个生产竞争)、SPDX license 头补齐 131 文件、前端测试套件 next-intl 迁移后 44 失败→全绿、过期 swagger 文档重新生成、pnpm-workspace 构建审批。

Experiments: #2-#17, #18, #20, #21, #23
Metric: total_issues 108 → 8 (-92.6%)
2026-08-16 21:24:14 +08:00

80 lines
2.5 KiB
Go

// Copyright 2026 Arctel.net
// SPDX-License-Identifier: Apache-2.0
// Package heartbeat runs the periodic flared heartbeat loop against the control plane.
package heartbeat
import (
"context"
"log/slog"
edgeheartbeat "github.com/Rain-kl/Wavelet/internal/apps/edge/heartbeat"
"github.com/Rain-kl/Wavelet/internal/apps/edge/nodeip"
"github.com/Rain-kl/Wavelet/internal/apps/flared/config"
"github.com/Rain-kl/Wavelet/internal/apps/flared/frpc"
"github.com/Rain-kl/Wavelet/internal/apps/flared/httpclient"
"github.com/Rain-kl/Wavelet/internal/apps/flared/updater"
service "github.com/Rain-kl/Wavelet/pkg/protocol"
)
// Service sends periodic heartbeat payloads and applies tunnel settings from responses.
type Service struct {
client *httpclient.Client
frpcManager *frpc.Manager
config *config.Config
updater *updater.Service
}
// New creates a heartbeat service with the given client, frpc manager, and config.
func New(client *httpclient.Client, manager *frpc.Manager, cfg *config.Config) *Service {
return &Service{
client: client,
frpcManager: manager,
config: cfg,
updater: updater.New(),
}
}
// Run starts the heartbeat loop until ctx is canceled.
func (s *Service) Run(ctx context.Context) {
edgeheartbeat.RunLoop(ctx, s.config.HeartbeatInterval.Duration(), s.doHeartbeat)
}
func (s *Service) doHeartbeat(ctx context.Context) {
slog.Debug("sending flared heartbeat")
payload := service.FlaredHeartbeatPayload{
ClientVersion: config.Version,
FrpVersion: s.frpcManager.GetVersion(ctx),
IP: nodeip.DetectWithContext(ctx),
TunnelStatus: "running",
ConnectedRelays: s.frpcManager.GetConnectedRelays(),
CurrentVersion: s.frpcManager.GetCurrentConfigVersion(),
CurrentChecksum: s.frpcManager.GetCurrentConfigChecksum(),
}
resp, err := s.client.Heartbeat(ctx, payload)
if err != nil {
slog.Error("flared heartbeat failed", "error", err)
return
}
slog.Debug("flared heartbeat succeeded")
if resp != nil && resp.TunnelSettings != nil {
edgeheartbeat.TryAutoUpdate(ctx, s.updater, tunnelSettingsToAutoUpdate(resp.TunnelSettings), "flared")
}
}
func tunnelSettingsToAutoUpdate(settings *service.RelaySettings) *edgeheartbeat.AutoUpdateSettings {
if settings == nil {
return nil
}
return &edgeheartbeat.AutoUpdateSettings{
AutoUpdate: settings.AutoUpdate,
UpdateNow: settings.UpdateNow,
UpdateRepo: settings.UpdateRepo,
UpdateChannel: settings.UpdateChannel,
UpdateTag: settings.UpdateTag,
}
}