mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-12 18:26:36 +08:00
refactor(backend): rename OpenFlare directory to lowercase openflare
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
// Copyright 2026 Arctel.net
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package heartbeat handles periodic heartbeat and update checks.
|
||||
package heartbeat
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
"strings"
|
||||
|
||||
edgeupdater "Wavelet/openflare/share/edge/updater"
|
||||
)
|
||||
|
||||
// AutoUpdateSettings defines the settings for automatic edge updates.
|
||||
type AutoUpdateSettings struct {
|
||||
AutoUpdate bool
|
||||
UpdateNow bool
|
||||
UpdateRepo string
|
||||
UpdateChannel string
|
||||
UpdateTag string
|
||||
}
|
||||
|
||||
// TryAutoUpdate attempts to check and apply auto updates for the edge service.
|
||||
func TryAutoUpdate(ctx context.Context, updater *edgeupdater.Service, settings *AutoUpdateSettings, logLabel string) {
|
||||
if settings == nil || updater == nil {
|
||||
return
|
||||
}
|
||||
force := settings.UpdateNow
|
||||
shouldCheck := settings.AutoUpdate || force
|
||||
if !shouldCheck || strings.TrimSpace(settings.UpdateRepo) == "" {
|
||||
return
|
||||
}
|
||||
channel := "stable"
|
||||
if force && strings.TrimSpace(settings.UpdateChannel) != "" {
|
||||
channel = settings.UpdateChannel
|
||||
}
|
||||
slog.Info("checking for "+logLabel+" updates", "repo", settings.UpdateRepo, "channel", channel, "force", force)
|
||||
err := updater.CheckAndUpdate(ctx, settings.UpdateRepo, edgeupdater.UpdateOptions{
|
||||
Channel: channel,
|
||||
TagName: settings.UpdateTag,
|
||||
Force: force,
|
||||
})
|
||||
if err != nil {
|
||||
slog.Error(logLabel+" update check failed", "error", err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// Copyright 2026 Arctel.net
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package heartbeat
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
)
|
||||
|
||||
// RunLoop invokes fn immediately, then on each interval tick until ctx is cancelled.
|
||||
func RunLoop(ctx context.Context, interval time.Duration, fn func(context.Context)) {
|
||||
fn(ctx)
|
||||
|
||||
ticker := time.NewTicker(interval)
|
||||
defer ticker.Stop()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case <-ticker.C:
|
||||
fn(ctx)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
// Copyright 2026 Arctel.net
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package heartbeat
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestRunLoopImmediateAndTicker(t *testing.T) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
var calls atomic.Int32
|
||||
interval := 20 * time.Millisecond
|
||||
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
RunLoop(ctx, interval, func(context.Context) {
|
||||
calls.Add(1)
|
||||
})
|
||||
close(done)
|
||||
}()
|
||||
|
||||
time.Sleep(5 * time.Millisecond)
|
||||
if got := calls.Load(); got != 1 {
|
||||
t.Fatalf("expected 1 immediate call, got %d", got)
|
||||
}
|
||||
|
||||
time.Sleep(35 * time.Millisecond)
|
||||
if got := calls.Load(); got < 2 {
|
||||
t.Fatalf("expected at least 2 calls after ticker, got %d", got)
|
||||
}
|
||||
|
||||
cancel()
|
||||
select {
|
||||
case <-done:
|
||||
case <-time.After(time.Second):
|
||||
t.Fatal("RunLoop did not exit after context cancellation")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user