# prefect overview
基本和`puppemon` 想做的事有關,但複雜很多,機制也不同。
* `prefect` 一樣有 ETL assets 的 idea,只是不像 `dagster` 更強制。
official document 分成
* concept
* 使用前
* how-to
* 基本使用
* advanced
* 完整設定
basic command
* `uv tool install prefect[docker]`
* `uv run python xxx.py` 單次的 run on server. (no deploy, worker...)
## working
* flow 需要 worker 執行
* worker 需要在 work pool 裡
* --> flow 需要指定 work pool。
* `prefect worker start --pool "my-process-pool" --type process` 建立 worker 和 work pool
* 這的 worker 的 process 是 blocking 的。
* worker 和 prefect 的 UI server 無關, prefect 只負責公告 work 存在,實際的執行依賴 worker 自己去 poll then execute。說是 work broker 都可以。
* "distributed execution"
* I actually think this is unnecessary, and will casue problem especially for file storage. 可能變成只能用 cloud DB。
* mount docker volume to NAS
* block e.g. AWS S3, that's why prefect need AWS block。
* `prefect worker` 可以在 `docker-compose.yml` 找隨便容器 called 就好。
* [prefect Workers](https://docs.prefect.io/v3/concepts/workers)
* [How to daemonize worker processes](https://docs.prefect.io/v3/advanced/daemonize-processes)
* `prefect worker start --pool docker-pool --type docker --install-policy always` worker in docker 天生就有sandbox 的能力。
* 綜合來說,只要有**持久化**的需求難度就會上升不少。
## deploy
* `prefect.yaml` 是重點,[How to define deployments with YAML](https://docs.prefect.io/v3/how-to-guides/deployments/prefect-yaml#how-to-define-deployments-with-yaml)
* > Deploying a prefect.yaml without a worker pool in a self-hosted Prefect environment is not possible for standard execution.
* 如果serve only 1 flow, 願意直接執行 python 用 flow.serve 是可以沒有 worker。
* [Static infrastructure](https://docs.prefect.io/v3/concepts/deployments#static-infrastructure)
* 以下主要 以 dynamic infrastructure 為主,也就是需要 work pool。
* build, push, pull, deployment 裡,`pull`, `deployment` 是必要的。
* `pull` defines how Prefect pulls your deployment in remote execution environments.
* `deployements` block define 每一個 deployment
* `prefect deploy --all` 就啟動全部 deployment。
* `work_pool/job_variables` 是所執行的 work pool 的設定
* image 表示 `Execute flow runs within Docker containers`
* `push`
* 能不能在這個階段把 code 上傳到 prefect server?
* `deployed flow` 需要 worker + work flow 才會變成 ready 的狀態。
* `deployed flow` run 以後,才會有 `flow run`(work) 真的執行。甚至是 completed.
* 點擊 quick run 等效 `prefect deployment run 'main/01-getting-started'`
* 注意 deploy 只有保證把 deploy 的事件傳到 prefect server, e.g. 時間、work pool、名字等上傳。不含 腳本 (code)
* 正確設定了話,可以把腳本送到遠端 prefect server 能夠access 的 store e.g. S3 or git。
* 之後腳本會再被 worker 從這些 store,fetch 並執行。worker 所 fetch 的server 取決於 `PREFECT_API_URL` 。
* `prefect init` will show more detail
* 見下 code persistence
### code persistence
code 可存在 S3, git repo.
* [Create the deployment](https://docs.prefect.io/v3/how-to-guides/deployment_infra/docker#create-the-deployment)
* `Automatically bake your code into a Docker image` 是把 code 放在image ,整個推到 dockerhub
* `Automatically build a custom Docker image with a local Dockerfile` 多做一點客制化
* docker based 的 deploy 算是最難保證環境穩定。
* git 是最推薦的方式。
* 也有版本管理。
* 存在 S3 的方法沒怎麼講,理論上在`prefect.yaml` 的 `pull` 設定存code 的位置是可以做到的。
* 好處是在離線環境也能用,且 container 元件數量最少。
#### github
有個很不好的弱點,正在改的code 還沒push。所以 worker pull 的不是正在修改的版本。
當然可以開獨立的 branch,改完再merge。但現在要求的 git branch 目的更像是file storage,而非 source code,就像 `gh-pages`。
--> orphan branch
* [Access flow code stored in a private GitHub repository in a deployment](https://docs-3.prefect.io/integrations/prefect-github#access-flow-code-stored-in-a-private-github-repository-in-a-deployment)
* [The pull action](https://docs.prefect.io/v3/how-to-guides/deployments/prefect-yaml#the-pull-action)
### action
local 開發完成後,可以單靠 github action 就完成 code push。而不需要手動下command deploy to prefect。
* [actions-prefect-deploy](https://github.com/PrefectHQ/actions-prefect-deploy)
* `examples/docker` 是 build 含 prefect cli 的 docker image 並執行 deploy 動作 到 某一 prefect server。
* `examples/simple`, `examples/multi-deployment` 都是 pull from github source then deploy in docker image
## persistent
prefect 的執行,是以 flow based programming 為中心思想。所以它更傾向user 以無狀態,單純靠 parameter pass in 的 方式去寫。
然後 最終結果 及 中間資料則透過 assets 去記錄。declare as assets 則會 自動儲存,不需要明確儲存,且儲存 介質,路徑... 的設定也是由 prefect global 設定。
prefect 內的 logger 也是如此。
其它如果真的需要獨立存檔,建議都直接存進 S3 bucket。
configuration 則if and only if 用 block,可以處理 distributed execution 和 secret 的問題。
[How to persist workflow results](https://docs.prefect.io/v3/advanced/results)
### [Assets](https://docs.prefect.io/v3/concepts/assets)
#### artifacts
### prefect variable
variable 是明碼顯示的,一般是希望多個 workflow 有共同設定時使用。
* [How to share configuration between workflows](https://docs.prefect.io/v3/how-to-guides/configuration/variables)
* [Variables](https://docs.prefect.io/v3/concepts/variables)
### [prefect block](https://docs.prefect.io/v3/concepts/blocks)
* > Prefect blocks store typed **configuration** that can be used across workflows and deployments. The most common use case for blocks is storing credentials used to access external systems such as AWS or GCP.
* block 的用途是**設定**,不要拿來做其它用途。
* 基本是為了 fix "distributed execution",處理**持久化** 的問題時,避免 file system token 之類 secret 寫在 code 裡,且讓secret 能在 worker間共用。
* file system 本身的 resource url 在 worker 間必須具有唯一共通的意思。
* 有 database, Remote File System, [Local File System](https://reference.prefect.io/prefect/filesystems/) ... 界面。
* LocalFileSystem 還是 save on work computer, 基本 only for 暫存檔 `/tmp/`
* RFS 是用 fsspec。沒有 nfs。
* aws s3 --> MinIO
* [boto3-AWS-S3 SDK for Python保姆级入门](https://zhuanlan.zhihu.com/p/539375418)
* aws s3 其實也是像 disk mount,並非魔法。
* 如果 db, MinIO... 之類 service 的 url,在 worker 和 prefect server 間不同,會導致failed。
* 這對 self host 的服務有些問題,LAN 內外可能不同。
* 算是 aws s3 的很難取代的好處。
* 如果 worker & prefect 對 NAS 有不同 mount point,一樣會failed.
* prefect server 應該要有 proxy file system 的能力。才能輕易解決這個問題。要求全體 worker 設定正確很不現實。大部分的 user 只先要簡單的 file system 功能而已。
* 也有對接 3rd service e.g. discord webhook
* [Variables](https://docs.prefect.io/v3/concepts/variables)
* 用來 init global distributed variable, e.g. json
* [ Serverless is a Scam. ](https://dev.to/code42cate/serverless-is-a-scam-5fc0)
* 想要用 `S3Bucket`
* `AwsCredentials` block 可以取 credential,然後再將其設定入 `S3Bucket` 。
* minIO credentials 一樣用 aws credentials 設定,minIO credentials 是
* prefect 也有提供 S3 bucket block,內含 bucket name 的設定。直接 load 就能產生 s3 bucket 供讀寫。
* `prefect` block 的 error message 蠻差的(2025),基本完全看不出來到底是什麼error。
#### secret
Secret 是特別重要的 block,因為要求 prefect support 所有廠商的 token type 不可能,沒必要。甚至是負優化,因為有一堆 class。
json
```python
@dataclass
class DiscordChatExport:
"""
decode from JSON secret block
"""
channel_id: int # DISCORD_CHANNEL_ID
token: str # DISCORD_TOKEN
secret_block = Secret.load("discord-chat-export")
secret_value = secret_block.get()
discord_chat_export = DiscordChatExport(**secret_value)
```
#### custom
* [< Marvin> Can create a Secret storage block in JSON ...](https://linen.prefect.io/t/18883816/ulva73b9p-can-create-a-secret-storage-block-in-json-format-i)
理論上可以custom block,但要事先執行註冊。所以我暫時更傾向簡單的 secret + json
如果有 python 的 regist 加入 .env ,透過 env var 去設定 custom block 了話,可能能夠更簡化。
## flow with 3rd lib
* [ Day14 - LLMOps Pipeline 自動化實戰:用 Prefect 與 Dagster,拯救你的睡眠時間 ](https://ithelp.ithome.com.tw/articles/10389635)
* 這篇的其實還是有很多點沒實作。沒有考慮 host on VPS的情況。
* vector db 應該 outside flow define,因為docker 內部存不了東西。
* 這也對worker 很尷尬,如果workder 不在localhost,且用 embeded db,就會存錯地方。
* that's why need AWS S3
* 這也顯示 純 docker host service 沒啥用 (render.com),正常都至少都要 docker compose 起跳。
* 其實file watch 還是額外一個 process 達成的,這對 deploy 造成一定的影響。
* 但另一個角度就是 可以把 local 的file change trigger 到遠端的 prefect server。更有彈性。
*
## excercise
## what Prefect lack
應用範圍
* 我們把 self host 的 prefect 視為單人
* 單人多個 app
* 或是 一個 project 使用
* 單一 project 希望有統一的界面去 trace 所有相關的工作,尤其是在純內網環境下。
* 不是一個團隊/企業。--> 這當然會需要多租戶。
* 一個 project 多個 app,如果 token, secret 統一是個別 project ,權限均質那沒問題。
* 但實際上,不同團隊做一個 project 很有可能想要控管 source code 的權限,且token 的來源不同。
* 姑且可以假設 flow source code 都是 script,都可以 open。但 token 總是要分開結算的,除非業主開共用 token。
* global 的 secret block 完全就會洩漏 token,缺乏 flow specific secret block。
code push
* worker 需要分佈式 parallel workload 可以理解。
* 但 存 code 也分佈式就很怪了。因為存code 沒有 workload 問題。
* 但不存code 就需要額外的 service 。這無疑增加麻煩。
* 再加上 上面的 global block 設計,額外 service 能夠提昇的效果 也被直接抹平。
直接限制
* [Webhooks](https://docs.prefect.io/v3/concepts/webhooks)
* 只有 prefect cloud 才能用? 這刀太狠。
* [Beyond Scheduling: Event-Driven Flows with Prefect](https://medium.com/the-prefect-blog/beyond-scheduling-event-driven-flows-with-prefect-b072edd06833)
* [Is there a way for self-hosted (not cloud) to use ...](https://linen.prefect.io/t/26890318/is-there-a-way-for-self-hosted-not-cloud-to-use-webhooks-i-g)
* > For self-hosted Prefect, you might need to implement custom solutions to handle webhook-like behavior, such as setting up an external service to listen for events and trigger Prefect flows via the Prefect API.
* [Create Events](https://docs.prefect.io/v3/api-ref/rest-api/server/events/create-events)
* 其他app 直接 call prefect API send event 是否可行?
* 必定是會有割裂的。除非把整個前端重做。
[microservice critical probelm](/9_EKsb8FSxqn1RgQ3xlUBA)
[git based automation](/TvCJnACwTFiTMNiiRYlR6Q)
## TODO
* store deploy code in local S3