> ## Documentation Index
> Fetch the complete documentation index at: https://docs.blockx.chaintable.com/llms.txt
> Use this file to discover all available pages before exploring further.

# BlockX 是什么

> BlockX 是一个面向链上数据的函数执行层：接收 task，把触发数据展开成 call，在常驻 Python Executor 池里并行执行轻量函数，再由 Writer Plugin 把结果一次性写回 BlockDB 或回传给调用方。

BlockX 是一个函数执行层。它不存数据，也不编排作业：BlockDB 负责表的存取与订阅，Client 负责生成 task、编排 DAG 和触发；BlockX 只做中间那一段计算。它收到一个 task，把触发数据展开成一组互不依赖的函数调用，在 Worker 本机的 Python Executor 进程池里并行跑完，再把所有返回值一次性交给 Writer Plugin 落库或回传。

核心计算模式是 `onchain table -> onchain table` 的单行状态计算：源表一个区块里的每一行，各自经过一次轻量函数，得到目标表的一行。

## 函数执行层

BlockX 在整条数据链路里只承担"算"这一环：

* **上游**：BlockDB 的 block 表、普通表，或 S3 上按 bundle 切分的 parquet 分区提供输入行；Client（notebook、blockx-py 的 `Pipeline`、调度系统）决定什么时候、对哪个区块算什么。
* **BlockX**：接收 task，扫描或接收触发数据，把每一行变成一次函数调用，在 Executor 池里并行执行，汇聚返回值。
* **下游**：Writer Plugin 把汇聚结果写回 BlockDB 的 block 表或普通表，或原样返回给 Client。

用户写的函数只读不写。它可以通过 SDK 读 BlockDB、调链节点 RPC、调用其他函数，但所有写入都由 task 声明的 Writer Plugin 在函数执行完之后统一完成。

## 一个 task 的三个阶段

| 阶段      | 做什么                                                                          | 由谁执行                        | 产物                        |
| ------- | ---------------------------------------------------------------------------- | --------------------------- | ------------------------- |
| Builder | 把 task 的 `functionCallConfig` 展开成 call 列表：从 BlockDB 读取区块行，或直接采用 task 自带的参数列表 | Call Builder，串行执行一次         | `call list`               |
| Calls   | 把每个 call 投递到 Python Executor 执行用户函数；函数发起的 IO 被拦截回 Worker 统一处理                | Dispatcher + Executor 池，全并行 | `outputs`（所有成功 call 的返回值） |
| Plugin  | 把 `outputs` 一次性写入目标表，或打包回传                                                   | Writer Plugin，串行执行一次        | `TaskResult`              |

三个阶段之间只传递扁平结果：Builder 不知道函数会返回什么，Writer Plugin 也不关心某一行来自哪个 call。详见 [Task 与 Call](/concepts/task-and-call)。

## 三类输入与三类结果处理

task 用两个 `(type, config)` 对声明"算什么"和"结果怎么处理"。`type` 是 Worker 注册表里的名字，`config` 是只有对应实现才解析的 JSON。

Call Builder 决定输入从哪来：

| `functionCallConfig.type` | 输入来源                                                 | 典型用途                |
| ------------------------- | ---------------------------------------------------- | ------------------- |
| `BlockTableCallConfig`    | 按区块从 BlockDB block 表读取触发行（dbScan）                    | 实时：每出一个块跑一次         |
| `InputsCallConfig`        | task 自带的参数列表，每行一次调用                                  | 一次性计算、dry-run、离线批处理 |
| `BlockBundleCallConfig`   | 按 bundle（1000 个区块一段）从 S3 parquet 流式读取触发行（bundleScan） | 历史回填                |

Writer Plugin 决定结果去哪：

| `resultHandler.type`      | 结果去向                | 说明                                            |
| ------------------------- | ------------------- | --------------------------------------------- |
| `BlockTableWriteHandler`  | BlockDB block 表（L2） | block 集群按区块写，bundle 集群按 bundle 批量写；两种实现共用一个名字 |
| `NormalTableWriteHandler` | BlockDB 普通表（L1）     | 按主键 upsert，可带条件更新策略                           |
| `ReturnValueHandler`      | 回传给 Client          | 不写表，把所有返回值拼成一个 JSON 数组放进 `TaskResult`         |

每个 task 恰好一个 Call Builder、至多一个 Writer Plugin。详见 [Call Builder 与 Writer Plugin](/concepts/builders-and-handlers)。

## 两种调用入口

| 入口   | 协议                                                          | 语义                                                    | 适合                   |
| ---- | ----------------------------------------------------------- | ----------------------------------------------------- | -------------------- |
| task | `WorkerService.SubmitTask` + `WatchTasks` / `GetTaskResult` | 异步：提交后拿到 `RUNNING`，终态结果另行订阅或查询；一个 task 内可以有成千上万个 call | 按区块、按 bundle 的批量计算   |
| 同步调用 | `SyncInvokerService.Invoke`                                 | 同步：一次 RPC 执行一次函数并当场返回结果                               | 页面调试、Open API、在线单次调用 |

两者共用同一套 Python Executor、函数代码视图和只读 IO 子系统。Sync Invoker 不经过 Coordinator，也没有 slot 和 Writer Plugin。

## 两套集群

BlockX 用同一份代码、不同的进程 profile 部署成两套集群：

| 集群     | 进程                                             | 注册的 Call Builder                                                  | 注册的 Writer Plugin                                                             | 面向           |
| ------ | ---------------------------------------------- | ----------------------------------------------------------------- | ----------------------------------------------------------------------------- | ------------ |
| block  | `cmd/coordinator` + `cmd/worker`               | `BlockTableCallConfig`、`InputsCallConfig`、`BlockBundleCallConfig` | `BlockTableWriteHandler`（按区块写）、`NormalTableWriteHandler`、`ReturnValueHandler` | 实时单块计算与一次性计算 |
| bundle | `cmd/bundle_coordinator` + `cmd/bundle_worker` | `BlockBundleCallConfig`、`InputsCallConfig`                        | `BlockTableWriteHandler`（按 bundle 写）、`NormalTableWriteHandler`                | 大范围历史回填      |

blockx-py 按 task 的 config 和 handler 自动选择集群；需要结果回传（`ReturnValueHandler`）的 task 一律走 block 集群。详见 [运行时](/concepts/runtime)。

## 小结

* BlockX 是函数执行层：不存数据、不编排，只把 task 展开成 call 并行算完再统一写回。
* 一个 task 经过 Builder → Calls → Plugin 三个阶段，阶段之间只传扁平的 `call list` 和 `outputs`。
* 三类 Call Builder 决定输入从哪来，三类 Writer Plugin 决定结果去哪；用户函数本身只读。
* 异步 task 与同步 `Invoke` 是两个入口；block 与 bundle 是两套按 profile 区分的集群。

继续阅读：

* [Task 与 Call](/concepts/task-and-call)：task 的字段、状态、结果与不变量。
* [函数代码](/concepts/function-code)：入口约定、参数与返回值、可用的 SDK 与静态审计。
* [Call Builder 与 Writer Plugin](/concepts/builders-and-handlers)：三类输入与三类结果处理的配置形状。
* [运行时](/concepts/runtime)：Coordinator、Worker、slot、Executor 与两套集群。
* [架构总览](/architecture/overview)：组件图、核心约束与贡献者阅读顺序。
