基於Elixir使用Phoenix建立CQRS/ES應用
該文介紹了 Segment Challenge 是如何使用命令查詢責任分離CQRS和事件溯源模式建立其Web應用。
使用Elixir遵循領域驅動設計使用CQRS非常自然,包括使用Erlang的Actor模型,聚合根非常適合Elixir中的Process,使用不可變的訊息驅動互動,彼此隔離並行執行,透過自己的訊息mailbox實現訪問控制。
關於Segment Challenge背景:
如果你是一個熱衷於騎腳踏車的喜歡運動的人,那麼你會知道Strava。它是一個運動者的社交網路。記錄了他們的騎乘和跑步日誌,並將日誌上傳到該網站。
Strava使用者根據路線中一段段建立記錄分段的。例如,一個記錄段包括爬上一座山;從底部開始爬並在頂部完成。每個記錄段都有自己的排行榜。顯示了已經跑過它的每個運動員的排名。最快的人是山的國王(KOM),最快的女人是山的女王(QOM)。運動員可以與其他沿著相同路線運動的Strava使用者進行比較。
這種分段挑戰允許運動員為腳踏車俱樂部及其成員建立比賽。每個月使用不同的Strava段。基於每個運動員在階段結束時的位置來累積積分。該網站使用Strava的API來獲取俱樂部成員的分段成績。排列成績,並在每個階段結束時公佈他們的積分。這種方式替換了在電子表格中手動跟蹤此類資訊的繁瑣。
該網站是完全自助服務。任何註冊的Strava使用者都可以為他們所屬的腳踏車俱樂部建立和主持挑戰。它在2016年年底部署,現在正在為三個地方俱樂部舉辦積極的挑戰。
Segment Challenge這個聚合根是需要來跟蹤每個分段挑戰,稱為Challenge,其有公開命令方法create_challenge接受挑戰的狀態和一個命令,返回零或一個或多個領域事件。
聚合根必須保護自己防止外部命令導致內部不變性的破壞,比如,試圖啟動一個挑戰,但是沒有被批准,將返回錯誤,模式匹配在這裡用於驗證聚集體的狀態,一個有限狀態機可正規化聚合根內部的狀態改變。
更多詳細開發步驟和說明見原文:
使用Elixir遵循領域驅動設計使用CQRS非常自然,包括使用Erlang的Actor模型,聚合根非常適合Elixir中的Process,使用不可變的訊息驅動互動,彼此隔離並行執行,透過自己的訊息mailbox實現訪問控制。
關於Segment Challenge背景:
如果你是一個熱衷於騎腳踏車的喜歡運動的人,那麼你會知道Strava。它是一個運動者的社交網路。記錄了他們的騎乘和跑步日誌,並將日誌上傳到該網站。
Strava使用者根據路線中一段段建立記錄分段的。例如,一個記錄段包括爬上一座山;從底部開始爬並在頂部完成。每個記錄段都有自己的排行榜。顯示了已經跑過它的每個運動員的排名。最快的人是山的國王(KOM),最快的女人是山的女王(QOM)。運動員可以與其他沿著相同路線運動的Strava使用者進行比較。
這種分段挑戰允許運動員為腳踏車俱樂部及其成員建立比賽。每個月使用不同的Strava段。基於每個運動員在階段結束時的位置來累積積分。該網站使用Strava的API來獲取俱樂部成員的分段成績。排列成績,並在每個階段結束時公佈他們的積分。這種方式替換了在電子表格中手動跟蹤此類資訊的繁瑣。
該網站是完全自助服務。任何註冊的Strava使用者都可以為他們所屬的腳踏車俱樂部建立和主持挑戰。它在2016年年底部署,現在正在為三個地方俱樂部舉辦積極的挑戰。
Segment Challenge這個聚合根是需要來跟蹤每個分段挑戰,稱為Challenge,其有公開命令方法create_challenge接受挑戰的狀態和一個命令,返回零或一個或多個領域事件。
聚合根必須保護自己防止外部命令導致內部不變性的破壞,比如,試圖啟動一個挑戰,但是沒有被批准,將返回錯誤,模式匹配在這裡用於驗證聚集體的狀態,一個有限狀態機可正規化聚合根內部的狀態改變。
defmodule SegmentChallenge.Challenges.Challenge do @moduledoc """ Challenges are multi-stage competitions, hosted by a club. Athletes compete every month during the challenge to set the fastest time for the current stage. """ defstruct [ challenge_uuid: nil, name: nil, description: nil, start_date: nil, start_date_local: nil, challenge_state: nil, # ... ] alias SegmentChallenge.Commands.{ CreateChallenge, IncludeCompetitorsInChallenge, HostChallenge, StartChallenge, EndChallenge, } alias SegmentChallenge.Events.{ ChallengeCreated, CompetitorsJoinedChallenge, ChallengeHosted, ChallengeStarted, ChallengeEnded, } alias SegmentChallenge.Challenges.Challenge @doc """ Create a new challenge """ def create_challenge(challenge, create_challenge) def create_challenge(%Challenge{challenge_state: nil}, %CreateChallenge{} = create_challenge) do %ChallengeCreated{ challenge_uuid: create_challenge.challenge_uuid, name: create_challenge.name, description: create_challenge.description, # ... } end def create_challenge(%Challenge{}, %CreateChallenge{}), do: {:error, :challenge_already_created} @doc """ Start the challenge, making it active """ def start_challenge(challenge, start_challenge) def start_challenge(%Challenge{challenge_uuid: challenge_uuid, challenge_state: :approved} = challenge, %StartChallenge{}) do %ChallengeStarted{ challenge_uuid: challenge_uuid, start_date: challenge.start_date, start_date_local: challenge.start_date_local, } end def start_challenge(%Challenge{}, %StartChallenge{}), do: {:error, :challenge_not_approved} def apply(%Challenge{} = challenge, %ChallengeCreated{challenge_uuid: challenge_uuid, name: name, description: description}) do %Challenge{challenge | challenge_uuid: challenge_uuid, name: name, description: description, challenge_state: :created, # ... } end def apply(%Challenge{} = challenge, %ChallengeStarted{}) do %Challenge{challenge | challenge_state: :active, } end end <p class="indent"> |
更多詳細開發步驟和說明見原文:
Building a CQRS/ES web application in Elixir using
[該貼被banq於2017-01-07 10:49修改過]
相關文章
- Phoenix - 基於Elixir的下一代Web開發框架Web框架
- 使用Akka實現CQRS/ES的原始碼原始碼
- MQTT 在 Elixir 中的應用MQQT
- CQRS+ES專案解析01-Diary.CQRS
- [nodejs/npm] 基於Docker建立Nodejs前端應用NodeJSNPMDocker前端
- 業務建模:CQRS應用場景
- Java的CQRS和事件溯源ES入門:如何從CRUD切換到CQRS/ES - BaeldungJava事件
- hbase與phoenix整合(使用phoenix操作hbase資料)
- 實踐ORM,建立基於Grove的.NET應用程式(二) (轉)ORM
- 輕鬆建立基於 GPT-4 的 AI 原生應用 - DifyGPTAI
- 影像處理的實現與應用(Elixir 版)
- 使用Redis/RabbitMQ/EventStore實現事件溯源CQRS微服務應用 - Aram KoukiaRedisMQ事件微服務
- 使用Knative基於構建、部署、管理serverless應用Server
- ES 應用場景
- [elixir! #0032] 在 elixir 中使用 ets (2) —- 匹配查詢
- Discord CTO 談如何構建500W併發使用者的Elixir應用
- Event Horizon是Go語言的CQRS/ES框架Go框架
- CQRS實用DEMO
- 基於應用程度的系統應用優化優化
- OpenGL ES 框架詳細解析(三) —— 構建用於iOS的OpenGL ES應用程式的清單框架iOS
- 基於COLA架構建立運輸微服務應用和DDD領域建模架構微服務
- .NET遵循CQRS-ES架構的EventFlow的DDD + CQRS + Event-sourcing原始碼架構原始碼
- 如何用SAP WebIDE的Fiori建立嚮導基於ABAP OData service快速建立UI5應用WebIDEUI
- 基於flask的最小的應用Flask
- 基於Dapr的 Azure 容器應用
- [譯] 使用智慧 CSS 基於使用者滾動位置應用樣式CSS
- 使用Spring AI + Redis 建立RAG應用SpringAIRedis
- CQRS模式要好於MVC模型模式MVC模型
- 使用Babel和ES7建立JavaScript模組BabelJavaScript
- Akka-CQRS(0)- 基於akka-cluster的讀寫分離框架,構建gRPC移動應用後端架構框架RPC後端架構
- 基於Axon框架使用Kotlin編寫的ES銀行案例框架Kotlin
- ECommerce Microservices:基於DDD+CQRS的實用電子商務.NET原始碼ROS原始碼
- 基於Flutter的仿微信聊天應用Flutter
- 基於react的影院購票應用React
- 基於Redis分散式BitMap的應用Redis分散式
- 基於lbs服務應用開發
- 基於業務的Web應用框架 SimpleFrameworkWeb框架Framework
- 建立第一個基於Prism框架的WPF應用例項(含原始碼下載)框架原始碼