Serverless實戰(zhàn):打造個人閱讀追蹤系統(tǒng)

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

進入互聯(lián)網時代,知識的獲取成本變得前所未有的低廉饵溅,但是無論再好的知識妨退,若是沒有對個人產生價值的話,那也只不過是一種信息噪音而已蜕企。我在《個人知識管理:知識的三種形態(tài)》這篇文章中使用“材料 -> 資料 -> 知識”這樣的路徑來詮釋信息的流通咬荷,如何方便快捷并且有效地收集材料,再將其整理轉化為有價值的個人知識體系結構轻掩,在這個信息極度碎片化的時代變得尤為重要萍丐。而在《去偽存真的知識管理之路》一文中也詳細闡述了如何將網絡上的碎片化文章納入統(tǒng)一的稍后閱讀體系,比如有時候在朋友圈看到一篇好文章放典,但暫時沒時間直接看,或是這篇文章值得再讀一遍基茵,細讀一遍奋构,那么我就會將其存入稍后閱讀工具即Instapaper當中,諸如此類的還有Pocket拱层、收趣等等弥臼。

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

隨著時間的推移,Instapaper里面的文章將會變得越來越多根灯,就像我們在代碼中所注釋的TODO:可能就變成了Never Do径缅,“稍后讀”也是一樣地被廣為詬病:Read it Later=Read Never烙肺。其實我發(fā)現(xiàn)文章堆積的一個永恒痛點就是沒有有效的方式追蹤自己的閱讀需求與能力纳猪,其核心原因在于閱讀的速度趕不上添加的速度。從而沒辦法可視化的評估閱讀進度桃笙、合理安排閱讀計劃氏堤,也就沒辦法給予自己適當?shù)莫剟睿L此以往必然將失去閱讀的動力搏明。

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

可視化Cumulative Flow Diagram

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

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

IFTTT與Serverless架構

那么這是怎么通過APIs來實現(xiàn)的呢敲霍?在真正進入正題之前我們先來簡單介紹一下Serverless架構。Serverless指的是在構建Web應用程序的時候丁存,不用擔心如何配置服務器肩杈,但是這并不意味著應用程序不會在服務器上運行,而是說服務器的管理都可以盡可能地交給相應的云平臺解寝,從而最大程度地減輕開發(fā)人員的部署與配置工作扩然。與之對應的一個名詞可能就是Function As a Service(FAAS),由AWS Lambda這個命名就能想到聋伦,當我們在構建Serverless架構時夫偶,實際上我們是在寫一個個的Function,即函數(shù)而已觉增。

流程化:APIs即服務

首先讓我們來介紹一下IFTTT即if this then that兵拢。通俗的來講,IFTTT的作用就是當一件事情被觸發(fā)時逾礁,能夠執(zhí)行設定好的另一件事卵佛。所謂的「事」,指的是各種應用敞斋、服務之間可以進行有趣的連鎖反應截汪。IFTTT的宗旨是Put the internet to work for you(讓互聯(lián)網為你服務)。用戶可以在IFTTT里設定任何一個你需要的條件植捎,當達成條件時衙解,便會觸發(fā)下一個指定好的動作。它就像是一座神奇的橋梁焰枢,能連接我們日常所用的各種網絡服務蚓峦。

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

初始化Webtask項目

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

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

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

創(chuàng)建項目目錄腾它,添加index.js文件并添加以下內容:

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

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

wt create index

Webtask的上下文綁定

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

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都會在后續(xù)與GitHub和ZenHub APIs交互時被用到。

wt create index --bundle --secret GITHUB_ACCESS_TOKEN=$GITHUB_ACCESS_TOKEN 
--secretZENHUB_ACCESS_TOKEN=$ZENHUB_ACCESS_TOKEN --secret
ZENHUB_ACCESS_TOKEN_V4=$ZENHUB_ACCESS_TOKEN_V4

# ./routes/reading.js
module.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文章后自動創(chuàng)建GitHub Issue

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

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

使用GitHub Webhook 更新Issue的Milestone

所以我們的Webtask就需要處理GitHub Webhook所轉發(fā)的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
    })
  })

}

結合ZenHub的Milestone燃盡圖我們可以清晰地看到剩余閱讀量榨了,并且能夠跟理想中的閱讀速度進行對比煎谍,從而判斷自己什么時候能夠全部讀完所有的文章×耄可能有些小伙伴看到這里會有所疑問呐粘,這些所謂的Story Point是從哪兒來的呢?接下來就要提到我們將要集成的ZenHub API了叔扼。

集成ZenHub API:閱讀可視化

更新Issue的估點和Release

GitHub Issue的任何變動都會觸發(fā)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(() => {
      return 
fetch(`https://api.zenhub.io/v4/reports/release/591dc19e81a6781f839705b9/items/issues?access_token=${ZENHUB_ACCESS_TOKEN_V4}`,
        {
          method: 'POST',

        })
    })
}

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

歸檔Instapaper文章后關閉GitHub Issue

說了這么多与柑,不要忘了整個閱讀系統(tǒng)最最核心的部分依然還是「閱讀」鞍肌!在眾多的稍后閱讀工具中我無比喜愛Instapaper并遲遲沒有轉到Diigo的原因就在于它優(yōu)秀价捧、簡潔丑念、純粹的閱讀體驗,讓人可以專注在閱讀本身這件事情上结蟋,在被Pinterest收購之后更是將所有的諸如全文搜索脯倚、無限高亮/筆記、速讀等Premium功能都變成了免費嵌屎,豈不美哉推正?

那么在完成閱讀歸檔之后,最后一步就是在GitHub當中將Issue關閉掉宝惰,但是IFTTT的GitHub服務并沒有提供close Issue的接口植榕,于是乎我們就只有利用IFTTT新推出的Maker自己創(chuàng)建一個,即將Instapaper規(guī)劃作為一個IF trigger尼夺,然后用Maker發(fā)出一個Web請求尊残,可以是GET、PUT淤堵、POST寝衫、HEAD、DELETE拐邪、PATCH或者OPTIONS之中的任何一種竞端,你甚至還可以制定Content Type和Body。

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所發(fā)送的GET請求庙睡,我們從query參數(shù)中取到文章標題之后再去搜索相對應的Issues事富,再通過GitHub API將其關閉技俐。

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

總結與后續(xù)計劃

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

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

與此同時鸵钝,還需要根據(jù)文章類型和難易程度具體劃分一下估點糙臼,而不是現(xiàn)在簡簡單單的1點,比如說Instapaper也有根據(jù)字數(shù)來預測的閱讀分鐘數(shù)蒋伦,以及根據(jù)中文或英文、技術或雞湯等不同種類文章閱讀難度進行區(qū)分焚鹊,從而使整套追蹤系統(tǒng)更具有效性與參考性痕届。

文/ThoughtWorks呂靖

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市末患,隨后出現(xiàn)的幾起案子研叫,更是在濱河造成了極大的恐慌,老刑警劉巖璧针,帶你破解...
    沈念sama閱讀 221,273評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件嚷炉,死亡現(xiàn)場離奇詭異,居然都是意外死亡探橱,警方通過查閱死者的電腦和手機申屹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評論 3 398
  • 文/潘曉璐 我一進店門绘证,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人哗讥,你說我怎么就攤上這事嚷那。” “怎么了杆煞?”我有些...
    開封第一講書人閱讀 167,709評論 0 360
  • 文/不壞的土叔 我叫張陵魏宽,是天一觀的道長。 經常有香客問我决乎,道長队询,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,520評論 1 296
  • 正文 為了忘掉前任构诚,我火速辦了婚禮蚌斩,結果婚禮上,老公的妹妹穿的比我還像新娘唤反。我一直安慰自己凳寺,他們只是感情好迄损,可當我...
    茶點故事閱讀 68,515評論 6 397
  • 文/花漫 我一把揭開白布黄锤。 她就那樣靜靜地躺著,像睡著了一般潜沦。 火紅的嫁衣襯著肌膚如雪盏阶。 梳的紋絲不亂的頭發(fā)上晒奕,一...
    開封第一講書人閱讀 52,158評論 1 308
  • 那天,我揣著相機與錄音名斟,去河邊找鬼脑慧。 笑死,一個胖子當著我的面吹牛砰盐,可吹牛的內容都是我干的闷袒。 我是一名探鬼主播,決...
    沈念sama閱讀 40,755評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼岩梳,長吁一口氣:“原來是場噩夢啊……” “哼囊骤!你這毒婦竟也來了?” 一聲冷哼從身側響起冀值,我...
    開封第一講書人閱讀 39,660評論 0 276
  • 序言:老撾萬榮一對情侶失蹤也物,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后列疗,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體滑蚯,經...
    沈念sama閱讀 46,203評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,287評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了告材。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片坤次。...
    茶點故事閱讀 40,427評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖创葡,靈堂內的尸體忽然破棺而出浙踢,到底是詐尸還是另有隱情,我是刑警寧澤灿渴,帶...
    沈念sama閱讀 36,122評論 5 349
  • 正文 年R本政府宣布洛波,位于F島的核電站,受9級特大地震影響骚露,放射性物質發(fā)生泄漏蹬挤。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,801評論 3 333
  • 文/蒙蒙 一棘幸、第九天 我趴在偏房一處隱蔽的房頂上張望焰扳。 院中可真熱鬧,春花似錦误续、人聲如沸吨悍。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,272評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽育瓜。三九已至,卻和暖如春栽烂,著一層夾襖步出監(jiān)牢的瞬間躏仇,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評論 1 272
  • 我被黑心中介騙來泰國打工腺办, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人怀喉。 一個月前我還...
    沈念sama閱讀 48,808評論 3 376
  • 正文 我出身青樓估灿,卻偏偏與公主長得像,于是被迫代替她去往敵國和親汗销。 傳聞我的和親對象是個殘疾皇子叠骑,可洞房花燭夜當晚...
    茶點故事閱讀 45,440評論 2 359

推薦閱讀更多精彩內容

  • 國慶放假期間慰丛,偶然發(fā)現(xiàn)這篇文章《Serverless實戰(zhàn):打造個人閱讀追蹤系統(tǒng)》http://insights.t...
    Coding01閱讀 766評論 0 3
  • 文/ThoughtWorks 呂靖 持續(xù)行動粥烁,持續(xù)反思芥永,持續(xù)進步。—— via. 敏捷學習宣言 前言 對時間的敬畏...
    ThoughtWorks閱讀 1,115評論 4 40
  • 用到的組件 1麻捻、通過CocoaPods安裝 2贸毕、第三方類庫安裝 3乡革、第三方服務 友盟社會化分享組件 友盟用戶反饋 ...
    SunnyLeong閱讀 14,625評論 1 180
  • 表情是什么细办,我認為表情就是表現(xiàn)出來的情緒蕾殴。表情可以傳達很多信息笑撞。高興了當然就笑了,難過就哭了钓觉。兩者是相互影響密不可...
    Persistenc_6aea閱讀 125,283評論 2 7
  • 16宿命:用概率思維提高你的勝算 以前的我是風險厭惡者娃殖,不喜歡去冒險,但是人生放棄了冒險议谷,也就放棄了無數(shù)的可能炉爆。 ...
    yichen大刀閱讀 6,056評論 0 4