發表文章

目前顯示的是 12月, 2023的文章

解剖 .git 資料夾 part. 2 - Blob Object

在前面的 解剖 .git 資料夾 part. 1 - Git Init 我們已經初步瞭解了 .git 資料夾初始化後的結構,但是其中 objects 這個資料夾是空的,就讓我們來看看 執行 git add 後是如何將檔案存放在 objects 資料夾下 Blob object 介紹 由於目前我們還沒有任何的檔案,讓我們新增一個 README.md echo "This is readme." > README.md 再來執行 git add README.md 來將他加到 git 的索引裡,完成後 git status 的結果應該會像下面這樣: On branch master No commits yet Changes to be committed: (use "git rm --cached <file>..." to unstage) new file: README.md 這時候我們可以來看一下 .git/objects 下的檔案長什麼樣子 objects/ ├─ pack/ ├─ info/ └─ 52/ └─ cb6cdb81a64344370c918a301eb153035f915a blob object 內容 這時候多了一個名字叫 52 的資料夾,底下有一個檔案叫 cb6cdb81a64344370c918a301eb153035f915a ,如果你把他打開會發現內容是看不懂的 $ xxd .git/objects/ 52 /cb6cdb81a64344370c918a301eb153035f915a 00000000 : 7801 4 bca c94f 5230 3463 08 c9 c82c 5600 x.K..OR04c...,V. 00000010 : a2a2 d4c4 94 dc 543 d 2 e00 5 ee3 0781 ......T=..^... 原因是所有在 object file 下的檔案都會經過 zlib 壓縮後存放,解壓縮後我們可以看到 object file 的內容是由以下的結構所組成 blob + 空格 + 檔案大小 + zer

Postgres 的跨 client 通知機制:LISTEN / NOTIFY

會想要使用 LISTEN 和 NOTIFY 的情況是想要偵測某個 table 的欄位變動時,想要做一些與 Query 本身無關的事情,例如: 寄送通知信 重算報表 更新快取 雖然這些操作我們都可以在 CPP ( 或其他 DB Client ) 執行完 query 後手動處理,但是如果今天我們 DB 的結構比較複雜,有比較多的 trigger 或是 foreign key 的時候,就會比較難在 CPP 來處理所有需要通知的時機點,或是未來在調整程式時很容易漏掉 相反的如果我們在 postgres trigger 來做這些操作,不但會讓 query 執行變久,也要做額外的錯誤處理 這時候 LISTEN / NOTIFY 會是一個不錯的選項 語法 NOTIFY NOTIFY channel [ , payload ] channel 和 payload 都是字串,只有 channel 是一定要帶的參數 假設我們今天每次登入都會寫紀錄到 login_log 這張 table,當發生 login 失敗時我們要額外寄送通知信,那麼我們就可以直接在這張 table 綁上一個 trigger,判斷是登入失敗時,就直接呼叫 NOTIFY login_failed 'user@example.com' 如此一來我們就送出了一個登入失敗的通知,並且帶有失敗的 email (也就是 payload) 還有另一種方法是執行 SQL function pg_notify(text, text) ,一樣也可以送出 notify NOTIFY 有以下的特性: 只有在 transaction 被 commit 後才會送出 一個 transaction 內重複的 channel, payload 組合只會送出一個 event 一個 transaction 內的 event 會依 NOTFIY 執行的順序送出 LISTEN LISTEN channel 我們只要將想要監聽的事件名稱放在 LISTEN 後面即可 舉例來說,我們想要寄送登入失敗的通知信的話,可以在負責寄信的 process 執行 LISTEN login_failed ,如此一來就可以收到事件 LISTEN 有以下特性: 不會收到執行 LISTEN 之

解剖 .git 資料夾 part. 1 - Git Init

圖片
一直以來使用 git 都覺得很神奇,很好奇 git 到底是怎麼樣將整個程式碼和歷史紀錄都存起來的,因此就決定來看看 .git 資料夾裡面到底是藏了什麼樣的檔案來達成這個目的 這一系列文章的目標就是讓大家可以了解 .git 資料夾下的檔案結構與其內容,說不定在哪天可以幫助我們救回操作失誤的檔案 Git init 萬事起頭難,我們首先來看 .git 資料夾是怎麼被產生的。 一般來說我們都不會自己執行 git init 這個指令,實際上在 github 或是其他 git server 在建立專案的時候就會幫我們在 server 上執行 git init --bare 來在 server 上建立好 .git/ 下所需要的檔案,然後在我們 git clone 的時候被下載到本地端的 .git/ 資料夾下 不過這邊我們就試著在一個空資料夾下來執行 git init 來看看效果,下圖是執行 tree .git 後所看到的檔案內容: (這邊使用的是 git v2.41.0 的版本,不同版本可能行為上會有些許的差別) 接下來就讓我們來看一下每個檔案的用途 config 這個檔案裡面放的是針對此 git repo 的 local 設定,初始的內容如下: [core] repositoryformatversion = 0 filemode = true bare = false logallrefupdates = true 基本上會先用 [] 切出 section,每個 section 會再有很多的 key = value 如果想要調整設定的話會需要用到 git config 這個指令,細節文件請看 這邊 如果我們執行 git config --local alias.co checkout 的話,就會在 alias 這個 section 新增 co = checkout 的設定,打開 .git/config 就會看到: [alias] co = checkout description 這個檔案基本上只會被 git instaweb 這個指令使用到,預設這個指令會用 lighttpd 來快速架一個網站,讓我們有介面可以瀏覽此 git repo 可以