Files
OpenFlare/internal/repository/logstore/imports_test.go
T
ryan 7d71f1e4e1 feat(log): decouple log storage from ClickHouse with switchable logstore
- New internal/repository/logstore abstraction: exported domain interfaces
  (AccessLogStore/ObservabilityStore/UserAccessLogStore/StatusStore),
  config-driven provider (Active/Build/Migrating/SetConfigReader), GORM
  implementation for PostgreSQL/SQLite (incl. hourly rollups computed in
  real time, migration listers, PG partition maintenance), and a ClickHouse
  wrapper preserving the native batch path; repository facade delegates to
  logstore; import-lint test enforces apps never import analyticsrepo.
- ClickHouse is now optional: the log DB is either the main DB (postgres
  when database.enabled, else sqlite) or clickhouse; boot validation +
  first-run seed; log_database / log_db_migration are protected keys.
- New user task 切换日志数据库 (of_log_db_switch): freeze log writes,
  drain batch writers, copy all 6 raw log tables by id (preserving IDs)
  with target-partition pre-creation for PG, flip log_database on success,
  clear the freeze flag on failure.
- Per-store retention (log_retention_days_*) with expiry cleanup folded
  into the daily system_cleanup task; legacy database_auto_cleanup_* and
  of_database_auto_cleanup decommissioned.
- goose migrations: 6 log tables in PG (2 monthly-partitioned) + SQLite,
  retention config seeds, schedule cleanup; GET
  /api/v1/admin/status/log-database endpoint; frontend retention settings,
  switch-task UI and status badge; changelog and docs updated.

docs(plan): log database decoupling implementation plan

docs(design): log database decoupling design (ClickHouse optional)
2026-08-08 19:43:01 +08:00

68 lines
2.4 KiB
Go
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.
// Copyright 2026 Arctel.net
// SPDX-License-Identifier: Apache-2.0
package logstore
import (
"os/exec"
"strings"
"testing"
)
// forbiddenImports 上层应用禁止直接触碰的底层日志实现。
var forbiddenImports = []string{
"github.com/Rain-kl/Wavelet/internal/repository/analytics",
}
// allowedAnalyticsDelegation 允许直接依赖 analyticsrepo 的委托层:
// - internal/repository:持久化门面,ListOpenFlareLatestMetricSnapshotsSince 的
// CH 快速路径仍直连 analyticsrepo(LIMIT 1 BY node_id);小时级聚合读已改走 logstore;
// - internal/repository/logstore:CH 后端实现按设计委托 analyticsrepo。
//
// 除此之外,依赖闭包内任何包都禁止引入 analyticsrepo。
var allowedAnalyticsDelegation = map[string]bool{
"github.com/Rain-kl/Wavelet/internal/repository": true,
"github.com/Rain-kl/Wavelet/internal/repository/logstore": true,
}
// allowedInfraPersistence 允许 apps 引入的 infra/persistence 子包。
var allowedInfraPersistence = []string{
"github.com/Rain-kl/Wavelet/internal/infra/persistence/batchwriter", // batchwriter 统计类型
"github.com/Rain-kl/Wavelet/internal/infra/persistence/idgen", // 雪花 ID 生成(无日志依赖)
}
func TestAppsMustNotImportLogBackendDirectly(t *testing.T) {
t.Chdir("../../..") // module root,保证 ./internal/apps/... 可解析
// -test 同时列出测试二进制依赖,覆盖仅测试文件引入的底层日志实现。
out, err := exec.Command("go", "list", "-test", "-deps", "-f", `{{.ImportPath}} {{join .Imports " "}}`, "./internal/apps/...").Output()
if err != nil {
t.Fatalf("go list: %v", err)
}
for _, line := range strings.Split(string(out), "\n") {
fields := strings.Fields(line)
if len(fields) == 0 {
continue
}
pkg := fields[0]
for _, forbidden := range forbiddenImports {
for _, imp := range fields[1:] {
if imp == forbidden && !allowedAnalyticsDelegation[pkg] {
t.Errorf("internal/apps must not import %s (via %s)", forbidden, pkg)
}
}
}
if strings.HasPrefix(pkg, "github.com/Rain-kl/Wavelet/internal/infra/persistence/") {
allowed := false
for _, a := range allowedInfraPersistence {
if pkg == a || strings.HasPrefix(pkg, a+"/") {
allowed = true
break
}
}
if !allowed {
t.Errorf("internal/apps must not import infra/persistence subpackage: %s", pkg)
}
}
}
}