news 2026/10/3 8:35:53

Papermark 集成 Tinybird 实战指南:Pipe 推送、数据源删除与 Danger Zone 操作手册

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Papermark 集成 Tinybird 实战指南:Pipe 推送、数据源删除与 Danger Zone 操作手册
  • 后端
  • 前端
  • 企业应用

【免费下载链接】papermark

Papermark is the open-source DocSend alternative and secure data rooms with built-in analytics and custom domains.

项目地址:https://gitcode.com/GitHub_Trending/pa/papermark
点击查看免费下载

导读

本文聚焦 Papermark 开源项目中lib/tinybird/目录承载的实时分析基础设施,完整讲解两件开发者高频实操:如何把新增的 Tinybird Pipe 推送到云端(tb push),以及如何在“危险区”按条件精确删除数据源中的记录(tb datasource delete)。读完本文,你将掌握 Tinybird CLI 的核心操作姿势、Papermark 五类埋点数据源与十五个分析端点的组织方式,以及避免误删线上数据的防御性操作套路。

Tinybird 在 Papermark 中的角色

Papermark 是开源的 DocSend 替代品,提供文档与数据房的链接分享、内置分析与自定义域名能力。其分析能力由 lib/tinybird/ 目录承载:这是一个完整的 Tinybird 项目,包含数据源定义(datasources)、SQL 分析端点(endpoints)、发布与查询的 TypeScript 客户端(publish.ts、pipes.ts),并以 README.md 记录了两类核心运维命令。

整个模块通过@chronark/zod-bird库与 Tinybird 云端交互,初始化代码位于 pipes.ts 与 publish.ts:

const tb = new Tinybird({ token: process.env.TINYBIRD_TOKEN!, // Tinybird is region-hosted; zod-bird defaults to the US API host. baseUrl: process.env.TINYBIRD_BASE_URL, });

对应需要配置两个环境变量:TINYBIRD_TOKEN(必填,用于认证)与TINYBIRD_BASE_URL(可选,用于指定 Tinybird 区域主机,默认指向美国 API Host)。仓库的.env示例中已预留TINYBIRD_TOKEN=项。

新增 Pipe 并推送到 Tinybird

核心命令

当你基于现有 Pipe 复制出一个新分析端点、或在本地调试 SQL 后,需要将本地 Pipe 文件同步到 Tinybird 云端。官方操作只有一条命令(出自 README.md):

tb push lib/tinybird/endpoints/<PIPENAME>.pipe

其中<PIPENAME>替换为 endpoints/ 目录下的实际 Pipe 文件名,例如:

# 推送“按查看者统计文档时长”的端点 tb push lib/tinybird/endpoints/get_document_duration_per_viewer.pipe # 推送“单次查看的点击事件”端点 tb push lib/tinybird/endpoints/get_click_events_by_view.pipe

前提与环境准备

  • 安装 Tinybird CLI(tb),并在终端完成tb auth登录;
  • 确认当前工作区绑定正确的工作区(tb workspace use <workspace>);
  • 确保 Pipe 文件引用的数据源(datasource)已经发布到云端,或在同一tb push前先推送数据源文件(tb push lib/tinybird/datasources/*.datasource)。

Pipe 文件结构:以get_total_average_page_duration.pipe为例

以仓库中 get_total_average_page_duration.pipe 为例,一个端点文件由版本声明与 SQL 组成:

VERSION 5 NODE endpoint SQL > % WITH DistinctDurations AS ( SELECT versionNumber, pageNumber, viewId, SUM(duration) AS distinct_duration FROM page_views__v3 WHERE documentId = {{ String(documentId, required=true) }} AND time >= {{ Int64(since, required=true) }} AND time <= {{ Int64(until, 9999999999999) }} AND linkId NOT IN splitByChar(',', {{ String(excludedLinkIds, required=True) }}) AND viewId NOT IN splitByChar(',', {{ String(excludedViewIds, required=True) }}) GROUP BY versionNumber, pageNumber, viewId ) SELECT versionNumber, pageNumber, AVG(distinct_duration) AS avg_duration FROM DistinctDurations GROUP BY versionNumber, pageNumber ORDER BY versionNumber ASC, pageNumber ASC

关键点:

  • VERSION N是 Pipe 的版本号,tb push时会与云端版本对比,相同版本需加--force才能覆盖;
  • {{ String(param, required=true) }}是 Tinybird 的参数模板语法,Int64(until, 9999999999999)表示带默认值(9999999999999 即“不限截止时间”)的可选参数;
  • splitByChar(',', {{ String(excludedLinkIds) }})演示了如何在 SQL 中消费逗号分隔的排除 ID 列表——这与下方 TypeScript 客户端里excludedLinkIds: z.string()的声明一一对应。

客户端与 Pipe 的“锁步”约定(重要实践)

lib/tinybird/pipes.ts 顶部有一段非常值得注意的注释(L13-L18):

这里声明的参数只是客户端契约:Tinybird 会静默忽略部署后的 Pipe SQL 中未引用的查询参数。因此在下方添加until之前,必须先推送匹配的endpoints/*.pipe(tb push --force)。两者必须保持同步——SQL 里不存在的until会让人误以为时间过滤生效,实则返回的是全时间段数据。

这意味着一个极易踩坑的陷阱:zod-bird 客户端的参数声明与 Pipe SQL 中{{ }}参数不同步时,错误不会报出来,只会悄悄返回错误结果。正确的改动顺序是:

  1. 修改 endpoints/ 下对应.pipe文件的 SQL,加入参数;
  2. 执行tb push lib/tinybird/endpoints/<PIPENAME>.pipe(版本未变时加--force);
  3. 再同步更新 pipes.ts 中对应buildPipe的parametersschema。

推送后可用tb pull反向验证云端 Pipe 与本地文件是否一致。

客户端侧的参数契约示例

在 pipes.ts 中,每个端点对应一个强类型查询客户端,例如按文档聚合的总平均时长(L19-L33):

export const getTotalAvgPageDuration = tb.buildPipe({ pipe: "get_total_average_page_duration__v5", parameters: z.object({ documentId: z.string(), excludedLinkIds: z.string().describe("Comma separated linkIds"), excludedViewIds: z.string().describe("Comma separated viewIds"), since: z.number(), until: z.number().optional(), }), data: z.object({ versionNumber: z.number().int(), pageNumber: z.string(), avg_duration: z.number(), }), });

注意 Pipe 名带__v5后缀,与.pipe文件内的VERSION 5对应,避免不同版本共存时互相覆盖。全仓库共有 15 个此类端点,覆盖:页面时长、文档/链接/查看者/团队总时长、查看完成度、UA 信息、视频事件、点击事件、Webhook 事件与数据房文档统计等场景。

数据写入侧:Ingest Endpoint

除了查询,publish.ts 定义了 5 个数据写入端点(buildIngestEndpoint),分别对应 5 个数据源:

写入函数数据源用途
publishPageViewpage_views__v3用户浏览文档的翻页事件
recordWebhookEventwebhook_events__v1Webhook 触发事件(含 QStash message ID)
recordVideoViewvideo_views__v1视频播放事件(播放率、音量、静音/聚焦/全屏状态)
recordClickEventclick_events__v1文档内链接点击事件
recordLinkViewTBpm_click_events__v1访客打开链接事件(含大陆/国家等地理信息)

这些函数同样基于 zod schema 做运行时校验与默认值填充,例如publishPageView中versionNumber限制在 1–65535、device默认"Desktop"、地理字段默认"Unknown"、referer默认"(direct)"。

Danger Zone:按条件删除数据源中的记录

官方命令

这是 README.md 中“危险区”的唯一命令,用于从指定数据源中按 SQL 条件精确删除数据:

tb datasource delete page_views__v3 --dry-run --sql-condition "viewId='VIEWID' and CAST(pageNumber AS UInt8) = PAGENUMBER" --wait

参数拆解:

  • page_views__v3:目标数据源名,必须与云端实际名称一致(注意版本后缀__v3);
  • --sql-condition:删除条件,用单引号包裹一段 ClickHouse SQL WHERE 子句,只有满足条件的行会被删除;
  • --dry-run:只统计将删除的行数而不实际删除,是上线前的必做演练;
  • --wait:等待删除任务完成并返回最终结果,避免异步任务未落库就退出。

命令本身即演示了一个典型场景:清理某次查看(viewId)在指定页号(pageNumber)上误采集的脏数据。CAST(pageNumber AS UInt8)说明pageNumber字段在 page_views.datasource 中声明为LowCardinality(String),与数字比较前需显式转型。

安全操作流程(建议顺序)

  1. 先 dry-run 评估影响面:对线上数据源执行--dry-run,确认返回的待删除行数符合预期;
  2. 核对条件字段:确认--sql-condition引用的字段名与目标数据源 SCHEMA 完全一致(大小写敏感),并与 Pipe 查询里使用的过滤字段对齐(如viewId、documentId、time);
  3. 去掉--dry-run正式执行,保留--wait等待任务完成;
  4. 用查询端点复核:通过对应的 Pipe(如get_page_duration_per_view)查询该viewId,确认数据已消失。

为什么需要这样的删除能力

Papermark 的 page_views.datasource 采用ENGINE "MergeTree",排序键为linkId, documentId, viewId, versionNumber, pageNumber, time, id。ClickHouse 的 MergeTree 系列引擎本身不支持按条件 UPDATE/DELETE 语义(主路径只能整表 TRUNCATE),因此“按条件删行”必须借助 Tinybird 提供的tb datasource delete能力完成。这解释了为什么该命令被放在 README 的Danger Zone章节——它是为数不多能直接改写线上数据的操作,一旦--sql-condition写得过宽,就可能误删整表数据。建议删除前先在副本数据源(如page_views__v3_dryrun)上验证条件语义。

各数据源删除条件参考

删除条件的字段以数据源 SCHEMA 为准。仓库共 5 个数据源:

  • page_views.datasource:id、linkId、documentId、viewId、dataroomId、versionNumber、time(Int64 Unix 时间戳)、duration、pageNumber、地理与 UA 字段、bot、referer;
  • click_events.datasource:event_id、session_id、link_id、document_id、view_id、page_number、version_number、href,按月分区(ENGINE_PARTITION_KEY "toYYYYMM(timestamp)");
  • pm_click_events.datasource:访客打开链接事件,含continent等地理字段;
  • video_views.datasource:event_type、start_time、end_time、playback_rate(存储为 100/150/200 而非 1.0/1.5/2.0)、volume(0–100 而非 0.0–1.0)、is_muted/is_focused/is_fullscreen、ip_address;
  • webhook_events.datasource:event_id、webhook_id、url、event、http_status、request_body、response_body、message_id。

示例删除条件:

# 删除某个 link 在指定时间窗口之前的全部浏览事件(谨慎!先 dry-run) tb datasource delete page_views__v3 --dry-run --sql-condition "linkId='link_xxx' and time < 1700000000" --wait # 删除某次查看的点击事件 tb datasource delete click_events__v1 --dry-run --sql-condition "view_id='view_xxx'" --wait

常见问题与排查

  • tb push提示版本冲突:Pipe 的VERSION与云端相同。若是真正覆盖,使用tb push --force;若应发布为新版本,则更新.pipe文件内的VERSION号,并同步修改 pipes.ts 中pipe:名称的__vN后缀。
  • 查询返回空结果但客户端未报错:优先检查 pipes.ts 参数与 Pipe SQL{{ }}模板是否同步(锁步约定),特别是新增until这类可选参数时,务必先推送 Pipe 再改客户端。
  • 删除命令疑似影响过大:永远先执行--dry-run,并根据输出行数与预期比对;条件字段务必对照目标.datasource文件的 SCHEMA 核对类型(如pageNumber为字符串需CAST)。
  • 区域/认证错误:检查TINYBIRD_TOKEN与TINYBIRD_BASE_URL环境变量是否配置正确,后者用于多区域部署时指定非美国区主机。

小结

Papermark 的 Tinybird 集成把“埋点写入”与“分析查询”全部收敛在 lib/tinybird/ 一个目录内:.datasource定义存储结构,.pipe定义 SQL 端点,pipes.ts 与 publish.ts 分别提供类型安全的查询与写入客户端。日常开发中,tb push lib/tinybird/endpoints/<PIPENAME>.pipe是发布新端点的标准动作,而tb datasource delete --dry-run --sql-condition "..." --wait则是清理脏数据时务必小心的危险操作——坚持“先 dry-run、后执行、再用 Pipe 复核”三步走,即可在享受实时分析能力的同时守住数据安全底线。

  • 后端
  • 前端
  • 企业应用

【免费下载链接】papermark

Papermark is the open-source DocSend alternative and secure data rooms with built-in analytics and custom domains.

项目地址:https://gitcode.com/GitHub_Trending/pa/papermark
点击查看免费下载

相关推荐

上一篇:告别灰屏,CefFlashBrowser 让老 Flash 游戏与 SWF 文件重新跑起来
下一篇:5 分钟解锁壁纸资源:RePKG 让 PKG 解包与 TEX 转 PNG 一步到位

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/3 8:26:14

linux-command 仓库详解 Linux tee 命令:标准输出与文件双写实战指南

文档教程 【免费下载链接】linux-command Linux命令大全搜索工具&#xff0c;内容包含Linux命令手册、详解、学习、搜集。https://git.io/linux 项目地址&#xff1a; https://gitcode.com/GitHub_Trending/linux/linux-command 点击查看 免费下载 tee 是 GNU coreutils 中一个…

作者头像 李华