Files
sub2api/backend/ent/schema/channel_monitor_daily_rollup.go
erio ef6ec8a15a fix(channel-monitor): drop soft delete, refactor feature flag to declarative form
### 后端修复:日志表不该用软删除

channel_monitor_histories / channel_monitor_daily_rollups 都是日志/聚合表,
没有恢复需求。110 里加的 SoftDeleteMixin 会让 DELETE 自动变成 UPDATE deleted_at,
导致行和索引只增不减,徒增磁盘占用和查询成本。

改回分批物理删(参考 OpsCleanupService.deleteOldRowsByID 模板):

- ent schema 移除 SoftDeleteMixin,重新 go generate
- repo 新增 deleteChannelMonitorBatched 辅助 + 两条 prune SQL 常量
  (WITH batch AS SELECT id LIMIT 5000 → DELETE IN batch)
- DeleteHistoryBefore / DeleteRollupsBefore 改调分批 raw SQL
- 移除 ComputeAvailability / ComputeAvailabilityForMonitors / UpsertDailyRollupsFor /
  ListLatestPerModel / ListLatestForMonitorIDs / ListRecentHistoryForMonitors 等
  raw SQL 中的 deleted_at IS NULL 过滤
- UpsertDailyRollupsFor 的 ON CONFLICT 去掉 deleted_at = NULL 重置
- migration 111 DROP COLUMN deleted_at + 对应索引(110 已部署但 maintenance
  首跑在次日 02:00,此时尚无业务数据在依赖软删除)

### 前端重构:feature flag 声明式 + 复用

AppSidebar.vue 里 7 处 `...(flag ? [item] : [])` 样板代码删光,改为 NavItem 加
featureFlag?: () => boolean | undefined 字段,加一个 applyFeatureFlags 递归
过滤(含 children)。语义统一为 `!== false`(宽容策略,undefined 时默认显示,
避免 public settings 未加载完成时菜单闪烁消失 — 对应用户反馈"刷新后菜单消失
要去保存设置才回来")。

- 集中声明 4 个 flag getter:flagChannelMonitor / flagPayment /
  flagOpsMonitoring / flagAdminPayment
- 提取 buildSelfNavItems 复用用户端主菜单和管理员"我的账户"子菜单
- 未来新增开关:在统一位置加一个 flag getter + 给对应 NavItem 加字段
  (不用再动渲染逻辑)

bump 0.1.114.29
2026-04-23 17:31:15 +08:00

67 lines
2.0 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.

package schema
import (
"time"
"entgo.io/ent"
"entgo.io/ent/dialect"
"entgo.io/ent/dialect/entsql"
"entgo.io/ent/schema"
"entgo.io/ent/schema/edge"
"entgo.io/ent/schema/field"
"entgo.io/ent/schema/index"
)
// ChannelMonitorDailyRollup 按 (monitor_id, model, bucket_date) 维度聚合的渠道监控日统计。
// 每天的明细被收敛为一行(保留 status 分布 + 延迟和),用于 7d/15d/30d 窗口的可用率
// 加权计算avg_latency = sum_latency_ms / count_latencyavailability = ok_count / total_checks
// 超过保留期由每日维护任务分批物理删(不用软删除,理由同 channel_monitor_history
type ChannelMonitorDailyRollup struct {
ent.Schema
}
func (ChannelMonitorDailyRollup) Annotations() []schema.Annotation {
return []schema.Annotation{
entsql.Annotation{Table: "channel_monitor_daily_rollups"},
}
}
func (ChannelMonitorDailyRollup) Fields() []ent.Field {
return []ent.Field{
field.Int64("monitor_id"),
field.String("model").
NotEmpty().
MaxLen(200),
field.Time("bucket_date").
SchemaType(map[string]string{dialect.Postgres: "date"}),
field.Int("total_checks").Default(0),
field.Int("ok_count").Default(0),
field.Int("operational_count").Default(0),
field.Int("degraded_count").Default(0),
field.Int("failed_count").Default(0),
field.Int("error_count").Default(0),
field.Int64("sum_latency_ms").Default(0),
field.Int("count_latency").Default(0),
field.Int64("sum_ping_latency_ms").Default(0),
field.Int("count_ping_latency").Default(0),
field.Time("computed_at").Default(time.Now).UpdateDefault(time.Now),
}
}
func (ChannelMonitorDailyRollup) Edges() []ent.Edge {
return []ent.Edge{
edge.From("monitor", ChannelMonitor.Type).
Ref("daily_rollups").
Field("monitor_id").
Unique().
Required(),
}
}
func (ChannelMonitorDailyRollup) Indexes() []ent.Index {
return []ent.Index{
index.Fields("monitor_id", "model", "bucket_date").Unique(),
index.Fields("bucket_date"),
}
}