chore(prep): shared groundwork for the parallel task batch
多 agent 并行批次的协调提交(消除全部共享文件冲突面): - 迁移 0004:id_session + ob_event 两表(T3/T4 用,任务不再写迁移) - ORM:UserSession / ObEvent;错误码:九个新码(40xxx/60006,含 meta) - 配置:四档 tiers / refresh TTL / 任务奖励注册表 / 埋点上限 / COS 直传全套 - 骨架:packages/analytics + packages/storage + events/uploads 空路由(已注册) - deps:AnalyticsServiceDep / StorageServiceDep;DailyBudgetGuard 接收 tiers - uv add cos-python-sdk-v5;import-linter/CI/Makefile 纳入两个新包
This commit is contained in:
Executable → Regular
+50
@@ -254,3 +254,53 @@ class AiCall(Base):
|
||||
Index("ix_ob_ai_call_scene_created", "scene", "created_at"),
|
||||
Index("ix_ob_ai_call_user_created", "user_id", "created_at"),
|
||||
)
|
||||
|
||||
|
||||
class UserSession(Base):
|
||||
"""refresh token 的服务端会话(架构文档 §6.2 id_session,FR-ACC-05).
|
||||
|
||||
刻意叫 UserSession 而不是 Session:避免与 SQLAlchemy 的 AsyncSession 混淆。
|
||||
refresh token 本体是 opaque 随机串(不出现在任何存储里),库里只存 sha256
|
||||
哈希 —— 泄漏数据库不等于泄漏令牌。轮换 = 旧行 revoked + 新行,同一事务。
|
||||
"""
|
||||
|
||||
__tablename__ = "id_session"
|
||||
|
||||
session_id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=False)
|
||||
user_id: Mapped[int] = mapped_column(BigInteger, nullable=False)
|
||||
refresh_token_hash: Mapped[str] = mapped_column(String(64), nullable=False)
|
||||
expire_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False)
|
||||
revoked: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
|
||||
revoked_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
|
||||
created_at: Mapped[datetime] = mapped_column(
|
||||
DateTime(timezone=True), nullable=False, server_default=func.now()
|
||||
)
|
||||
|
||||
__table_args__ = (
|
||||
UniqueConstraint("refresh_token_hash", name="uq_id_session_token_hash"),
|
||||
Index("ix_id_session_user", "user_id"),
|
||||
)
|
||||
|
||||
|
||||
class ObEvent(Base):
|
||||
"""客户端埋点事件(架构文档 §6.2 ob_event,FR-SYS-06).
|
||||
|
||||
架构原文「按月分区」—— V1 先普通表(与 ob_ai_call 同样处理),
|
||||
数据量上来后再分区,先不预支复杂度。
|
||||
"""
|
||||
|
||||
__tablename__ = "ob_event"
|
||||
|
||||
event_id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=False)
|
||||
user_id: Mapped[int] = mapped_column(BigInteger, nullable=False)
|
||||
event_name: Mapped[str] = mapped_column(String(64), nullable=False)
|
||||
props: Mapped[dict[str, Any]] = mapped_column(JSONB, nullable=False, default=dict)
|
||||
client_ts: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
|
||||
server_ts: Mapped[datetime] = mapped_column(
|
||||
DateTime(timezone=True), nullable=False, server_default=func.now()
|
||||
)
|
||||
|
||||
__table_args__ = (
|
||||
Index("ix_ob_event_name_ts", "event_name", "server_ts"),
|
||||
Index("ix_ob_event_user_ts", "user_id", "server_ts"),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user