safesight-control/CLAUDE.md
tian 84b8b1c65a fix: remove transactions causing SQLITE_BUSY, add coding rules
- persistTask: 去掉事务,每个 Exec 原子即可
- saveAsset(profiles): 去掉事务,profile 和 units 分步保存
- CLAUDE.md: 加两条规则——不用事务除非必要;调试只加日志不改代码
2026-05-12 16:43:44 +08:00

106 lines
6.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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)