github
https://bitbucket.org/rubyf2e/2025-laravel-etl-project/src/main/
API 服務提供:
1. 在指定的時間和星期幾列出所有開放的藥局
https://rubyworks.site/2025-laravel-etl-project/public/api/pharmacies?open_at=08:00&week_day=Mon&show_pharmacy_masks=1
2. 列出特定藥局銷售的所有口罩,並按名稱或價格排序(ASC升序)
https://rubyworks.site/2025-laravel-etl-project/public/api/pharmacies/3/masks?sort=price&order=ASC
3. 列出口罩產品數量多於或少於 X 並且價格在某個範圍內的藥局
https://rubyworks.site/2025-laravel-etl-project/public/api/pharmacies?mask_count=1&mask_count_op=le&price_range_start=10.00&price_range_end=50.00&show_pharmacy_masks=1
4. 根據總交易金額,在特定日期範圍內列出交易金額最高的 X 位用戶
https://rubyworks.site/2025-laravel-etl-project/public/api/reports/top_members?date_range_start=2021-01-01&date_range_end=2022-03-02&num=2&show_total_transaction_revenue=1&show_orders=1
5. 在特定日期範圍內計算總口罩銷量和交易總金額(美元)
https://rubyworks.site/2025-laravel-etl-project/public/api/reports/statistics?date_range_start=2021-01-01&date_range_end=2022-03-02
6. 根據名稱搜索藥局或口罩,並按與搜索詞的相關性排序
https://rubyworks.site/2025-laravel-etl-project/public/api/pharmacy_masks?keyword=True
更新用戶與藥局的現金餘額與庫存的程式設計
執行購買流程,並確保交易為原子性(atomic transaction),更新用戶與藥局的現金餘額與庫存。
當藥局系統有訂單成立時會更新自家系統的資料庫,經過程式處理後 ftp 定期更新 /laravel/storage/data/ 底下的 pharmacies.json 和 users.json
此專案會用排程檢視 pharmacies.json 和 users.json 異動時間,如有異動才更新資料庫相關資料表 並在 etl_json_data_histories 資料表儲存更新紀錄避免重複更新,用 Queue 排程並加上 Atomic Locks 避免重複執行 在呼叫 api 查詢時也會執行同樣動作,但是會等到該 Queue 執行完才會載入資料,方為即時資料
php artisan app:etl-json-data-update {type : pharmacies or users} 指令可以達到同樣的效果
注意事項: users.json 資料更新時會判斷口罩訂單,該藥局口罩如果交易時間是一樣的,則價格不同才會更新,如果交易時間比資料庫的資料更早以前的則不更新,只更新近期的,避免錯亂 pharmacies.json 資料更新時如果價格有異動,會儲存價格異動紀錄在 pharmacy_masks_price_histories 資料表裡以供查詢
Chatgpt 評語
這個流程屬於 ETL (Extract, Transform, Load),但它比較偏向 近乎即時 (Near Real-Time) 的 ETL,而不是傳統的批次處理 (Batch Processing) 的 ETL。
根據流程來看,它符合 ETL 的基本步驟:
1. Extract(提取)
從 pharmacies.json 和 users.json 讀取最新資料。
使用 Laravel 的 Storage::lastModified() 來判斷是否有異動。
2. Transform(轉換)
過濾掉不需要更新的資料(例如:舊的 users.json 口罩訂單不更新)。
檢查價格是否異動,並決定是否寫入 pharmacy_masks_price_histories。
計算用戶餘額變動,確保交易邏輯正確。
3. Load(載入)
資料庫更新:
更新 users 表的用戶餘額。
更新 pharmacies 表的庫存與價格。
紀錄變更至 etl_json_data_histories 避免重複更新。
交易使用 DB::transaction() 確保原子性。
這樣設計的好處
✅ 降低 DB 負載(透過 JSON 緩存 + 排程批次更新)
✅ 確保交易原子性(DB Transaction + Queue + Redis Lock)
✅ 符合供需影響價格的市場機制(購買 → 價格變動)
✅ 可追溯價格變化(歷史記錄,避免異常變動)
ETL 的變種
傳統的 ETL 流程通常是:
在固定時間點跑一次(例如每天凌晨)。
透過大型數據倉儲 (Data Warehouse) 來處理轉換與分析。
而這個專案的 ETL 不同點 在於:
✅ 近乎即時處理:透過 Queue + Redis Atomic Lock 確保新資料進來時能迅速更新。
✅ 觸發式 ETL:不是固定時間執行,而是當檔案變動時觸發更新。
✅ 資料一致性要求高:考慮交易原子性,避免並發更新導致錯誤。
所以,雖然這是 ETL,但更像是 增量式 (Incremental) 和 近乎即時 (Near Real-Time) 的 ETL,而不是傳統的批次 ETL。