3/22

  • 修好 new printing 讓他可以用

  • 取代(? papercut

  • by PM 大大 willychan: 好好寫後端跟 test 確定他不會出大問題,可能要做到什麼當 DB 掛掉要自動切到備用 DB 之類的

    • 先不管,、做出可以動的東西再說

  • 界面應該仿製 papercut

  • API

    • 登入:使用者輸入帳號密碼驗證

      • 要傳的 json:

        • json {status: string, cookie: string, error_reason: string}

      • (後端)可能需要 LDAP 給一個 API 做驗證(?

        • password

    • query user 餘額

      • 直接檢查 cookie session ?

    • 上傳檔案並列印

      • 檢查餘額(?

      • 上傳多個檔案

      • 單/雙面列印

      • 不檢查格式,等列印結果有問題再報錯

    • 讓 UI/UX 可以 query status

      • GET

  • [ ] ubuntu 裡面開一個小的 windows vm 負責列印

  • ubuntu backend -> windows VM -> modify driver info -> print

工作分配

  • 陳陽天:ubuntu backend: 處理跟 UI/UX 對接、LDAP 驗證

  • 尤薪綸:ubuntu backend: 跟 windows VM 對接

  • 張秉中:很多個(? windows VM :修改 driver info 讓他可以列印,並且要取得列印結果回傳,可能會需要用到密碼明文

    • 先不管,去問 wiwi papercut 怎麼做到的

      • ubuntu 跟 windows 之間 接一個 RSA?

      • 或者是再 windows VM 裡面 query user 的 password 明文

TODO

  • 定開會時間?這週先不開會,這週先搞清楚狀況下週再開會

  • 叫 willychan 多開幾個語音頻道給各組用


3/23 with UI/UX

他們會實作的頁面

  • 登入

  • 上傳 pdf

  • 看目前那份文件的 status

3/30 會議

UI/UX 對接:高翊恩

進度報告

  • [https://hackmd.io/@uuuu2024/Sy5Jhy_jex](ubuntu 後端 -> windows)

  • 把 windows 的自動化研究好了,可以用 auto hot key 跟 summatra pdf 做到從 cli 做事 -> 剩接到 server.py 上

  • Django 與 pypdf API

  • 給出 前端的 API 細節

TODO

  • 還要處理 job queue 從 windows 到 ubuntu 的 API 要回傳什麼(或 ubuntu 要給我什麼?)

  • 好欸 ubuntu 後端可以用 pypdf 把 pdf 先接起來,windows 那邊不用處理 XD

  • windows 那邊先當作只上傳單一檔案

By wiwi 的列印流程(new printing)

(前端 -> 後端帳戶驗證)-> windows 印表機 -> new printing server (需要 jump.csie.ntu.edu.tw 才可存取) 驗證餘額等等 -> 通過之後到印表機

TODO: API 細項

https://hackmd.io/@uuuu2024/Sy5Jhy_jex

  • API

    • 登入(GET/POST “接口?”):使用者輸入帳號密碼驗證

      • 要傳的 json:

        • json {status: string, cookie: string, error_reason: string}

      • (後端)可能需要 LDAP 給一個 API 做驗證(?

        • password

    • query user 餘額

      • 直接檢查 cookie session ?

    • 上傳檔案並列印

      • 檢查餘額(?

      • 上傳多個檔案

      • 單/雙面列印

      • 不檢查格式,等列印結果有問題再報錯

    • 讓 UI/UX 可以 query status

      • GET

下週挪到週三 16:00 ~17:00?

之後還要幹嘛?

  • 張秉中趕快給出後端需要的東西,這樣中間才可以做事

4/8(? 會議

  • ubuntu 後端對接 windows: 每個 job 用一個 int 表示,windows 只負則處理列印部份(需要 windows VM 才能做的事情們),剩下紀錄用戶/餘額查詢都在 ubuntu 做?

  • 目前 Ariel 的身份驗證是爛的 QAQ 基本上帳密亂打都會過

    • 更:wiwi 修好了

  • Windows 目前回傳 printed 的意思其實是 submit 給印表機了,並不代表已經印好了(驗證沒過也會回傳 printed,所以印表機回傳不太可信)

  • 前端工作:

    • LDAP 出來了可以去接身份驗證了

    • 餘額的部份張秉中會去找 NASA 借 jump.csie.ntu.edu.tw 到 new printing server 看看怎麼辦

    • 前端大致上高翊恩寫完了 >w< ,應該剩下把網頁跟後端接起來等等的工作

  • ubuntu 到 windows:

    • 目前有的功能只有測過列印而已,但是應該要有 query 工作們的功能(?可能會再需要幾個 grpc 的接口去處理

    • 總之 jobs 查詢的 code 只需要接口就可以了

API 流程清單

  • 列印:前端 -> ubuntu -> windows (回傳 job id(int) ubuntu)

  • 餘額:前端 -> ubuntu -> new printing server

  • 登入驗證:前端 -> ubuntu -> LDAP server

  • 查詢列印進度(列印完應該會 redirect 過來):前端 -> ubuntu -> windows (用 job id 查)

TODO

  • ubuntu -> sender

    • 把 grpc 包成 python library 讓 django server 去 call

  • ubuntu -> ldap

  • ubuntu -> 前端

  • ubuntu -> new printer server

    • 把 ubuntu 用 VPN 關到 jump.csie 中

  • ubuntu -> windows

    • Jobs(整個清單)

      • 先不做單一 user 做整個清單,到時候要的話再改

    • Job(單一工作)

      • 給 windows 一個 job id ,回傳是否 printed

Deadline

  • 4/18 以前把 grpc 接好、windows 把 jobs 的查詢 API 弄好

  • 4/19 前完全做完

Demo 目標

  • login

  • 單一檔案,可以選單雙面

開會時間

改成週三下午 16:00~17:00

4/15 進度追蹤

Windows server

  • 改成不驗證身份了,因為餘額系統接不出來所以目前直接在 ubuntu 架一個餘額的 server 測試(目前是用 superuser 過)

  • 所以在 ubuntu 裡面有蓋好測試用的 sqlite3 了,應該 import 一下就可以用了

TODO

  • 方案 1 :總之可能改成一定得過前端?拔掉直接戳印表機的方法

  • 方案 2 :想辦法 reverse/生出跟 new printing server 同步的方式(用bs4 直接戳會需要戳 $10^4$ 頁的 UI 找人,不然就是要找出 db 在哪裡戳他)

TODO

Gprc TODO

  • windows server query job

  • testing

UIUX Backend

  • 接 LDAP

  • 接 grpc 到 windows

  • 接 database 餘額

Windows

  • latency:主要的延遲來源其實是 sumantrapdf.exe 執行時間,之後換個方法試試看(應該不會影響到其他前端運作)

進度規劃

  • 趕進度

  • 如果接前端 web 來不及,就改成 DEMO 直接 curl ubuntu

  • 確認東西可以從 uiux_backend/ 這層 import (不然到時候還要修會很麻煩

4/29

工作整理與分配

基本功能

  • Windows 後端 (by 張秉中)

    • 把 sumatrapdf 換掉(問題:winget 抓的東西不知道到哪裡了)

  • Ubuntu 後端

    • GET /api/print 會拿到 username 跟餘額

      • 改名叫 /api/me

    • 餘額系統換一下可以 concurrent 的,用 sqlite 太蠢了(by 張秉中)

      • 餘額系統可能換成 postgresql

    • 增加上傳多個 pdf 的功能(by 陳陽天)

      • Pdf 切割合併

    • 增加 /api/jobs/my 的功能(by 陳陽天)

      • 會需要新增一個 database 儲存 printing submissions

      • django API

    • admin(by 陳陽天)

      • 修改 DB 餘額資料:django 那裡要驗證身份

      • 也需要 database 紀錄 admin 身份

  • 前端(by 高翊恩)

    • 修好前端 username 只會顯示 miku 的問題

    • 需要多寫一個 /jobs/my 的頁面,顯示那個人自己的 submission(先不做動態更新,手動刷新就好)

    • 可以寫一個 /admin 的界面可以看到 users,還有查用戶餘額

    • 可能會需要 /admin/users 跟 /admin/jobs

      • 查特定使用者並修改餘額

  • nginx (by 張秉中)

    • 把 reverse proxy 接好,newprinting.org/ 接到前端

HA

碰到 HA 要小心 race condition

  • Ubuntu 後端

    • 用 gunicorn 包起來,在後端開兩三個 instance(尤薪綸)

      • 問題:session 跨 instance 會失效

        • 蓋一個 redis db 給他們 cache?

      • 問題:餘額系統 race condition?(by 張秉中)

        • 寫的時候要注意用 postgresql 的 atomic operations

    • 跟 windows 對接(尤薪綸)

      • 用多個 grpc 對接 windows server(s)

      • JobID 要改用其他方法儲存,像是 IP_port_jobid

      • 怎麼隨便選 grpc ?

    • 查 job 狀態除非該 job 不是 in queue 不然直接問 DB 就好

    • 每天低峰時間(早上 4:00 之類的)跟所有 windows server sync

  • Windows 後端

    • 好解決,直接多個 grpc server (python3 server.py {port} {printer_name}

      • PrinterUtils.py: 張秉中

      • server.py :尤薪綸

    • 多個 driver 應該已經解決了

  • Nginx(by 張秉中)

    • 設定要改,盡量讓同一個 IP 來的 client 接到同一個 api

    • load balancing 要開

可能不重要

  • containerize

死線

  • HA 跟基本功能開 branch 做事

  • DSA 軟工死線:三週後(?

  • OS mp3:5/11

5/6 開會

記得寫測試

關於 HA

  • PDFtoPrinter 裝好了,但感覺效果沒有好多少

    • 宣告死亡

  • 其實是要做讓東西倒掉之後還可以動

    • 但目前的架構應該是好的,因為這樣我們機器可以倒很多臺才會出事

  • gRPC 改成 single thread ,跟印表機 driver 一對一

  • printerUtils 可能會稍微改一下接口,會用一個 class 包起來

    • (張秉中)改 submit_print_job_bytes()

TODO after 機率小考

  • Testing

  • Django (陳陽天)

    • 接到 Redis DB

    • Docker

    • 傳多個檔案

    • 寫 api/jobs/my 查自己的 submission

    • Django Log

    • 查 admin/新增 admin(張秉中)

    • 跟 Scheduler 對接的 gRPC(尤薪綸)

  • DB(張秉中)

    • HA

    • 蓋 Table

  • Scheduler(尤薪綸)

    • 開兩個服務

      • print

        • 往後送到 windows 的 print port

      • query

        • 往後送到 windows 的 query port

      • 更新 DB 中的 submission

  • DB

    • Redis

    • Postgres

    • balance (蓋好了)

    • admin

      • username

    • submission

      • uid: string

      • wid: string

      • status: string

      • time: string

      • pages: int

  • Nginx

    • 需要 Django 做完 Docker ?

5/13

新的流程(refund):

  • scheduler 如果送到windows失敗,他會retry最多3次,如果還是失敗

  • scheduler去submission table把status改成failed且附上reason(string)

  • scheduler會去call django的refund服務並傳入id1,再交給django去查balance db、update balance db(把錢加回去)

  • django去寫一筆transaction_log紀錄

新的流程(to django)

  • 需要django先去db submission table新增一個類似skeleton的東西(wid還不能填入),然後先把status(新的field)設為pending

  • 用grpc傳給scheduler,scheduler這時候是grpc server

  • scheduler有一個獨立的single worker thread,他會去卡在conditional variable上,平常sleep wait for pending submission

  • event(pending submission) occur的時候會醒來

  • 另外他定期5分鐘會期來scan db submission table,確保沒有因為grpc失敗產生的orphan pending submission

TODO

  • DB(張秉中)

    • 開始做 HA

      • redis 的 sentinel 應該好了

      • postgres 可能用 master/slave 備份

    • 開 transaction table 跟改一下 submission table

  • Django(陳陽天)

    • 接 redis DB

    • Docker

    • 加 /api/refund

    • 跟 scheduler 對接(陳陽天跟尤薪綸自己接起來)

      • api/jobs/my

  • Scheduler

    • 給出讓 django 戳的 api

  • FE

    • 測試前端能不能動

5/20 Meeting

下週之前的 TODO

  • DB(張秉中)

    • 要兩台 VM 之後做 postgres HA

    • 改一下 submission table

      • 加 money 欄位在 np_submission

  • Django(尤薪綸)

    • 加 /api/refund

    • 跟 scheduler 對接(陳陽天跟尤薪綸自己接起來)

      • api/jobs/my

    • 給出讓 django 戳的 api

    • Docker

  • 研究 CUPS(陳陽天)

  • 跟 hardware 組處理 logging

5/27 Meeting

TODO

週五前:/api/submissions/(張秉中) 週六前: scheduler->windows(尤薪綸) 週日前:containerize(陳陽天)

Document

架構圖 image

從 nginx 開始左到右依序為 nginx, django, scheduler, DB, windows server, Printer

Nginx

  • 使用 newprinting.csie.org 做 domain name

  • 做 load balancing 將多個前端 request 分派給多台 django 去處理

  • 在做 load balancing 的同時去監控是否有後端死亡,有的話要重啟

  • location /, location /assets 等等 forward 到前端

  • location /api, /static 等等後端物品 forward 到後端(這部份會需要做 load balancing)

Django

  • 接收後端 request

    • /api/login:直接在 django 處理之後回傳

    • /api/me:去 DB 的 balance table 查詢餘額之後回傳(用 cookie 檢查)

    • /api/admin:去 DB 的 admin table 檢查

    • /api/jobs/my:對 scheduler 發送 print query 查詢對應 user 的工作(via gRPC)

    • /api/print:先用 pypdf 數頁數並扣款之後,將對應的多個 file 在 django 用 pypdf 將檔案合併成一個之後傳送一個 print request 給 scheduler ,並等待 scheduler 回傳一個 job ID(via gRPC)

  • 由於會開啟多個 django instance ,因此為了讓使用者的 session 可以共享(不同 django 的 session 不一定可共用),需要開啟一個 redis DB 來將所有的 cookie 紀錄,並統一到 redis 查詢

Redis

  • redis 部份應該會用 sentinel 進行,但是因為目前全部用 docker 做所以 docker-compose 設定要修改,不能讓他直接給 django domain name 而是要給 localhost:port

Scheduler

  • 主要功能為降低送 request 到印表機的延遲,並把那部份變為 async

  • 紀錄一個 printing queue 並依序發送給 windows server

    • 在發送的同時先回應 django server 一個 id1,也就是 django 端認知到的 jobID

  • 每一個 print job 會是一個 jobid pairt (id1, id2),其中 id1 是 django 端認為的 ID ,而 id2 則是 scheduler 跟 windows 端查詢用的 id

    • 這樣設計的主因是因為 id2 只有在經過 windows server 送出 printer request 之後才可以取得,因此在 async 的情況下前端會需要一個暫時的 id

  • 收到 print job 的 workflow

    • 取得一個 id1

    • 將 (id1, -1, time.now())放進 DB 中

    • 將工作放進 print queue

    • 回傳 id1 到 django

  • 收到 get print job 的 workflow

    • 在 DB 中 query id1 或 user

    • 如果 id2 = -1 ,那就 return “pending”

    • 如果 id2 != -1

      • 如果 status=in queue 或 pending 就往 windows server query status

      • 否則直接回傳 status

  • 透過 gRPC 接收來自 django 的各個 request ,並且將需要到 windows server 的 request 用 gRPC 送出

DB

  • 基本上就是一個 postgres DB,table 有 balance, admin, submissions

Balance

  • 由於在 django 驗證過身份了,所以到這裡的 user 一定都是合法 user

  • 如果 user 不存在,就建立新 entry 並初始化餘額

  • 如果 user 存在就直接查詢餘額

  • (username: string, balance: int)

  • 只會由 django 存取

Admin

  • 只需要存 admin usernames

  • (username: string)

  • 只會由 django 存取

Submissions

  • 紀錄所有列印 submission

  • 只會由 scheduler 存取

  • (uid, wid, username, printer, pages, status, created_at)

Windows Server

  • 目前應該會開兩個 instance ,一個處理發送 print request ,另一個處理 query 們(因為 query 很快)

  • 從 gRPC 接收檔案跟 request 並發到 printer

  • 流程:gRPC -> windows printerUtils -> sumatrapdf.exe 送出列印 request -> 取得 jobID -> return