Thursday, June 29, 2023

background job queue library of Clojure

先談簡易的結論:
1. 想搭配 Postgres 使用 => 用 Proletarian
2. 想搭配 Redis 使用 => 用 Jesque 
3. 都不滿意的話,就再去 Java 的 ecosystem 找,總會找到勉強可以接受的 library 來用。


其實這個問題也滿多人討論的:
比方說,這一篇:有人在 ClojureVerse 詢問,在 Clojure 世界裡,相當於 Ruby 的 sidekiq 是什麼?


< 技術決策的理論 >

如果是我來思考這個議題的話,兩個重點:

1. Deployment 是否省事?
2. Library 提供給我的 interface 是否好用?直覺?不會太多儀式性的 code 要寫

DevOps 要省事的話,常常會不想用 Redis 。可以參考這一篇


由於使用 Redis 做為 durable storage 的 library 疑似發展比較久、也比較成熟,有可能反而是 Redis 組別的 Library interface 比較好用。類似的觀點來自這邊


< 技術決策的實務 >

Proletarian 與 Jesque 我都用過,library 給的感覺嘛,好像也沒有差很多。大概還是優先選 Proletarian ,畢竟我本人很怕 Deploy 那一段的 complexity。

Postgres 的一些好用的功能:Auth, jsonb, validation on json, ltree, Expression based index

1. Postgres 可以利用 pg_crypto 這個 extension ,快速地做出 Authentication。參考這篇

2. Postgres 的 jsonb column ,這可以用來快速地搬移 Firestore  到 Postgres 。參考這篇

3. Postgres 可以對 json column 加上 schema validation。參考這篇

4. Postgres 可以利用 ltree 這個 extension 來記錄 tree 類型的資料結構。參考這篇

5. Postgres 也支援 expression based unique index 。參考這篇

第五項多加一些說明:

在 Clojure 的世界,我想找一個簡單易用的 worker queue ,但是又懶得架 Redis,所以 Proletarian 是選項之一。(Proletarian 是一個輕薄的 job queue library on top of Postgres)

然而,使用 Proletarian 也是有一些缺點:

- 比方說,job 的 payload 會被 Proletarian library 先做成 Transit ,再轉換成 text 來儲存。這時,如果你要放進 worker queue 裡的 job ,你想要對其施加一些 unique constriaint 時,該怎麼做呢?


之前我想不出做法,因為整個 payload 都被先打包成一包做成 text ,總覺得 unique constraint 加不上去。無奈之下,只好在 application layer 去實作這個 unique constraint 的檢查,實在有夠難寫。


最近研究 Postgres 才發現,有一個很犯規的東西叫做 expression based UNIQUE INDEX。用了這個的話,就可以輕易地對 text 或是 json 之類的資料的部分集合,加上 unique constraint了。