很少有传统能像丑陋的节日毛衣比赛那样融化公司的坚冰。这就是为什么在去年12月,我接受了建立一个丑陋毛衣投票应用程序的挑战,以娱乐我们100%分布的团队。
该应用(可用于对任何图片进行投票--不仅仅是丑陋毛衣)包括一个显示比赛状态的仪表盘和一个无服务器的后端,便于启动仪表盘并使用websockets处理短信的更新。比赛的结果是......丑陋的!(当然,除了我们的首席执行官,他不知何故穿了一件丑陋的毛衣,但却让人觉得很时尚)。

丑陋毛衣应用程序的经验有两个有趣的收获。
- 我们比赛的获胜者从未听说过 "丑陋节日毛衣"。显然,在英国,它们被礼貌地称为 "节日毛衣"。
- Pusher Channels让生活变得更简单,我强烈推荐用它来构建。
这是我用CockroachDB建立的第一个样本应用程序之一,我对数据库与我的许多首选工具的契合度很满意。如果你想跳到README,github repo就在这里。
这个 "丑毛衣 "应用程序的目标是为我的团队提供一个互动体验,同时也展示了使用CockroachDB访问数据的多种常见方式。以下是该应用的工作原理。
- 要参加比赛。向 "丑陋毛衣 "比赛的指定电话号码发送图片和名字。
- 要在比赛中投票。将你想投票的人的名字发到同一个指定的电话号码上。
该应用程序的功能在设计上很简单。我认为重要的是该应用程序的组成部分,值得进一步解释。请看一下图,然后我将解释应用程序组件的功能以及我为什么选择它们。
无服务器应用程序的工作流程
Netlify平台。使用serverless函数作为webhook接收器
我是Netlify的粉丝已经不是什么秘密了(看看我过去几年的任何一个项目就知道了),这个应用充分利用了他们的平台。Twilio和应用程序之间的通信是使用Netlify函数处理的,而仪表盘是一个使用Netlify Essential Next.js Build Plugin部署的Next.js应用程序。
在过去的几年里,在事件驱动架构中使用无服务器函数已经变得相当流行,而Netlify使它们易于编写和部署。如果你在指定的文件夹中提供一个带有处理函数的JavaScript文件,Netlify将把它作为AWS Lambda函数来构建、打包和部署。
无服务器函数很适合这个应用,因为我们需要一个端点作为webhook的接收器。这是一个端点,Twilio可以在收到彩信后向你的Twilio电话号码发送一个POST请求。重要的是,如果有很多人同时参赛和投票,这个函数可以扩展到处理负载,因为这个函数负责比赛的所有行动。这些动作包括创建一个新的参赛项目或更新投票数等。这是由写到CockroachDB和推送新事件到Pusher Channels来完成的。
Twilio用于入站/出站短信
我希望这个应用程序有一个非常低的进入门槛。任何人都应该能够参与,而不需要安装一个应用程序。我认为可以说,在2022年,大多数人都有一个能够发送彩信的设备。进入Twilio。Twilio已经存在了很长时间,并且一直是我创建有趣的互动应用程序的首选。虽然我们大多数人都可能用Twilio来发送短信,但不是每个人都用Twilio来接收短信(以及发送的任何图片)。这一点很好,因为发送图片的同时也将图片文件减少到了1MB以下,小到可以存储在数据库的BYTES列中。这使得我们可以把带有图像的消息作为条目,而把没有图像的消息作为投票。一旦我们将Messaging Webhook配置到我们的Twilio电话号码上,并将其POST到我们的无服务器函数上,每条消息(连同任何图片)就会被发送到我们的应用程序中进行处理。
CockroachDB无服务器存储
一旦我们的无服务器函数完成了对来自Twilio的文本消息的处理,数据就需要被存储起来,这样才能在仪表盘上显示给参与者。我们需要跟踪所有可能同时进行的比赛,以及包括图片和投票在内的参赛项目。
由于我们使用的是无服务器功能,可以通过扩展来处理增加的负载,所以我们需要一个能做到这一点的数据库。这使得CockroachDB无服务器成为一个很好的选择。你可以免费开始使用CockroachDB Serverless。这个特殊的应用利用了BOTTES列的类型,使我们能够在数据库中存储图像。我们还使用外键和唯一约束来确保数据的完整性。由于CockroachDB Serverless使用基于消费的定价(5GB以下免费,2.5亿个请求单位),我们可以确保你在没有竞赛的情况下不会付费。
前台的Next.js
现在,比赛项目和投票都在CockroachDB中被写入和更新,我们需要一种方式让参与者查看它们。我可以使用任何框架来建立这个仪表板。我的很多项目都使用Next.js,所以我在这个项目中也使用了它。如果我再做一次,也许我会使用Remix之类的东西......(可能预示着我的下一篇博客?)Next.js允许我在服务器上渲染页面,使用Prisma从CockroachDB提取数据。
Prisma是一个ORM,可以帮助开发者使用CockroachDB快速构建应用程序。CockroachDB和Prisma正处于早期阶段,最终将成为一个全面的整合。
显示参赛作品和票数是很好的,但是由于参赛者遍布世界各地(美国、英国、意大利、印度......),我们需要能够看到实时出现的投票。没有人有时间坐在网站上按F5键。这就是Pusher的作用。他们的Channels产品是websockets服务,与我们的无服务器架构相匹配。你不需要建立自己的socket.io服务,而只需创建一个新的Channels应用并连接到它。从无服务器功能中,你可以将事件推送到你的频道中,并在订阅该频道的任何前端实时接收它们。每个竞赛都有自己的频道,仪表板会聆听任何新的投票或参赛项目,并进行相应的更新。
如果你想了解更多关于为像CockroachDB这样的分布式SQL数据库编写模式的信息,我建议你参加一个在线课程或者阅读我们的一些博客和文档。(是的,写模式是很重要的。这将为你省去很多麻烦)。
下面是我为这个应用程序写的数据库模式(你可以在这里查看所有的SQL语句。)
用于比赛。
- id - UUID
- name - 字符串
- description - 字符串
- max_votes - Int (每个投票者的最大票数)
对于参加比赛的作品。
- id - UUID
- contest_id - UUID
- name - String
- picture - BYTES (最大1MB)
- picture_type - 字符串
用于在比赛中投票。
- contest_id
- 参赛者_ID
- voter_id (从电话号码中提取的哈希值?)
就这样了。这就是这个应用程序。如果你对我选择的任何组件或我如何使用它们有疑问,请在Twitter上给我发信息。我还在twitch上做了每周一次的直播,你可以在我的狗在背景中发出迷人的声音时向我提问。