- persistTask: 去掉事务,每个 Exec 原子即可 - saveAsset(profiles): 去掉事务,profile 和 units 分步保存 - CLAUDE.md: 加两条规则——不用事务除非必要;调试只加日志不改代码
106 lines
6.0 KiB
Markdown
106 lines
6.0 KiB
Markdown
# CLAUDE.md
|
||
|
||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||
|
||
## Build, Test & Restart Commands
|
||
|
||
- Build: `go build -o managerd ./cmd/managerd` 或 `pwsh -File scripts/managerd.ps1 build`
|
||
- Run: `./managerd` (uses `managerd.json` config) or `./managerd <config-path>`
|
||
- 重启服务(编译+启停+健康检查一站式):`pwsh -File scripts/managerd.ps1 restart`
|
||
- 查看服务状态:`pwsh -File scripts/managerd.ps1 status`
|
||
- Test all: `go test ./...`
|
||
- Test single package: `go test ./internal/service/...`
|
||
- Test single test: `go test ./internal/storage/... -run TestAssetsRepo_SaveTemplate`
|
||
- Verbose test: `go test ./internal/web/... -v -run TestUI_ActionDevicesBatchAction`
|
||
|
||
## Codebase Architecture
|
||
|
||
### Layered Structure (no DI framework — manual wiring in main.go)
|
||
|
||
```
|
||
cmd/managerd/main.go — Composition root: builds config, services, storage, router
|
||
internal/api/ — Thin HTTP handlers that delegate to services (chi router, no framework)
|
||
internal/web/ — Embedded HTML UI (Go html/template + layout.html pattern)
|
||
internal/service/ — Business logic (discovery, registry, tasks, config assets, preview rendering, template slots)
|
||
internal/storage/ — SQLite persistence (raw SQL via database/sql, pure-Go modernc.org/sqlite driver)
|
||
internal/config/ — JSON config file loading (managerd.json)
|
||
internal/models/ — Core domain types (Device, Task, DeviceTaskStatus, etc.)
|
||
templates/ — Local JSON template files loaded at runtime
|
||
templates/standard_templates/ — "Standard" templates (std_ prefix) imported into SQLite on startup
|
||
```
|
||
|
||
### Dependency Flow (all wired in main.go)
|
||
|
||
```
|
||
config → service (agent client, registry, discovery)
|
||
config + service → storage (opens SQLite, creates repos)
|
||
storage → service (task service, config preview, etc.)
|
||
service + storage → api + web (HTTP handlers)
|
||
chi.Router → mounts api routes + UI
|
||
```
|
||
|
||
### Device Communication
|
||
|
||
- `AgentClient` proxies HTTP requests to device-side `rk3588-agent` via the device's IP/port.
|
||
- Two timeout tiers: 3s for normal requests, 120s for long operations (config apply, media server, model uploads).
|
||
- All proxied requests carry `X-RK-Token` header from config.
|
||
- Generic passthrough: `r.Handle("/devices/{id}/v1/*", proxyAgentV1)` covers agent sub-routes.
|
||
|
||
### Config Asset Management
|
||
|
||
The system manages four asset types stored as JSON blobs in SQLite:
|
||
|
||
| Asset | Table | Key Concept |
|
||
|---|---|---|
|
||
| Templates | `templates` | Base config template with bindings/variables |
|
||
| Profiles | `profiles` | Template-specific configuration (references `primary_template_name`) |
|
||
| Overlays | `overlays` | Named config overrides that can be appended to any profile |
|
||
| Integration Services | `integration_services` | Third-party service definitions (e.g., RTMP, HTTP push) |
|
||
| Video Sources | `video_sources` | Camera/stream source definitions |
|
||
|
||
Naming convention: names starting with `std_` are read-only standard templates, imported on startup from `templates/standard_templates/`.
|
||
|
||
The config preview rendering pipeline: merge template + profile + overlays → resolve binding references (video sources, integration services) → expand slot tokens (`${slot:name.field}`) → compute SHA256 hash.
|
||
|
||
### Background Goroutines
|
||
|
||
- RegistryService: 2s tick for offline pruning, 30s tick for graph polling
|
||
- DiscoveryService: UDP broadcast listener (blocking goroutine per discovery request)
|
||
- TaskService: concurrent task execution gated by a semaphore channel
|
||
|
||
### Key Database Tables (SQLite, migrations in storage/migrate.go)
|
||
|
||
- `devices` — device registry (device_id PK, ip, port, online status, last_seen)
|
||
- `templates`, `profiles`, `overlays` — config assets
|
||
- `integration_services`, `video_sources` — third-party service and video source definitions
|
||
- `tasks` + `task_devices` — batch task execution (type, status, per-device status)
|
||
- `device_config_state` — per-device applied config state
|
||
- `audit_logs` — action audit trail (actor, action, target, details)
|
||
|
||
### Test Patterns
|
||
|
||
- Test files co-located with source: `*_test.go`
|
||
- Services constructed with nil/real dependencies (no mocking framework)
|
||
- HTTP tests use `httptest.NewRequest` + `httptest.NewRecorder`
|
||
- Storage tests use in-memory SQLite (tests seed their own data via repo methods)
|
||
- Tests assert on status codes, redirect URLs, and response body content
|
||
|
||
## Coding Rules
|
||
|
||
- **Never use `sed`** on Windows (Git Bash). It produces stray `t` characters, broken indentation, and corrupted files.
|
||
- **Use `rg` and `fd`** for searching (not `grep`/`find`). Both are installed.
|
||
- **File editing**: use the `write` tool for new/rewritten files and `edit` tool for precise changes. For complex find-and-replace, write a small temporary Go program.
|
||
- **No tabs**: use spaces for indentation in all source files.
|
||
- **No `fetch()` in templates** for page data — all API calls must go through Go server-side handlers. JS is only for UI interactivity (modals, carousels, confirm dialogs).
|
||
- **No inline `onclick` with complex quoting** — use `data-*` attributes + event delegation instead.
|
||
- **Use `pwsh`** for PowerShell commands (v7.6.1 in PATH, not `powershell.exe`).
|
||
- **重启服务**:统一用 `pwsh -File scripts/managerd.ps1 restart`,它会先编译、停旧进程、再启动新进程并做健康检查。不要手动 kill + build + start。
|
||
- **如无必要,不使用数据库事务**:SQLite 只允许一个写者,事务会阻塞所有其他写操作。单个 `Exec` 已是原子操作,绝大多数场景不需要包裹事务。仅模板重命名等必须原子完成的多步操作才用事务。
|
||
- **调试时只加日志,不改代码**:遇到 bug 先用 `fmt.Printf` 全量打印关键路径的状态和数据流,定位根因后再动手修。不要猜测、不要加 workaround(重试、超时、锁之类)。
|
||
|
||
## 测试设备
|
||
|
||
- RK3588: `orangepi@10.0.0.81` / password: `orangepi` / key: `~/.ssh/id_ed25519_rk3588`
|
||
- Agent:9100 / Media:9000 / Token:`4fe2d69fda23d0d5d04a1486d4920e68`
|
||
- 详细命令参考 [docs/test-devices.md](docs/test-devices.md)
|