Serverless實戰:打造個人閱讀追蹤系統

軟件 Instapaper GitHub IFTTT ThoughtWorks ThoughtWorks 2017-10-04

閱讀習慣和個人知識管理體系

進入互聯網時代,知識的獲取成本變得前所未有的低廉,但是無論再好的知識,若是沒有對個人產生價值的話,那也只不過是一種信息噪音而已。我在《個人知識管理:知識的三種形態》這篇文章中使用“材料 -> 資料 -> 知識”這樣的路徑來詮釋信息的流通,如何方便快捷並且有效地收集材料,再將其整理轉化為有價值的個人知識體系結構,在這個信息極度碎片化的時代變得尤為重要。而在《去偽存真的知識管理之路》一文中也詳細闡述瞭如何將網絡上的碎片化文章納入統一的稍後閱讀體系,比如有時候在朋友圈看到一篇好文章,但暫時沒時間直接看,或是這篇文章值得再讀一遍,細讀一遍,那麼我就會將其存入稍後閱讀工具即Instapaper當中,諸如此類的還有Pocket、收趣等等。

Serverless實戰:打造個人閱讀追蹤系統

稍後閱讀中永遠讀不完的痛點:缺乏追蹤

隨著時間的推移,Instapaper裡面的文章將會變得越來越多,就像我們在代碼中所註釋的TODO:可能就變成了Never Do,“稍後讀”也是一樣地被廣為詬病:Read it Later=Read Never。其實我發現文章堆積的一個永恆痛點就是沒有有效的方式追蹤自己的閱讀需求與能力,其核心原因在於閱讀的速度趕不上添加的速度。從而沒辦法可視化的評估閱讀進度、合理安排閱讀計劃,也就沒辦法給予自己適當的獎勵,長此以往必然將失去閱讀的動力。

在之前的一篇文章——《基於GitHub的敏捷學習方法之道與術》,其中提到使用GitHub Issue來管理自己的學習計劃,於是就產生了這麼一個想法——將我的稍後閱讀列表跟GitHub結合起來,使用ZenHub豐富的圖表功能將閱讀體系進行追蹤與可視化。

Serverless實戰:打造個人閱讀追蹤系統

可視化Cumulative Flow Diagram

首先讓我們直接來看一下最終的具體效果圖,在這裡簡單介紹一下CFD(Cumulative Flow Diagram)即累積流圖,這是一種能讓你快速瞭解項目或產品工作概況的圖表,關注的是價值的流動效率,價值的流動最直接的體現就是需求卡片在各個隊列中的數量。

Serverless實戰:打造個人閱讀追蹤系統

裡特定律(Little’s law)告訴我們,交付時間(Delivery time)依賴於在製品數量(Work In Progress, WIP)。WIP是指所有已經初始但還未完成的工作,例如:所有在分析(Analysis)與完成(Done)之間的工作。首先需要留意的就是WIP,如果WIP增加了,交付日期就會有風險。ZenHub所提供的Release Report中最有效果的就是預測完成日期,總之就是跟敏捷方法結合起來,使用項目管理的方式來管理自己的閱讀列表,雖然我還處在進一步的探索之中,但是每次看到這個走勢圖就能對自己的閱讀列表有更多的掌控和理解,至少減少了因文章堆積而產生的焦慮感。

IFTTT與Serverless架構

那麼這是怎麼通過APIs來實現的呢?在真正進入正題之前我們先來簡單介紹一下Serverless架構。Serverless指的是在構建Web應用程序的時候,不用擔心如何配置服務器,但是這並不意味著應用程序不會在服務器上運行,而是說服務器的管理都可以儘可能地交給相應的雲平臺,從而最大程度地減輕開發人員的部署與配置工作。與之對應的一個名詞可能就是Function As a Service(FAAS),由AWS Lambda這個命名就能想到,當我們在構建Serverless架構時,實際上我們是在寫一個個的Function,即函數而已。

Serverless實戰:打造個人閱讀追蹤系統

流程化:APIs即服務

首先讓我們來介紹一下IFTTT即if this then that。通俗的來講,IFTTT的作用就是當一件事情被觸發時,能夠執行設定好的另一件事。所謂的「事」,指的是各種應用、服務之間可以進行有趣的連鎖反應。IFTTT的宗旨是Put the internet to work for you(讓互聯網為你服務)。用戶可以在IFTTT裡設定任何一個你需要的條件,當達成條件時,便會觸發下一個指定好的動作。它就像是一座神奇的橋樑,能連接我們日常所用的各種網絡服務。

Serverless實戰:打造個人閱讀追蹤系統

而我們現在遇到的這個串聯式的場景是特別合適Serverless架構的,使用IFTTT並且將它跟Instapaper賬號綁定,設置文章添加、高亮、歸檔等行為作為trigger條件,然後將相關信息發到某一個指定API endpoint。先把操作GitHub Issue和ZenHub的各種APIs準備好,結合IFTTT的觸發器與Marker工具能夠非常方便地與之相集成,最後我們可以產出這樣一個APIs交互流程圖:

Serverless實戰:打造個人閱讀追蹤系統

初始化Webtask項目

雖然AWS Lambda是Serverless架構的典範,但它也有一些槽點,而且我覺得已經被人說得足夠多了,所以我們今天就來嚐嚐鮮,著重介紹和使用一下Webtask。你可能沒有聽說過推出該服務的這家公司——Auth0,但你一定知道大名鼎鼎的JWT即JSON Web Token,這是一種開放標準(RFC 7519),通常被運用在身份驗證(Authentication)和信息交換等需要安全傳輸信息的場景下。

首先讓我們來安裝工具初始化項目以及註冊賬號,然後使用電子郵件進行登錄:

npm install -g wt-cliwt init <YOUR-EMAIL>

創建項目目錄,添加index.js文件並添加以下內容:

module.exports = function (cb) { cb(null, 'Hello World');}

然後在該目錄中運行以下命令,進行應用程序部署之後,點擊控制檯中輸出的URL就能看到編程史上最有名氣、沒有之一的HelloWorld!:

wt create index

Serverless實戰:打造個人閱讀追蹤系統

Webtask的上下文綁定

Webtask有一個實用工具webtask-tools,可以將應用程序綁定到Webtask上下文,讓我們將之前所export的簡單函數修改為綁定到Webtask的Express app,然後就可以愉快地使用Express進行開發,一切就又回到了熟悉的軌道:

app.use(bodyParser.urlencoded({ extended: false }))app.use(bodyParser.json())require('./routes/reading')(app)module.exports = Webtask.fromExpress(app)

Webtask context還有一個非常重要的用途,就是在部署時傳輸一些敏感信息,比如安全Token,從而在應用程序當中隨時使用它們。下面的部署命令中–secret後面所傳入的ACCESS_TOKEN都會在後續與GitHub和ZenHub APIs交互時被用到。

wt create index --bundle --secret GITHUB_ACCESS_TOKEN=$GITHUB_ACCESS_TOKEN--secretZENHUB_ACCESS_TOKEN=$ZENHUB_ACCESS_TOKEN --secretZENHUB_ACCESS_TOKEN_V4=$ZENHUB_ACCESS_TOKEN_V4# ./routes/reading.jsmodule.exports = (app) => { app.post('/reading', (req, res) => { const { GITHUB_ACCESS_TOKEN, ZENHUB_ACCESS_TOKEN, ZENHUB_ACCESS_TOKEN_V4 } = req.webtaskContext.secrets }}

使用GitHub Issue追蹤閱讀列表

IFTTT:添加Instapaper文章後自動創建GitHub Issue

得益於IFTTT非常豐富的第三方服務,IFTTT可以直接創建Instapaper與GitHub Issue相集成的Applet:If new item saved, then create a new issue – IFTTT,就可以在當Instapaper新增文章的時候,自動在GitHub所指定的倉庫Issues · JimmyLv/reading 中創建一個新的Issue並添加相應的標題、鏈接以及描述等相關信息。

Serverless實戰:打造個人閱讀追蹤系統

但僅僅只是添加一個Issue還不夠,這時候還需要將這個Issue加入到指定的Milestone以便利用ZenHub的圖表功能,使用GitHub的Webhooks功能就可以輕鬆幫我們把Issue更新的狀態轉發到我們所指定的Webtask地址:

Serverless實戰:打造個人閱讀追蹤系統

使用GitHub Webhook 更新Issue的Milestone

所以我們的Webtask就需要處理GitHub Webhook所轉發的POST請求,其中包括了Issue的類型和內容,在拿到’opened’即新建Issue類型的action之後我們可以對其進行相應的處理,即添加到Milestone當中:

if (action === 'opened') { fetch(`${url}?access_token=${GITHUB_ACCESS_TOKEN}`, { method: 'PATCH', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ milestone: 1 }) })}

Serverless實戰:打造個人閱讀追蹤系統

結合ZenHub的Milestone燃盡圖我們可以清晰地看到剩餘閱讀量,並且能夠跟理想中的閱讀速度進行對比,從而判斷自己什麼時候能夠全部讀完所有的文章。可能有些小夥伴看到這裡會有所疑問,這些所謂的Story Point是從哪兒來的呢?接下來就要提到我們將要集成的ZenHub API了。

集成ZenHub API:閱讀可視化

更新Issue的估點和Release

GitHub Issue的任何變動都會觸發Webhook,因此我們可以在Issue被加入Milestone之後再處理下一個’milestoned’ action,即:

if (action === 'milestoned') {fetch(`https://api.zenhub.io/p1/repositories/${REPO_ID}/issues/${number}/estimate?access_token=${ZENHUB_ACCESS_TOKEN}`, { method: 'PUT', body: JSON.stringify({ estimate: 1 }) }) .then(() => { returnfetch(`https://api.zenhub.io/v4/reports/release/591dc19e81a6781f839705b9/items/issues?access_token=${ZENHUB_ACCESS_TOKEN_V4}`, { method: 'POST', }) })}

這樣我們就完成了對每個GitHub Issue的估點,以及設置了對應的Release,接下來所有的變動都將體現在ZenHub的圖表當中。

歸檔Instapaper文章後關閉GitHub Issue

說了這麼多,不要忘了整個閱讀系統最最核心的部分依然還是「閱讀」啊!在眾多的稍後閱讀工具中我無比喜愛Instapaper並遲遲沒有轉到Diigo的原因就在於它優秀、簡潔、純粹的閱讀體驗,讓人可以專注在閱讀本身這件事情上,在被Pinterest收購之後更是將所有的諸如全文搜索、無限高亮/筆記、速讀等Premium功能都變成了免費,豈不美哉?

Serverless實戰:打造個人閱讀追蹤系統

那麼在完成閱讀歸檔之後,最後一步就是在GitHub當中將Issue關閉掉,但是IFTTT的GitHub服務並沒有提供close Issue的接口,於是乎我們就只有利用IFTTT新推出的Maker自己創建一個,即將Instapaper規劃作為一個IF trigger,然後用Maker發出一個Web請求,可以是GET、PUT、POST、HEAD、DELETE、PATCH或者OPTIONS之中的任何一種,你甚至還可以制定Content Type和Body。

Serverless實戰:打造個人閱讀追蹤系統

app.get('/reading', (req, res) => { const { GITHUB_ACCESS_TOKEN } = req.webtaskContext.secrets const title = req.query.title let keyword = encodeURIComponent(title.replace(/\s/g, '+'))fetch(`https://api.github.com/search/issues?q=${keyword}%20repo:jimmylv/reading`) .then(data => { if (data.total_count > 0) { data.items.forEach(({ url, html_url }) => fetch(`${url}?access_token=${GITHUB_ACCESS_TOKEN}`, { method: 'PATCH', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ state: 'closed' }), }) } })}

上述代碼就可以用於處理IFTTT Marker所發送的GET請求,我們從query參數中取到文章標題之後再去搜索相對應的Issues,再通過GitHub API將其關閉。

而與此同時,我們在文章的閱讀過程中,有時候也會想要對文章中的亮點部分進行高亮,甚至添加自己的一些想法和總結,那我們也可以用IFTTT Marker和Webtask的套路添加至GitHub Issues的comments當中。具體的詳細代碼就不貼了,更多內容都已經放在我的GitHub上:JimmyLv/demo.serverless-mern,與此同時我的閱讀列表也公開在GitHub上:Issues · JimmyLv/reading,歡迎圍觀。

總結與後續計劃

隨著時間的推移,日常你只需要在Instapaper添加並閱讀文章即可,而背後利用Serverless所搭建的整套閱讀追蹤系統將會任勞任怨的幫你記錄下所有的蹤跡和筆記,你只需要在特定的時候定期review、分析閱讀的效果與預測效果,與此同時結合自己的時間統計系統,持續不斷地改進自己的閱讀目標與閱讀計劃。

Serverless實戰:打造個人閱讀追蹤系統

最後再來考慮一下後續計劃,比如說我現在只是簡單把Instapaper中高亮部分和閱讀筆記作為評論放到GitHub的comments裡面,但是最終我需要把它收藏到自己的個人知識庫即Diigo,這也是可以通過API自動實現的,以及最終需要被刻意記憶的部分還需要與Tinycards或者QuizletAPI相集成,對抗艾賓浩斯遺忘曲線。

與此同時,還需要根據文章類型和難易程度具體劃分一下估點,而不是現在簡簡單單的1點,比如說Instapaper也有根據字數來預測的閱讀分鐘數,以及根據中文或英文、技術或雞湯等不同種類文章閱讀難度進行區分,從而使整套追蹤系統更具有效性與參考性。

文/ThoughtWorks呂靖

相關推薦

推薦中...