TinyPilot: Month 29

Michael Lynch

TinyPilot:第 29 个月

一句话总结

当长期任务停滞时,就该警惕了。

亮点

  • TinyPilot 月收入达到 11.2 万美元,首次突破六位数大关。
  • 我严重高估了 TinyPilot 履约团队的空闲产能。
  • 长期任务可以成为资源即将耗尽的“金丝雀”。

目标评分

每个月初,我都会宣布本月想完成的目标。以下是我对这些目标的完成情况:

准备将 TinyPilot 的履约业务过渡到 3PL 供应商

  • 结果:以一款低销量的产品开始了入驻流程
  • 评分:B

我低估了本地员工在这件事上能腾出的空闲产能。加上一次意外的销售高峰,我们在把内部履约流程适配到 3PL(第三方物流)供应商方面没有取得进展。不过,我们可以先用一个不完美的流程推进,随着 3PL 供应商为我们腾出时间再逐步改进。

继续培训新的支持工程师

  • 结果:两位支持工程师都能独立处理约 80% 的支持工单。
  • 评分:A

支持工程团队的效率超出了我的预期。除了处理高级支持请求之外,支持工程师们还在进行深入调查,从源头上减少 bug 的产生,并改进 TinyPilot 的诊断日志。

减少我处于关键路径上的项目

  • 结果:我克制住了启动任何新项目的冲动。
  • 评分:B

发布新的 TinyPilot 型号总是需要投入我大量时间。我已经经历过足够多次这个过程,能够预见到大部分工作,但我也知道,无论计划做得多周全,总会有我预料不到的工作。尽管有些日子我觉得自己还有点余力,我还是尽量让自己的时间保持空闲。

TinyPilot 数据统计

指标2022 年 10 月2022 年 11 月变化
独立访客数7,9949,512+1,518(+19%)
总页面浏览量17,86220,387+2,525(+14%)
销售收入$85,834.20$107,223.10+$21,388.90(+25%)
企业订阅$290.70$290.700
版税$5,544.12$4,402.50-$1,141.62(-21%)
总收入$91,669.02$111,916.30+$20,247.28(+22%)
利润$26,042.39$7,407.30-$18,635.09(-72%)

TinyPilot 销售额再创历史新高,总收入达到 11.2 万美元。这是 TinyPilot 有史以来第一个突破六位数大关的月份。

这一跃升主要归功于 TinyPilot 在 Linus Tech Tips 上获得了一次正面提及,这是面向家庭实验室(homelab)爱好者最受欢迎的 YouTube 频道之一。尽管那期评测主要讲的是我们竞争对手的产品,但该频道的订阅者实在太多,以至于 TinyPilot 在随后两周内订单大幅激增。

我很高兴看到三个月滚动利润在成本异常偏高的情况下依然稳稳保持为正。TinyPilot 正在以高于正常产能的溢价 3D 打印外壳,但等到一月份切换为金属外壳后,我们的成本应该会显著下降。

我们没有足够的时间来为自己节省时间

11 月的目标之一是开始把履约业务过渡给第三方物流供应商。我请履约团队的一位成员审查我们的工作流程,并准备把它们移交给一家 3PL 供应商。

接下来一周,Linus Tech Tips 视频带来了订单激增,因此关于 3PL 过渡的研究毫无进展。又过了两周,我们仍在消化销售高峰带来的积压,所以依然没有额外进展。

下次与那位履约团队成员开会时,我问他们平时有多少空闲产能来处理这类非典型任务,得知答案大约为零时我很惊讶。履约团队组装设备、发货和处理支持请求这些短期任务,已经占满了他们每周的全部工时。

这种情况似曾相识,只不过通常那个没有短期产能的人是我自己。

对任何工作流程来说,通常都有显而易见的办法可以腾出时间:自动化、增聘人手、改用托管服务等。问题在于,改变一个工作流程存在摩擦成本。

过去几个月里,我一直在画关于外包和授权的时间投入的漂亮图表。本着这种精神,下面是我雇人接手某项任务前后所花时间的对比:

图表显示,在我面试和培训新人的过程中时间投入上升,随后随着对方接管任务而缓慢下降。

一开始,任务很耗时,因为所有工作都由我自己完成。雇人之后,我要做的事反而更多了,因为我既要继续自己做这项任务,又要承担招聘和培训新人的工作。等新人完全上手后,我才能实现净节省,但这可能需要数周甚至数月,取决于任务的复杂程度。

现实中,一天只有那么多小时。如果把我工作时间的上限考虑进去,会发生什么?

图表显示考虑每日工时上限后的时间投入,由于没有足够的空闲产能,我无法完成招聘。

糟糕,现在我无法达到雇人之后的状态了,因为我没有足够的短期空闲产能去招聘和培训别人。我没有足够的时间来为自己节省时间。

用长期任务作为资源耗尽的预警

切换到 3PL 供应商的延误让我意识到,我需要一个更好的预警系统,以便及时发现空闲产能即将耗尽。

我能想到的最佳方案是更加用心地平衡每个人的短期和长期任务。例如,支持工程师的紧急职责是在 TinyPilot 帮助论坛和我们的 CRM 平台上回复客户支持请求。支持量有起有伏,当支持工程师有空闲时间时,他们会寻找支持请求中的重复模式,发布帮助文章,或者调查更深层的 bug 修复。

TinyPilot 的每个人都同时承担着短期和长期任务:

团队短期任务长期任务
创始人团队管理
供应商管理
审查工作
填补职责空缺
市场营销
公开写作
重新评估战略
招聘与培训
履约人员组装设备
履行订单
客户服务
编写客户支持手册
协助市场营销
支持工程师回答技术支持问题编写文档
撰写博客文章
调查疑难 bug
软件开发者发布新功能
修复紧急 bug
重构代码
改善开发体验
编写自动化测试
修复非紧急 bug

长期任务可以充当煤矿里的金丝雀。当一个团队在长期任务上的进度持续放缓时,他们很可能正在逼近最大产能。此时,我应该通过减少职责或增加产能来降低负载。

用长期任务作为预警信号有两个难点。第一,最经常忽视自己长期任务的团队是创始人团队——也就是我自己。当我超负荷运转时,我不会注意到其他团队长期任务的放缓;即使注意到了,我也没有时间去处理。我想解决办法是对自己承接的项目数量更加警惕,从而留出应对切换成本的空闲产能。

另一个问题是,履约团队的长期任务最不明显。我们的制造和履约流程并不是那种每周都能改进的工作流。但随着我们把履约和制造转移给第三方供应商,履约团队的职责将转向客户支持。客户支持在回复支持请求这类短期工作和完善内部手册这类长期工作之间有着更自然的平衡。

爬出 Ansible 这个坑

Ansible 是一个用于自动配置服务器的工具。我用它已经七年了,它也是我管理家庭实验室中所有虚拟机的方式。

2020 年我开始开发 TinyPilot 时,需要一种方法把代码部署到树莓派上,并配置 TinyPilot 所需的系统功能。Ansible 很合适,因为远程系统配置正是 Ansible 的看家本领。

发布 TinyPilot 时,让用户安装它的最简单方式就是复刻我开发时使用的工作流。我创建了一个简单的安装脚本,先引导搭建一个 Ansible 环境,然后通过 Ansible 安装 TinyPilot。

当时我就知道,更常规的做法是使用 Debian 软件包。问题是我对制作 Debian 软件包一无所知,而且看起来工作量很大。我是不是得自建 apt 仓库?要不要管理仓库密钥?TinyPilot 依赖 nginx,那我该怎么在自己的软件包里配置 nginx?

两年半过去了,开发团队正在为我当初选择 Ansible 付出代价。随着 TinyPilot 功能越来越多,我们的 Ansible 配置变得复杂得令人痛苦。如果安装器是一个纯 shell 脚本或 Debian 软件包,安装大概只需 10 到 20 秒。而现在,Ansible 带来的各种开销把安装和更新时间拖到了六分钟以上。

除了影响最终用户之外,Ansible 还倾向于吞噬开发资源。Ansible 代码调试起来既慢又繁琐,尤其是在涉及我们持续集成环境中没有的操作系统和架构时。微小的改动经常膨胀成一周的开发时间。

最近几个月,开发团队一直在探索如何把 Ansible 代码移植成 TinyPilot 的 Debian 软件包。我很高兴地报告,我们现在已经有了立足点。我们创建了一个混合方案:TinyPilot 的 Ansible role 负责安装最新的 TinyPilot Debian 软件包。这样我们就可以逐步蚕食 Ansible 代码,把它迁移到 Debian 软件包中。

以下是我当初着手开发 TinyPilot 时希望就已了解的关于 Debian 的事情:

  • 你可以在不运行自己的 apt 仓库的情况下创建和分发独立的 Debian 软件包。
  • 只要遵循正确的教程,创建一个简单的 Debian 软件包只需 15 分钟。
  • 你可以使用 Docker QEMU 从 x64 系统构建 ARM 架构的 Debian 软件包。
  • 如果你的代码是用 Python 这类可移植语言编写的,你可以跳过 QEMU,构建架构无关的 Debian 软件包。
  • 如果你的软件包需要配置另一个软件包,通常的做法是向配置目录添加文件,而不是改动对方软件包拥有的文件。
    • 例如,TinyPilot 的 Debian 软件包可以通过向 /etc/nginx/sites-enabled/ 目录添加文件来配置 nginx。

学习 Debian 最难的部分是在海量噪音中找到有用的信息。很多资源的说法基本上就是:“直接去读那份9000 页的 Debian 维护者指南吧,忽略其中过时的部分就行。”

我觉得最有帮助的指南是:

Vincent 甚至非常热心地和我进行了视频通话,解答了我关于 Debian 软件包的一些遗留问题。

业余项目

ScreenJournal

我看很多电视剧和电影,也喜欢向朋友推荐,但我常常忘记自己想推荐的是哪部剧或哪部电影。

我找过一些能像用 Goodreads 追踪阅读那样追踪电影和电视剧的应用,但没有一个符合我的设想。我感觉朋友们已经被那些默认公开的社交应用搞得疲惫不堪,所以我想要的是一个让你能建立一个小型朋友社区、彼此分享推荐的东西。少一点 Twitter 的味道,多一点 Discord 的感觉。

我已经开始开发一个与朋友分享影评的应用,名叫 ScreenJournal

我在 ScreenJournal 上的影评截图

ScreenJournal 就像是给沙发土豆用的 Goodreads。

它还没准备好正式上线,因为目前评论是私密的,而且只支持单个用户。现在它只能作为一个人的私人观影日记发挥作用,但我清单上的下一个功能就是多用户支持。

用户管理出了名地难以做好,所以我一直避免自己造轮子。过去几年,我一直用我的朋友 David Toth(David Toth)的 UserKit 服务来管理用户。UserKit 一直很好用,但它尚未对公众开放,这让其他想在自家服务器上运行 ScreenJournal 的开发者没法用它。

我找过 Go 语言的开源用户管理框架,但大多数依赖外部服务的 OAuth,这不是我想要的;剩下的要么太重要么太复杂,我不想费那个劲。

于是,我决定铤而走险,自己实现用户管理。会话管理方面,我在用 jeff;身份验证方面,我打算用 bcrypt,然后听天由命。

收尾

完成了什么?

  • 开始了与一家 3PL 供应商的入驻流程。
  • 在几个重要方面改进了 TinyPilot 的 Debian 软件包。
  • 为国际承包商找到了更好的支付平台。
    • Deel 的体验很差,我对 Remote.com 也不太满意,所以我们选择了 Pilot

经验教训

  • 长期任务是资源耗尽的一个很好的先行指标。
    • 如果一个团队在长期任务上的进度持续放缓,就必须在你还有回旋余地切换流程之前解决这个问题。
    • 创始人尤其要为长期任务留出时间,否则就无法有效应对其他团队的资源耗尽。
  • Debian 打包并不像乍看上去那么吓人。

下月目标

  • 完成来自 3PL 供应商的首笔订单履约。
  • 让下一个 TinyPilot Pro 版本达到代码完成状态。
  • 为一月份发布 TinyPilot Voyager 2a 做好准备。

原文由 Michael Lynch 发布

本文章由 stealth/ox-alpha 进行翻译