mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-04 15:06:37 +08:00
[新增] 实现 Agent WebSocket 连接升级功能,支持状态上报和配置广播
This commit is contained in:
@@ -18,6 +18,7 @@ import {
|
||||
getNodeStatusVariant,
|
||||
getOpenrestyStatusLabel,
|
||||
getOpenrestyStatusVariant,
|
||||
isWSConnectedLastSeen,
|
||||
} from '@/features/nodes/utils';
|
||||
import { formatDateTime, formatRelativeTime } from '@/lib/utils/date';
|
||||
import {
|
||||
@@ -133,7 +134,9 @@ function NodeHealthRow({ node }: { node: DashboardNodeHealth }) {
|
||||
<p>当前版本:{node.current_version || '未应用'}</p>
|
||||
<p>
|
||||
最近心跳:
|
||||
{node.last_seen_at
|
||||
{isWSConnectedLastSeen(node.last_seen_at)
|
||||
? ' WS 已连接'
|
||||
: node.last_seen_at
|
||||
? ` ${formatRelativeTime(node.last_seen_at)} · ${formatDateTime(node.last_seen_at)}`
|
||||
: ' 暂无'}
|
||||
</p>
|
||||
|
||||
@@ -34,6 +34,7 @@ import {
|
||||
getOpenrestyStatusLabel,
|
||||
getOpenrestyStatusVariant,
|
||||
isMeaningfulTime,
|
||||
isWSConnectedLastSeen,
|
||||
} from '@/features/nodes/utils';
|
||||
|
||||
const nodesQueryKey = ['nodes'];
|
||||
@@ -350,7 +351,9 @@ export function NodesPage() {
|
||||
</div>
|
||||
</td>
|
||||
<td className="px-3 py-4 text-[var(--foreground-secondary)]">
|
||||
{isMeaningfulTime(node.last_seen_at)
|
||||
{isWSConnectedLastSeen(node.last_seen_at)
|
||||
? 'WS 已连接'
|
||||
: isMeaningfulTime(node.last_seen_at)
|
||||
? `${formatRelativeTime(
|
||||
node.last_seen_at,
|
||||
)} · ${formatDateTime(node.last_seen_at)}`
|
||||
|
||||
@@ -1,8 +1,18 @@
|
||||
import type { NodeItem } from '@/features/nodes/types';
|
||||
|
||||
export function isMeaningfulTime(value: string | null | undefined) {
|
||||
return Boolean(value) && !String(value).startsWith('0001-01-01');
|
||||
}
|
||||
import type { NodeItem } from '@/features/nodes/types';
|
||||
|
||||
export const WS_CONNECTED_LAST_SEEN = '__OPENFLARE_WS_CONNECTED__';
|
||||
|
||||
export function isWSConnectedLastSeen(value: string | null | undefined) {
|
||||
return value === WS_CONNECTED_LAST_SEEN;
|
||||
}
|
||||
|
||||
export function isMeaningfulTime(value: string | null | undefined) {
|
||||
return (
|
||||
Boolean(value) &&
|
||||
!isWSConnectedLastSeen(value) &&
|
||||
!String(value).startsWith('0001-01-01')
|
||||
);
|
||||
}
|
||||
|
||||
export function getNodeStatusVariant(status: NodeItem['status']) {
|
||||
if (status === 'online') {
|
||||
|
||||
@@ -87,6 +87,7 @@ const defaultSystemFields = {
|
||||
|
||||
const defaultOperationFields = {
|
||||
AgentHeartbeatInterval: '10000',
|
||||
AgentWebsocketUpgradeEnabled: true,
|
||||
NodeOfflineThreshold: '120000',
|
||||
AgentUpdateRepo: 'Rain-kl/OpenFlare',
|
||||
GeoIPProvider: 'ipinfo',
|
||||
@@ -379,6 +380,10 @@ export function SettingsPage() {
|
||||
|
||||
setOperationFields({
|
||||
AgentHeartbeatInterval: optionMap.AgentHeartbeatInterval ?? '10000',
|
||||
AgentWebsocketUpgradeEnabled: toBoolean(
|
||||
optionMap.AgentWebsocketUpgradeEnabled,
|
||||
true,
|
||||
),
|
||||
NodeOfflineThreshold: optionMap.NodeOfflineThreshold ?? '120000',
|
||||
AgentUpdateRepo: optionMap.AgentUpdateRepo ?? 'Rain-kl/OpenFlare',
|
||||
GeoIPProvider: optionMap.GeoIPProvider ?? 'ipinfo',
|
||||
@@ -1059,6 +1064,12 @@ export function SettingsPage() {
|
||||
await saveOptionEntries(
|
||||
[
|
||||
['AgentHeartbeatInterval', String(heartbeat)],
|
||||
[
|
||||
'AgentWebsocketUpgradeEnabled',
|
||||
String(
|
||||
operationFields.AgentWebsocketUpgradeEnabled,
|
||||
),
|
||||
],
|
||||
['NodeOfflineThreshold', String(offline)],
|
||||
[
|
||||
'AgentUpdateRepo',
|
||||
@@ -1115,6 +1126,17 @@ export function SettingsPage() {
|
||||
/>
|
||||
</ResourceField>
|
||||
</div>
|
||||
<ToggleField
|
||||
label="开启 WS 连接升级"
|
||||
description="开启后 Agent 会在 HTTP 心跳成功后尝试升级为 WebSocket,发布配置时可立即收到同步通知。"
|
||||
checked={operationFields.AgentWebsocketUpgradeEnabled}
|
||||
onChange={(checked) =>
|
||||
setOperationFields((previous) => ({
|
||||
...previous,
|
||||
AgentWebsocketUpgradeEnabled: checked,
|
||||
}))
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="border-t border-[var(--border-default)] pt-6">
|
||||
|
||||
Reference in New Issue
Block a user