server

package
v0.2.32 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 10, 2026 License: MIT Imports: 45 Imported by: 0

Documentation

Overview

Package server 是 Cloudpath 中心服务:chi REST + WS hub(edge 接入 / 浏览器 fan-out) + SQLite 持久化 + 内嵌 webui。

并发不变量(改代码前先读):

  1. s.mu 只保护内存态(devices/edges/browsers/限流器),**锁内绝不做磁盘 I/O**; 需要落库时在锁内收集数据、锁外调用 persistXxx。
  2. broadcast 只读 browsers 集合,慢消费者丢帧不阻塞(历史可从 REST 补)。
  3. Store 可为 nil(API-only 模式):所有落库路径必须先判空。

Index

Constants

View Source
const AppHostEdgeID = "server"

AppHostEdgeID 是 Server 侧应用实例的部署约定 edge_id:真实 Edge 的 desired 快照按 edge_id 过滤,天然不会收到它;AppHost 以该 id 上报 observed 投影。 同一个标识符也用作应用运行时的 NodeID(中心服务就是一个节点)。 生产代码不得再写裸 "server" 字面量——那正是 overview.go 曾经绕过这个常量的方式; 测试里保留字面量是有意的,用来钉住常量对外的值。

Variables

This section is empty.

Functions

func InstalledApplicationPlugins added in v0.2.3

func InstalledApplicationPlugins(pluginsDir, lockPath string) (map[string]string, error)

InstalledApplicationPlugins 返回已安装的 Application kind 插件集合(pluginID → version)。

Types

type AppHost added in v0.2.3

type AppHost struct {
	// contains filtered or unexported fields
}

AppHost 在 Server 进程内运行 Application Plugin 实例(设计归属见 docs/architecture/plugin-system.md「Application Plugin → Server Plugin Host」)。

组成(各积木均已存在,本文件只做接线):

  • pluginhost.Manager + plugincontrol.Host:进程面(与 Edge 同款:注册安装物、 拉起/监督插件进程、kind 感知地建立 ApplicationClient);
  • appruntime.Runtime:协议面(Initialize→Describe→ConfigureInstance→ ValidateBinding→HandleEvents 流 + 效果安全边界);
  • desired 事实源:Server DB 的 plugin_desired_instances(不是 Edge 期望态、 不是 plugincontrol 本地文件态)。

实例配置约定:plugin_desired_instances.config_json 是 map[string]string(租户安全 契约),而应用配置是结构化 JSON。约定应用配置 JSON 字符串放在键 app_config 下, AppHost 解出后原样交给 appruntime.ConfigureInstance。

部署约定:Application 实例的 edge_id 使用保留伪 edge "server"——真实 Edge 不会 收到它的期望态(desired 快照按 edge_id 过滤),AppHost 以该 edge_id 上报 observed 投影,UI 上即呈现为 server 侧运行的实例。

func NewAppHost added in v0.2.3

func NewAppHost(srv *Server, cfg AppHostConfig) (*AppHost, error)

NewAppHost 构造 AppHost(不启动;调用 Start)。

func (*AppHost) Close added in v0.2.3

func (h *AppHost) Close()

Close 幂等停止(外部主动停机路径)。从未 Start 过时直接释放底层资源。

func (*AppHost) DispatchDeviceEvent added in v0.2.3

func (h *AppHost) DispatchDeviceEvent(deviceTenantID int64, deviceKey, entityID, eventType string, ts int64)

DispatchDeviceEvent 把一条设备事件路由到绑定了该实体的应用实例。 nil 接收者安全(未启用 AppHost 时 Server 直接调用)。 成功路由与无路由都留痕:实体事件是稀疏高信号面(key/hall/vib/nav), 静默丢弃会让「按了没反应」类问题无从排查(2026-09-05 D3 真板实测教训)。

func (*AppHost) DispatchDeviceObservations added in v0.2.15

func (h *AppHost) DispatchDeviceObservations(tenantID int64, deviceKey string, online bool, sets []api.EntityObservationSet)

DispatchDeviceObservations delivers real property samples to bound apps. Values/quality/sampling timestamps remain intact; offline transport is never promoted to good data. No domain event, sensor name or driver id is assumed.

func (*AppHost) InstanceBindings added in v0.2.7

func (h *AppHost) InstanceBindings(tenantID int64, instanceID string) ([]api.AppBindingView, bool)

InstanceBindings 返回实例的 Capability 绑定投影(运行态)。ok=false 表示 实例未运行或 AppHost 未启用——绑定只存在于实例运行期间。 instance id 不跨租户全局唯一,因此运行记录按 (tenant, instance) 寻址。

func (*AppHost) InstanceJobDescriptors added in v0.2.15

func (h *AppHost) InstanceJobDescriptors(tenantID int64, instanceID string) []api.AppJobView

InstanceJobDescriptors is tenant-scoped and returns a detached projection.

func (*AppHost) InstanceJobs added in v0.2.7

func (h *AppHost) InstanceJobs(tenantID int64, instanceID string) ([]string, bool)

InstanceJobs 返回实例声明的 job id 列表(运行态)。

func (*AppHost) NotifyCommandAck added in v0.2.3

func (h *AppHost) NotifyCommandAck(commandID int64, status, detail string)

NotifyCommandAck 在应用发起的命令收到最终回执时通知应用(RequestCompleted)。 nil 接收者安全;非最终态(sent)保留引用,等最终回执再消费。

func (*AppHost) Start added in v0.2.3

func (h *AppHost) Start(ctx context.Context) error

Start 启动 reconcile/分钟调度/observed 上报三个循环,阻塞至 ctx 取消。

type AppHostConfig added in v0.2.3

type AppHostConfig struct {
	Enabled    bool
	PluginsDir string
	LockPath   string
	StateDir   string // plugincontrol 进程面本地状态目录(非 desired SSOT)
}

AppHostConfig 是 Server 侧 Application Plugin Host 的配置(Config.AppHost)。

type Config

type Config struct {
	Store    *store.Store
	Token    string // 共享令牌;空 = 无鉴权(仅限本机/内网)
	Version  string
	WebUIDir string // 开发模式:从磁盘目录服务前端(优先于内嵌)
	// RetentionDays 是事件/命令保留天数,超期由 sweeper 清理。<=0 用默认 30 天。
	RetentionDays int
	// CmdRatePerMin 是单设备每分钟命令下发上限(防跑飞的 UI/脚本刷串口)。<=0 用默认 20。
	CmdRatePerMin int
	// AllowedOrigins 是 WS 握手允许的浏览器 Origin 模式(如 "console.example.com"、
	// "*.example.com:8443")。留空 = 开发策略:同源 + localhost/127.0.0.1 任意端口。
	// 公网部署必须显式配置(非浏览器客户端不带 Origin,不受影响)。
	AllowedOrigins []string
	// RequireAuth 在无用户时也强制读/写鉴权(L2 公网形态,配合服务令牌)。
	RequireAuth bool
	// LoginRatePerMin 是单 IP 每分钟登录尝试上限。<=0 用默认 5。
	LoginRatePerMin int
	// SessionDays 是服务端会话 TTL(天)。<=0 用默认 7。
	SessionDays int
	// SetupToken 是一次性首装令牌:非本机直连来源执行 /api/auth/setup 时必须携带
	// (同机反代转发的请求也算非本机直连,见 setupFromLocalClient);
	// 首次成功 setup 后进程内失效。空 = 仅允许本机直连 setup。
	SetupToken string
	// TrustedProxies 是可信反代 CIDR allowlist(已解析);nil = 不采信任何转发头。
	TrustedProxies *auth.TrustedProxies
	// PluginCatalog 是只读插件目录(可选)。nil 时默认用 Server 自己的插件控制面
	// 投影构造(真实数据源),因此插件端点永不返回内置/静态样例。
	PluginCatalog plugincatalog.Catalog
	// PluginStore 是插件控制面持久化端口(internal/server/storeport,§3 契约)。
	// nil = 未接线:插件写 API 返回 503,WS plugin_* 消息按旧协议忽略,读面为空。
	// 生产必须由 SQLite 适配器注入(见 storeport/adapter_sqlite.go)。
	PluginStore storeport.PluginStore
	// PluginStaleAfter 是 observed 投影过期阈值;<=0 用默认 2 分钟。
	PluginStaleAfter time.Duration
	// AppHost 启用 Server 侧 Application Plugin Host(进程面 + 协议面 + 调度;
	// 见 internal/server/apphost.go)。Enabled=false 时全部钩子 nil 安全跳过。
	AppHost AppHostConfig
}

Config 是服务配置。

type Server

type Server struct {
	// contains filtered or unexported fields
}

Server 持有全部运行态。

func New

func New(cfg Config) *Server

New 创建服务并从数据库水合上次已知状态(重启后面板不空白,离线标记)。

func (*Server) CloseAll

func (s *Server) CloseAll()

CloseAll 断开全部 WS 客户端(优雅停机用,避免 Shutdown 等长连接挂死)。 用 cancel 而非 close(chan):与 broadcast 的并发发送零竞态。

func (*Server) PluginControlPlaneWired

func (s *Server) PluginControlPlaneWired() bool

PluginControlPlaneWired 报告插件控制面持久化是否已接线(启动日志/健康自检用)。

func (*Server) Routes

func (s *Server) Routes() http.Handler

Routes 组装 chi 路由树。

func (*Server) RunSweeper

func (s *Server) RunSweeper(ctx context.Context)

RunSweeper 后台维护协程:命令超时标记(30s)+ 保留期清理(1h)。ctx 取消即退出。

func (*Server) SetAppHost added in v0.2.3

func (s *Server) SetAppHost(h *AppHost)

SetAppHost 注入 Application Plugin Host(main 在 -app-host 启用时调用; 事件/回执钩子经 nil 安全方法分发,未注入即跳过)。

Directories

Path Synopsis
Package storeadapter 是 Captain 在 STORE / SERVER 两条 lane 合并后的唯一接线点: 把 *store.Store 接到 internal/server/storeport.PluginStore 端口。
Package storeadapter 是 Captain 在 STORE / SERVER 两条 lane 合并后的唯一接线点: 把 *store.Store 接到 internal/server/storeport.PluginStore 端口。
Package storeport defines the persistence port used by the server-side plugin control plane.
Package storeport defines the persistence port used by the server-side plugin control plane.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL