ThearchyHelios
|
9a0d87aa6e
|
合入遗留收口分支 nr8/l(问数据心跳不落库与事件日志清理、续跑重新核对身份、事件触发批量查询与去抖边界、子图编号与驳回出口等),W2-b 在此之上做多进程协调
|
2026-10-19 10:46:34 +08:00 |
|
ThearchyHelios
|
2d108d116f
|
表结构变了之后口径凑不齐参数时照实记下:以前不试算、也不记日志,一声不响地跳过。现在记一条日志写缺哪几个参数(必填、没给值也没有缺省值的入口字段)和参数本来从哪来,同时写进变化记录的 affects.probes(同一版只记一条),变化页的「影响」一块写「「x」v3:缺少参数 start、end,没有试算」;同一条变化再被探查到时这份记录不丢。变化接口给的 affects 缺的几项补上空的
|
2026-10-19 10:10:38 +08:00 |
|
ThearchyHelios
|
2e7d6103ea
|
应用库可移植到 PostgreSQL:AGENTLAB_DATABASE_URL 设成 postgresql+asyncpg://… 时整个应用库用 PostgreSQL,断点用官方的 langgraph-checkpoint-postgres(同一个库,AGENTLAB_CHECKPOINT_URL 可另给);不设时照旧是数据目录里的 SQLite,行为不变
- 配置:database_url、checkpoint_url(启动时校验写法,只认 PostgreSQL)、连接池四项;启动日志写用的是哪种库(主机、库名、用户,不写密码)
- 引擎(db/base.make_engine):SQLite 照旧 WAL、外键、忙等;PostgreSQL 用连接池、探活、会话时区 UTC,装上方言调整(db/postgres.py):建表时 String(n) 是不限长的 VARCHAR(SQLite 从不查长度,导过来的存量也可能超长)、ORDER BY 里可空列的 NULL 位置照 SQLite 补写(升序在前、降序在后,窗口函数里同样);Integer 列在 PostgreSQL 上是 BIGINT(列挂到表上时换成 with_variant,绑定参数跟着列按 BIGINT 转换);JSON 列两边都存原文(PostgreSQL 的 json,不用 JSONB:JSONB 重排对象里的键,快照的列序、表的先后读回来就变了);JSON 里的 NaN 写成 null、NUL 去掉(PostgreSQL 不收)
- 迁移按方言:已有的列和索引用 inspector 认;PostgreSQL 上补列的类型取模型里这一列的、缺省值取迁移表里的(布尔 0/1 换成 false/true),ADD COLUMN IF NOT EXISTS;去重语句里的布尔按方言写;部分唯一索引补 postgresql_where;init_db 在 PostgreSQL 上拿咨询锁(几个进程同时启动不撞)
- 应用库上的 SQLite 专用写法改成按方言编译的表达式(db/portable.py):json_extract 的十几处(口径召回、出具、对账、个人应用、幂等键、访问控制、数据源变化通知、剖析任务、待办超时)换成 json_eq / json_flag / json_text,json_type 换成 json_is_string(两种库同一套带类型的比较);能力登记的 sqlite insert 换成按会话方言的 insert_ignore;能力使用次数的 json_each 按方言分支;附件「没绑记录」的条件不靠 json 的等号;按报错文字认唯一约束的地方换成 unique_violation(按表和列认,两种库的报错都认得)
- 断点(engine/checkpoints.py):PostgreSQL 时开 psycopg 连接池、在咨询锁里 setup;runner 只认 BaseCheckpointSaver,读断点仍只走 saver 的公开接口
- 依赖:新 extra postgres(asyncpg、psycopg[binary] 3、psycopg-pool、langgraph-checkpoint-postgres 3.1.2);langgraph-checkpoint 卡在 <4.3(断点格式就在这个包里,postgres 包新版要 4.3,不动已装的 4.2.0);锁文件补上新包
- 运行收尾:记 action.unknown、安排核实做完才把运行摘掉(以前先摘掉,等「不在跑了」再读事件的一方在库慢时读不到这一条)
- 测试:AGENTLAB_TEST_DATABASE_URL 时跑在 PostgreSQL 上(每个 xdist 进程建自己的库、按事件循环分的连接池 tests/pgpool.py),不设时盖掉环境里的数据库地址照旧用 SQLite;scripts/test-postgres.sh 起临时的 postgres:16 容器跑全量;sqlite_only 标记;另开连接改库的几个竞态测试、触发器测试改成两种库都能跑(tests/appdb.py);新增 test_db_portable 守着方言调整、JSON 键序、超长字符串、大整数、NULL 排序、时区、PostgreSQL 老库迁移
|
2026-10-19 09:52:09 +08:00 |
|
ThearchyHelios
|
a1ab3247f9
|
数据事件触发(后端):待派发事件表、调度循环派发与去抖、防环、{{ event.* }} 模板变量、接口收 trigger_kind / trigger
做了什么:
- 新表 trigger_events(待派发事件)、trigger_deliveries(一个事件派给一个定时任务、等去抖),放在 db/models_triggers.py,
models.py 末尾整模块导入。事件在发生处、和那件事同一个事务里写一行:上传表格按期累积的新一期启用(table_versions 的
publish_build / publish_snapshot 切指针那一下,移除、作废、回滚不算)、正式运行成功收尾(runner._finalize 写终态的事务里
加两行调用 outbox.stage_run_finished)、探查 / 剖析新记了要处理的变化(source_changes.notify_after_job,一个任务一条)。
发生处不发起运行:事务边界、重复与重启都在派发这边说清,也为第 2 波多进程做准备(认领靠条件 UPDATE)。
- scheduler/outbox.py:调度循环每一拍(fire_due 之后)派发:pending 事件条件 UPDATE 认领成 routed,同一事务里给合条件、启用着的
事件触发任务写 delivery;窗口从最早一条的发生时刻起算 debounce_s(缺省 60 秒),过了就合成一次触发,内容取最新的那条,
fire_at 取窗口结束的时刻(同一窗口永远同一个时刻,触发记录唯一约束兜住重复派发);照 fire_once 发起正式运行,ScheduleFire
kind=event、inputs 写 {event: 事件说明, inputs: 渲染出的输入};上一次没结束记 skipped_overlap;派发太晚(超出补发宽限)
记 skipped_misfire;任务停用、改了触发条件时等着的标 dropped。AGENTLAB_SCHEDULER 关着时没有这一拍,事件留着,接口照实说。
- scheduler/triggers.py:三种事件的触发条件(table.version 可选只认新增的一期;workflow.finished 可选只认某个应用 / 某种来源;
source.changed)、核对对象(表格是按期累积的上传表格、上游工作流已发布、应用在)、说法、{{ event.* }} 变量(table、version、
period、activated_at;workflow_id、run_id、outputs.<字段>;source、counts)、示例事件(预览、立即运行用对象最近一次真实的事件)、
防环:保存时查 workflow.finished 串成的环(停用的也算,A→B→A、自己触发自己都拒,422 写出经过的工作流),运行时按 origin 里的
触发深度兜底(超过 5 层记未能发起)。
- service:fire_once / _fire_workflow 接事件(模板按事件种类校验、渲染 {{ event.* }},运行来源 origin.trigger 带种类、对象、
事件 id、深度、经过的运行和一句说法);check_template / render_inputs / variables 加可选的 event 参数,cron 任务一字不变。
- api/schedules.py:收 trigger_kind(cron 缺省)/ trigger,event 时目标只能是工作流、cron 存空串、下一次触发为空;返回带
trigger_kind、trigger、trigger_text(也是 description_text)、trigger_state(几条事件在等、去抖到何时、调度开没开);触发
历史带 event;预览按示例事件渲染;变量清单按事件种类给;新增 GET /api/schedules/trigger-options(各事件能选的对象及不能选的
原因、来源、应用,界面不自己判);立即运行按示例事件发起;触发方式建好之后不能改。Webhook 照旧可配,通知写「事件触发」那一行。
- 应用页印章的来源(apps/resolve._from_text)照实写「由事件触发:…」。
为什么:总方案 §4 已拍板接这三种事件、不接口径发布,一套定时机制(X4);派发放在调度循环里而不是发生处,事务和重复都说得清。
测试:test_schedule_events.py(三种事件各触发一次、去抖合并与窗口外另起、重叠跳过、停用 / 改条件丢弃、调度关着时事件留着、
超出宽限、触发链深度与上限、模板校验与渲染、期次写法、通知、印章)、test_schedule_events_api.py(建、核对、防环、改、预览、
变量、立即运行、触发状态、可选对象);test_schedules_api.py 的约定键集合补上新加的几项。
|
2026-10-18 15:53:08 +08:00 |
|
ThearchyHelios
|
d4e68bd1a9
|
合入 W4-d 目录前端:数据目录的「变化」视图与处理动作、数据源角标、表详情「结构与取值变化」一节、数据源的定时维护(一条目标为数据源的定时任务)、后台任务条(探查、起草、剖析按服务端排队顺序);打开 source.changed 订阅;指名数据源卡片统一用 #source-<id>
|
2026-10-16 22:30:09 +08:00 |
|
ThearchyHelios
|
77fc0efa10
|
口径召回后端(W4-a):发布新版本后反查用过旧版的答案、按参数分组在同一份数据上重算两版之差,数真变了才开 recall 待办
为什么:口径升版是被迫处置的事件(02 做法 7、拍板 L6),已交付的答案以前没人追;目录事实被驳回、表结构变了也没有地方标。
- ledger/uses.py(新):反查旧版本被谁用过——比对工件里等价已证明的问数回答(含轮次、对话主人)、W 的正式运行(定时任务、
应用各取最近 4 期)、固定了它的工作流版本发起的正式运行、固定这一版的应用、导出审计(导出人也是主人);预告、召回、
版本用量共用这一份
- ledger/recall.py(新):计划按(旧版本、新版本、input_key)去重成组,从已有召回运行重算(幂等、不建任务表);每组一次
召回运行(origin_kind=recall,探索运行),派生图经 derive.recall_graph(新旧两版取数和口径卡带前缀、召回卡里算两版之差);
不能重算照实记原因(数据部分不能复用、新版没这张卡、入口参数不齐、图里有人工节点或写入);每次发布最多 recall_limit 组,
超出的手动接着算;收尾时按渲染的旧值新值判数变没变:变了开 recall 待办(开登录按主人各一条、关登录派给任何人)、推
ledger.recall,没变在原答案上记 ledger.recalled;待办「按新版重新出具」走 issue.check_target 同一套判法、「知道了」
- 目录事实被驳回或修改(审阅、人工编辑、保存提案、批量审阅之后):冻结目录里看得到这一项的探索运行记 ledger.basis_changed,
按新目录多出错误级 SQL 检查问题的才开待办;表结构变动消费 source_changes(游标、处理时改了目录的当场交过去),标依据的
表结构已变,受影响的口径试算一次,算不出来才通知发布人
- 发布钩子在 commit_publish 提交之后排队(自动的几样和调度循环同一个开关),GET /api/workflows/{id}/recall-preview 给发布
弹窗预告;GET/POST /api/ledger/recall/{wf}/{v}[/continue] 给版本历史看批次、接着算;版本用量加问数回答、导出、召回
- ledger.recall 打开订阅(全局、个人渠道),同一渠道只推一次,消息不放数;新事件 ledger.recalled、ledger.basis_changed
登记为封存后追加的事件,可验证报告离线核对页认得;E4 每次发布召回了几组、数变了的比例
- runner 收尾时召回运行在后台收尾,启动时接着做没发完的批次
|
2026-10-16 19:52:03 +08:00 |
|
ThearchyHelios
|
238330b9c1
|
W4-d 后端:给目录前端的变化、观察、后台任务、定时维护接口补齐界面要的几样;打开 source.changed 的订阅
第 3 波的变化接口只给了 agentlab-change/1 的原样,界面要的几样(能不能做、依据什么、现在怎样)如果让前端自己判,就违背
「界面层不放逻辑」。这一提交由服务端给出,界面只照写:
- 变化列表、单条、处理的回答里每条另带 category(结构 / 取值)、basis_text(依据的口径,照观察时记下的写整表、窗口、块采样、
按存储顺序的前 N 行)、actions(现在能做哪几个处理动作,做不了的写原因:剖析没开、表结构里没有了、影响面里没有目录项)、
job(处理时建的任务,界面能点进进度)、影响面里每个目录项现在的状态(清理过、改过的照实)。召回拉的 list_changes 不带这些。
- 列表能按 category 筛(和 kind 一起给时取交集,一种都对不上就是空的,不是不筛),能按 status=handled 看处理过的(最近测到的
在前:处理过的不再按要不要先处理排)。
- GET /api/datasources/upkeep:数据源列表一次取齐各源要处理的变化条数(卡片角标)和指向它的维护定时(频率、开没开、下一次)。
- GET /{id}/observations:表详情「结构与取值变化」一节的最近几次观察,各带口径;码值的占比、按日行数的合计由服务端算;现在
被遮罩的列(观察时还没遮的)整组不给,遮罩在读的那一刻再核。
- GET /{id}/background-jobs:这个源进行中和排队的探查、起草、剖析,按同源队的先后排好(05 (g):排队顺序取服务端的,界面
不自己排),各带 waiting_for。
- GET /{id}/maintenance:维护定时换成定时任务页同一个形状(改频率、开关照样带 version 走 PATCH),最近一次触发带 inputs
(建了哪些任务、哪几步没执行和原因),另说调度开没开、这个源要不要维护(上传表格、记录表不要)。
- notify:source.changed 打开订阅(只推全局渠道,按源汇总不归哪个人),链接落到目录页的「变化」标签页。
test_notify_events 里 W4-d 那一行加上;test_source_changes 里原先假设订阅没开的那句改成「没有渠道订阅时推不出去」。
data/source_changes.py(W4-a 的文件)只在末尾加了 available_actions、counts_by_source、list_handled 和 HANDLED;
data/catalog_profile_observe.py 末尾加了 key_text、recent。新测试 tests/test_source_upkeep.py。
|
2026-10-16 19:31:21 +08:00 |
|
ThearchyHelios
|
ed72ee68d6
|
W3-a 关联覆盖率下降、清理目录跨表、扩容器集成测试到对象索引和取值观察
- 剖析核对关联关系时,覆盖率从够有确证的线(95%)掉到线以下的记一条 coverage_drop(取值变化,warning):剖析本身照旧
按规则降回推断(人工确认的只补上新的覆盖率),这里只把「覆盖率下降」留进变化记录。人点的剖析也记(变化记录全站一份)。
关系的发现里多带 previous_coverage。
- 处理动作「清理目录」逐表清:这张表上说到被删的列的项,加上别的表指向它的关联关系(表删了时尤其如此);记这张表的
目录版本,别的表也动了的另记 catalog_versions。
- 剖析任务的逐表进度多一类 observe(取值观察的四类合成一组),前端「取值观察 N/M」用它。
- 定时维护补一条测试:AGENTLAB_SCHEDULER 关着时调度循环不起,到点的维护不触发、不建任务。
- scripts/dialect-it.sh / dialect_it.py 扩到第 2 波的对象索引字典查询(走字典查询不退回 Inspector、类型、表注释、行数
估算、Oracle 小写名的 quote)和这一波的取值观察(经剖析引擎只观察:行数、小表码值整表、大表 PG / Oracle 块采样、MySQL
前 N 行、最新业务日期排除无效日期,max_date_sql 直接跑)。夹具的订单表加了表注释。本机跑了一次四种库的容器
(postgres:16、mysql:8.4、mariadb:11、gvenzl/oracle-free:23-slim):121 项全过、0 项不通过,跑完容器已删、镜像留着。
验证:后端全量 14046 通过(11 跳过、8 预期失败)。
|
2026-10-16 17:28:07 +08:00 |
|
ThearchyHelios
|
f5c94cf12d
|
W3-a 变化记录的接口与处理、定时维护(next-round 03 B3、B4)
变化没有统一的记录:进不了审阅,发不了通知,口径账本的召回也没有可以订阅的接口;目录只能手动探查、手动剖析。现在:
- api/source_changes.py(骨架已在 datasources 通配之前登记,搭建者可用,访问密钥不放):GET /api/datasources/{id}/changes
(缺省开着的和知道了的,按「使用次数权重 × 严重程度」排,带各级别计数)、GET /changes/{change_id}、POST
/changes/{change_id}/resolve。处理动作落到目录已有的写入接口:清理目录里说到被删的列的项(整份写、乐观锁)、加入码值
(apply_patch 配 _merge_codes,含义待填写,依据写变化编号)、重新起草这张表(模型用不了时只按表结构起草)、重新剖析、
知道了、误报(必须写理由);每个动作写 resolution,动了目录的记目录版本,建了任务的记任务编号。
- data/source_changes.py 给召回:list_changes(按 seq 游标拉)、affecting(按源和表反查)、resolve、triggers_recall(只认
结构类、处理时改了目录的、触及有效记录条件的新码值)。
- 通知 source.changed 的发送函数 notify/service.notify_source_changed:只推还要人看的「要处理」级变化,按源汇总,消息里
只有源名、各级别条数和链接(D9);探查、剖析任务结束时有新的要处理变化就调。这一行的订阅范围第 4 波有了界面才打开,
现在推不出去(照实)。
- 定时维护(data/source_maintenance.py,X4:就是一条 target_kind=source_maintenance 的定时,不另建表):fire 按顺序建
探查任务 → 剖析任务(范围 needed / observe / maintenance 按选的步骤),任务上记 trigger=schedule、fire_at、schedule_id;
剖析等探查进了同源队才建,靠 SourceLanes 串行;剖析没开、数据源停用 / 不存在 / 是上传表格时照实记没执行,同源还有
探查或剖析在做时记跳过;触发记录的 inputs 写明建了哪几个任务、哪几步没执行。check_target 核对目标。维护步骤存在
options.catalog_maintenance,经 GET / PUT /api/datasources/{id}/maintenance 改,数据源表单不显示它(api/datasources.py
的 _MANAGED_OPTIONS 加了这一个键)。
测试:test_source_changes(列表与计数、误报要理由、处理过的 409、清理目录与加入码值记目录版本、剖析没开照实 422、
去重、游标拉取与反查、召回触发、通知只有源名条数链接)、test_source_maintenance(按顺序串行、trigger 与 fire_at、
剖析没开记未执行、停用 / 不存在 / 忙、调度循环只补最近一次且积压只记一条、步骤接口与核对目标)。
|
2026-10-16 16:48:40 +08:00 |
|
ThearchyHelios
|
8d59ca1581
|
W3-a 表结构变化:前后差异、影响面、结构版本与 schema.drift(next-round 03 B1)
以前重新探查是整份替换表结构、不比前后:删了一列,那一列上人工确认过的目录项、写死这一列的已发布模板都收不到提醒,
正式运行要到查询那一步才报错。现在:
- data/schema_diff.py:纯函数,同一张表前后两次的结构比出变化(加列、删列、类型、可空、注释、主键与唯一约束、外键);
疑似改名(类型相同、夹在同样两列之间、只有一对)只说「可能」;读不到唯一约束、外键的一边不比;升级后第一次读到
(结构版本 0)只建基线,不把通用写法换成方言完整写法说成类型变了。
- 后台探查顺带记变化(data/introspect_jobs.py):刷新对象索引记新出现的表、真删除的表(第一次建索引只建基线);开始
执行时记离开范围的有目录的表、范围规则和上一次不同;逐批读完拿上一次的结构比,读不到结构的记 table_reflect_failed。
离开范围、读不到结构不算删除。记变化出错只记日志,不挡探查。
- 变化记录 source_changes(db/models_sources.py 的 SourceChange,格式 agentlab-change/1,seq 自增不复用、按指纹去重),
记录与读取在 data/source_changes.py;取值观察的表 TableObservation 同文件建好。
- 影响面(data/catalog_impact.structure_impact):目录里说到被删、被改的列的项(列级项、业务主键、业务日期、有效记录条件
按 parse_valid_filter 取列、两端的关联关系)带状态,人工确认过的升为要处理;已发布模板写死的 SQL 换上新结构再跑
sql_unknown_columns,说得出「这条 SQL 现在会报列不存在」。sql_unknown_columns 从 api/copilot.py 挪到
data/sqlcheck_columns.py 共用,copilot 那边只改 import。
- 发布时记 WorkflowVersion.schema_versions(只记直接引用、结构版本大于 0 的表);正式运行发起时比对,变了写 schema.drift
(core/events.py 登记,只提醒、不拦);版本详情给出 schema_versions、schema_changes;发布前检查把这一版直接引用的表上
还没处理的结构变化列成警告(schema.change_open),不拦发布。
测试:test_schema_diff(纯函数)、test_schema_changes(SQLite 夹具 ALTER 前后、影响面、去重、真删除与离开范围、
schema.drift、发布前检查、升级后基线)。
|
2026-10-16 16:26:11 +08:00 |
|