diff --git a/Eventual2PC.code-workspace b/Eventual2PC.code-workspace
new file mode 100644
index 0000000..876a149
--- /dev/null
+++ b/Eventual2PC.code-workspace
@@ -0,0 +1,8 @@
+{
+ "folders": [
+ {
+ "path": "."
+ }
+ ],
+ "settings": {}
+}
\ No newline at end of file
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..c3f8f68
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,9 @@
+all: pack
+
+pack: build
+ mkdir -p `pwd`/packages
+ dotnet pack -c Release `pwd`/src/Eventual2PC/
+ mv `pwd`/src/Eventual2PC/bin/Release/*.nupkg `pwd`/packages/
+
+build:
+ dotnet build -c Release `pwd`/src/Eventual2PC/
diff --git a/README.md b/README.md
index 199a35a..48ac6b0 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,106 @@
# Eventual2PC
-最终一致性二阶段提交范式,简化多聚合根之间交互事务的实现。
+
+最终一致性二阶段提交范式,简化多聚合根之间交互事务的实现。任何基于cqrs + eda 实现多聚合根最终一致性的框架,都可使用。
+
+## 安装
+
+```
+dotnet add package Eventual2PC
+```
+
+## 范式
+
+### 术语定义
+
+- `Initiator`: 作为事务发起方,它是聚合根
+
+- `Participant`: 作为事务参与方(仅被修改的聚合根,新增的,不会产生业务失败问题),它是聚合根
+
+- `Preparation`: 事务准备,对应一个具体的业务修改动作;同一个 `Participant` 参与多个事务时,应定义多个事务准备
+
+- `Transaction`: 2PC事务,从开始事务,到事务完成,贯穿整个事务生命周期;可以只是一个标识ID(通常使用 `TransactionStarted` 事件的ID),也可以使用代表事务的聚合根(如银行转账的转账事务聚合根)
+
+- `ProcessManager`: CQRS中的概念,作为事务相关消息路由的角色,负责响应 `DomainEvent`、`DomainException` 消息,并发送 `Command` 消息
+
+#### Initiator 事件定义
+
+- `TransactionStarted`: 事务已发起事件
+
+- `PreCommitSucceedParticipantAdded`: 预提交成功的参与者已添加事件
+
+- `PreCommitFailedParticipantAdded`: 预提交失败的参与者已添加事件
+
+- `AllParticipantPreCommitSucceed`: 所有参与者预提交已成功事件
+
+- `AnyParticipantPreCommitFailed`: 任意一个参与者预提交已失败事件
+
+- `CommittedParticipantAdded`: 已提交的参与者已添加事件(Option)
+
+- `RolledbackParticipantAdded`: 已回滚的参与者已添加事件(Option)
+
+- `TransactionCompleted`: 事务已完成事件(Option),并包含是否事务已提交的状态
+
+#### Participant 事件定义
+
+- `PreCommitSucceed`: 预提交已成功事件
+
+- `PreCommitFailed`: 预提交已失败事件(或领域异常消息)
+
+- `Committed`: 已提交事件
+
+- `Rolledback`: 已回滚事件
+
+
+### 规范
+
+- 一个聚合根,可以同时扮演 `Initiator` 和 `Transaction`的角色,如银行转账事务聚合根
+
+- 一个聚合根,可以同时扮演事务A中的 `Participant` 和事务B的 `Initiator`
+
+- 一个 `Participant`,参与多少个事务,需对应定义多少个`Preparation`
+
+- `Participant` 的聚合根实例,允许同时参与多个不同的事务;也可以通过业务代码,在 `PreCommit` 时,判断是否存在其他类型的 `Preparation` 来阻止参与多个事务
+
+- `Initiator` 必须发布事件 `TransactionStarted`、`PreCommitSucceedParticipantAdded`、`PreCommitFailedParticipantAdded`、`AllParticipantPreCommitSucceed`、`AnyParticipantPreCommitFailed`
+
+- `Participant` 必须发布事件 `PreCommitSucceed`、`PreCommitFailed`、`Committed`、`Rolledback`
+
+- 如果需要关注 `Transaction` 是否已完成,则 `Initiator` 需要发布事件 `CommittedParticipantAdded`、`RolledbackParticipantAdded`、`TransactionCompleted`
+
+### 处理流程
+
+- `Initiator` 发布 `TransactionStarted` 事件;
+
+- `ProcessManager` 响应 `TransactionStarted` 事件,并发送 `PreCommit` 命令;
+
+- `Participant` 接受命令 `PreCommit`,如果成功,则发布 `PreCommitSucceed` 事件;如果失败,则发布 `PreCommitFailed` 事件(或领域异常);
+
+- `ProcessManager` 响应 `PreCommitSucceed`,并发送 `AddPreCommitSucceedParticipant` 命令;
+
+- `ProcessManager` 响应 `PreCommitFailed`,并发送 `AddPreCommitFailedParticipant` 命令;
+
+- `Initiator` 接受命令 `AddPreCommitSucceedParticipant`,发布 `PreCommitSucceedParticipantAdded` 事件;如果所有 `Participant` 的 `PreCommit` 都已处理完成,则发布 `AllParticipantPreCommitSucceed` 事件;
+
+- `Initiator` 接受命令 `AddPreCommitFailedParticipant`,发布 `PreCommitFailedParticipantAdded` 事件;如果所有 `Participant` 的 `PreCommit` 都已处理完成,则发布 `AnyParticipantPreCommitFailed` 事件;
+
+- `ProcessManager` 响应 `AllParticipantPreCommitSucceed`,并发送 `Commit` 命令;
+
+- `ProcessManager` 响应 `AnyParticipantPreCommitFailed`,并发送 `Rollback` 命令;
+
+- `Participant` 接受命令 `Commit`,并发布 `Committed` 事件;
+
+- `Participant` 接受命令 `Rollback`,并发布 `Rolledback` 事件;
+
+- `ProcessManager` 响应 `Committed`,并发送 `AddCommittedParticipant` 命令;
+
+- `ProcessManager` 响应 `Rolledback`,并发送 `AddRolledbackParticipant` 命令;
+
+- `Initiator` 接受命令 `AddCommittedParticipant`,发布 `CommittedParticipantAdded` 事件;如果所有 `Participant` 的 `Commit` 都已处理完成,则发布 `TransactionCompleted` 事件;
+
+- `Initiator` 接受命令 `AddRolledbackParticipant`,发布 `RolledbackParticipantAdded` 事件;如果所有 `Participant` 的 `Rolledback` 都已处理完成,则发布 `TransactionCompleted` 事件。
+
+## 发布历史
+
+### 1.0.0(2020/4/25)
+
+- 初始版本
diff --git a/src/Eventual2PC.sln b/src/Eventual2PC.sln
new file mode 100644
index 0000000..88bc75a
--- /dev/null
+++ b/src/Eventual2PC.sln
@@ -0,0 +1,34 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26124.0
+MinimumVisualStudioVersion = 15.0.26124.0
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Eventual2PC", "Eventual2PC\Eventual2PC.csproj", "{FB832C09-5CB6-4A1D-A11D-F7E10D94E333}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {FB832C09-5CB6-4A1D-A11D-F7E10D94E333}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FB832C09-5CB6-4A1D-A11D-F7E10D94E333}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FB832C09-5CB6-4A1D-A11D-F7E10D94E333}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {FB832C09-5CB6-4A1D-A11D-F7E10D94E333}.Debug|x64.Build.0 = Debug|Any CPU
+ {FB832C09-5CB6-4A1D-A11D-F7E10D94E333}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {FB832C09-5CB6-4A1D-A11D-F7E10D94E333}.Debug|x86.Build.0 = Debug|Any CPU
+ {FB832C09-5CB6-4A1D-A11D-F7E10D94E333}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FB832C09-5CB6-4A1D-A11D-F7E10D94E333}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FB832C09-5CB6-4A1D-A11D-F7E10D94E333}.Release|x64.ActiveCfg = Release|Any CPU
+ {FB832C09-5CB6-4A1D-A11D-F7E10D94E333}.Release|x64.Build.0 = Release|Any CPU
+ {FB832C09-5CB6-4A1D-A11D-F7E10D94E333}.Release|x86.ActiveCfg = Release|Any CPU
+ {FB832C09-5CB6-4A1D-A11D-F7E10D94E333}.Release|x86.Build.0 = Release|Any CPU
+ EndGlobalSection
+EndGlobal
diff --git a/src/Eventual2PC/Events/ITransactionInitiatorAllParticipantPreCommitSucceed.cs b/src/Eventual2PC/Events/ITransactionInitiatorAllParticipantPreCommitSucceed.cs
new file mode 100644
index 0000000..d6443a7
--- /dev/null
+++ b/src/Eventual2PC/Events/ITransactionInitiatorAllParticipantPreCommitSucceed.cs
@@ -0,0 +1,26 @@
+using System.Collections.Generic;
+
+namespace Eventual2PC.Events
+{
+ ///
+ /// 事务参与方所有预提交已成功事件接口
+ ///
+ public interface ITransactionInitiatorAllParticipantPreCommitSucceed
+ where TInitiator : class, ITransactionInitiator
+ {
+ ///
+ /// 事务ID
+ ///
+ string TransactionId { get; }
+
+ ///
+ /// 事务类型
+ ///
+ byte TransactionType { get; }
+
+ ///
+ /// 事务参与方信息
+ ///
+ IEnumerable TransactionParticipants { get; }
+ }
+}
diff --git a/src/Eventual2PC/Events/ITransactionInitiatorAnyParticipantPreCommitFailed.cs b/src/Eventual2PC/Events/ITransactionInitiatorAnyParticipantPreCommitFailed.cs
new file mode 100644
index 0000000..badee4b
--- /dev/null
+++ b/src/Eventual2PC/Events/ITransactionInitiatorAnyParticipantPreCommitFailed.cs
@@ -0,0 +1,26 @@
+using System.Collections.Generic;
+
+namespace Eventual2PC.Events
+{
+ ///
+ /// 事务参与方任意一个预提交已失败的事件接口
+ ///
+ public interface ITransactionInitiatorAnyParticipantPreCommitFailed
+ where TInitiator : class, ITransactionInitiator
+ {
+ ///
+ /// 事务ID
+ ///
+ string TransactionId { get; }
+
+ ///
+ /// 事务类型
+ ///
+ byte TransactionType { get; }
+
+ ///
+ /// 成功预提交的事务参与方信息
+ ///
+ IEnumerable PreCommitSucceedTransactionParticipants { get; }
+ }
+}
diff --git a/src/Eventual2PC/Events/ITransactionInitiatorCommittedParticipantAdded.cs b/src/Eventual2PC/Events/ITransactionInitiatorCommittedParticipantAdded.cs
new file mode 100644
index 0000000..2603d37
--- /dev/null
+++ b/src/Eventual2PC/Events/ITransactionInitiatorCommittedParticipantAdded.cs
@@ -0,0 +1,24 @@
+namespace Eventual2PC.Events
+{
+ ///
+ /// 已提交的事务参与方已添加事件接口
+ ///
+ public interface ITransactionInitiatorCommittedParticipantAdded
+ where TInitiator : class, ITransactionInitiator
+ {
+ ///
+ /// 事务ID
+ ///
+ string TransactionId { get; }
+
+ ///
+ /// 事务类型
+ ///
+ byte TransactionType { get; }
+
+ ///
+ /// 事务参与方信息
+ ///
+ TransactionParticipantInfo TransactionParticipant { get; }
+ }
+}
diff --git a/src/Eventual2PC/Events/ITransactionInitiatorPreCommitFailedParticipantAdded.cs b/src/Eventual2PC/Events/ITransactionInitiatorPreCommitFailedParticipantAdded.cs
new file mode 100644
index 0000000..b5bcf3a
--- /dev/null
+++ b/src/Eventual2PC/Events/ITransactionInitiatorPreCommitFailedParticipantAdded.cs
@@ -0,0 +1,24 @@
+namespace Eventual2PC.Events
+{
+ ///
+ /// 预提交失败的事务参与方已添加事件接口
+ ///
+ public interface ITransactionInitiatorPreCommitFailedParticipantAdded
+ where TInitiator : class, ITransactionInitiator
+ {
+ ///
+ /// 事务ID
+ ///
+ string TransactionId { get; }
+
+ ///
+ /// 事务类型
+ ///
+ byte TransactionType { get; }
+
+ ///
+ /// 事务参与方信息
+ ///
+ TransactionParticipantInfo TransactionParticipant { get; }
+ }
+}
diff --git a/src/Eventual2PC/Events/ITransactionInitiatorPreCommitSucceedParticipantAdded.cs b/src/Eventual2PC/Events/ITransactionInitiatorPreCommitSucceedParticipantAdded.cs
new file mode 100644
index 0000000..ef1e6b6
--- /dev/null
+++ b/src/Eventual2PC/Events/ITransactionInitiatorPreCommitSucceedParticipantAdded.cs
@@ -0,0 +1,24 @@
+namespace Eventual2PC.Events
+{
+ ///
+ /// 预提交成功的事务参与方已添加事件接口
+ ///
+ public interface ITransactionInitiatorPreCommitSucceedParticipantAdded
+ where TInitiator : class, ITransactionInitiator
+ {
+ ///
+ /// 事务ID
+ ///
+ string TransactionId { get; }
+
+ ///
+ /// 事务类型
+ ///
+ byte TransactionType { get; }
+
+ ///
+ /// 事务参与方信息
+ ///
+ TransactionParticipantInfo TransactionParticipant { get; }
+ }
+}
diff --git a/src/Eventual2PC/Events/ITransactionInitiatorRolledbackParticipantAdded.cs b/src/Eventual2PC/Events/ITransactionInitiatorRolledbackParticipantAdded.cs
new file mode 100644
index 0000000..cdb8aca
--- /dev/null
+++ b/src/Eventual2PC/Events/ITransactionInitiatorRolledbackParticipantAdded.cs
@@ -0,0 +1,24 @@
+namespace Eventual2PC.Events
+{
+ ///
+ /// 已回滚的事务参与方已添加事件接口
+ ///
+ public interface ITransactionInitiatorRolledbackParticipantAdded
+ where TInitiator : class, ITransactionInitiator
+ {
+ ///
+ /// 事务ID
+ ///
+ string TransactionId { get; }
+
+ ///
+ /// 事务类型
+ ///
+ byte TransactionType { get; }
+
+ ///
+ /// 事务参与方信息
+ ///
+ TransactionParticipantInfo TransactionParticipant { get; }
+ }
+}
diff --git a/src/Eventual2PC/Events/ITransactionInitiatorTransactionCompleted.cs b/src/Eventual2PC/Events/ITransactionInitiatorTransactionCompleted.cs
new file mode 100644
index 0000000..c5045a0
--- /dev/null
+++ b/src/Eventual2PC/Events/ITransactionInitiatorTransactionCompleted.cs
@@ -0,0 +1,24 @@
+namespace Eventual2PC.Events
+{
+ ///
+ /// 事务已完成事件接口
+ ///
+ public interface ITransactionInitiatorTransactionCompleted
+ where TInitiator : class, ITransactionInitiator
+ {
+ ///
+ /// 事务ID
+ ///
+ string TransactionId { get; }
+
+ ///
+ /// 事务类型
+ ///
+ byte TransactionType { get; }
+
+ ///
+ /// 事务是否成功
+ ///
+ bool IsCommitSuccess { get; }
+ }
+}
diff --git a/src/Eventual2PC/Events/ITransactionInitiatorTransactionStarted.cs b/src/Eventual2PC/Events/ITransactionInitiatorTransactionStarted.cs
new file mode 100644
index 0000000..e2a28ec
--- /dev/null
+++ b/src/Eventual2PC/Events/ITransactionInitiatorTransactionStarted.cs
@@ -0,0 +1,19 @@
+namespace Eventual2PC.Events
+{
+ ///
+ /// 事务已开始事件接口
+ ///
+ public interface ITransactionInitiatorTransactionStarted
+ where TInitiator : class, ITransactionInitiator
+ {
+ ///
+ /// 事务ID
+ ///
+ string TransactionId { get; }
+
+ ///
+ /// 事务类型
+ ///
+ byte TransactionType { get; }
+ }
+}
diff --git a/src/Eventual2PC/Events/ITransactionParticipantCommitted.cs b/src/Eventual2PC/Events/ITransactionParticipantCommitted.cs
new file mode 100644
index 0000000..21c76c8
--- /dev/null
+++ b/src/Eventual2PC/Events/ITransactionParticipantCommitted.cs
@@ -0,0 +1,17 @@
+namespace Eventual2PC.Events
+{
+ ///
+ /// 事务参与者已提交事件
+ ///
+ ///
+ ///
+ public interface ITransactionParticipantCommitted
+ where TParticipant : class, ITransactionParticipant
+ where TTransactionPreparation : class, ITransactionPreparation
+ {
+ ///
+ /// 事务准备
+ ///
+ TTransactionPreparation TransactionPreparation { get; }
+ }
+}
diff --git a/src/Eventual2PC/Events/ITransactionParticipantPreCommitFailed.cs b/src/Eventual2PC/Events/ITransactionParticipantPreCommitFailed.cs
new file mode 100644
index 0000000..119b880
--- /dev/null
+++ b/src/Eventual2PC/Events/ITransactionParticipantPreCommitFailed.cs
@@ -0,0 +1,35 @@
+namespace Eventual2PC.Events
+{
+ ///
+ /// 事务参与者预提交失败事件(或领域异常)
+ ///
+ ///
+ ///
+ public interface ITransactionParticipantPreCommitFailed
+ where TParticipant : class, ITransactionParticipant
+ where TTransactionPreparation : class, ITransactionPreparation
+ {
+ ///
+ /// 事务准备
+ ///
+ TTransactionPreparation TransactionPreparation { get; }
+ }
+
+ ///
+ /// 事务参与者预提交失败事件(或领域异常)
+ ///
+ ///
+ public interface ITransactionParticipantPreCommitFailed
+ where TParticipant : class, ITransactionParticipant
+ {
+ ///
+ /// 事务准备类型
+ ///
+ string TransactionPreparationType { get; }
+
+ ///
+ /// 事务准备
+ ///
+ TransactionPreparationInfo TransactionPreparation { get; }
+ }
+}
diff --git a/src/Eventual2PC/Events/ITransactionParticipantPreCommitSucceed.cs b/src/Eventual2PC/Events/ITransactionParticipantPreCommitSucceed.cs
new file mode 100644
index 0000000..f82001a
--- /dev/null
+++ b/src/Eventual2PC/Events/ITransactionParticipantPreCommitSucceed.cs
@@ -0,0 +1,17 @@
+namespace Eventual2PC.Events
+{
+ ///
+ /// 事务参与者预提交成功事件
+ ///
+ ///
+ ///
+ public interface ITransactionParticipantPreCommitSucceed
+ where TParticipant : class, ITransactionParticipant
+ where TTransactionPreparation : class, ITransactionPreparation
+ {
+ ///
+ /// 事务准备
+ ///
+ TTransactionPreparation TransactionPreparation { get; }
+ }
+}
diff --git a/src/Eventual2PC/Events/ITransactionParticipantRolledback.cs b/src/Eventual2PC/Events/ITransactionParticipantRolledback.cs
new file mode 100644
index 0000000..06ca2bd
--- /dev/null
+++ b/src/Eventual2PC/Events/ITransactionParticipantRolledback.cs
@@ -0,0 +1,17 @@
+namespace Eventual2PC.Events
+{
+ ///
+ /// 事务参与者已回滚事件
+ ///
+ ///
+ ///
+ public interface ITransactionParticipantRolledback
+ where TParticipant : class, ITransactionParticipant
+ where TTransactionPreparation : class, ITransactionPreparation
+ {
+ ///
+ /// 事务准备
+ ///
+ TTransactionPreparation TransactionPreparation { get; }
+ }
+}
diff --git a/src/Eventual2PC/Eventual2PC.csproj b/src/Eventual2PC/Eventual2PC.csproj
new file mode 100644
index 0000000..ead2d84
--- /dev/null
+++ b/src/Eventual2PC/Eventual2PC.csproj
@@ -0,0 +1,22 @@
+
+
+
+ netstandard2.0
+ true
+ false
+ false
+ MIT
+ https://github.com/berkaroad/Eventual2PC
+ https://github.com/berkaroad/Eventual2PC
+ Jerry Bai
+ Eventual2PC
+ 1.0.0
+ 1.0.0
+ Eventual2PC
+ 最终一致性二阶段提交范式,简化多聚合根之间交互事务的实现。
+ 2pc eventual transaction processmanager saga eda
+ 最终一致性二阶段提交范式,简化多聚合根之间交互事务的实现。任何基于cqrs + eda 实现多聚合根最终一致性的框架,都可使用。
+
+
+
+
diff --git a/src/Eventual2PC/ITransactionInitiator.cs b/src/Eventual2PC/ITransactionInitiator.cs
new file mode 100644
index 0000000..36a800c
--- /dev/null
+++ b/src/Eventual2PC/ITransactionInitiator.cs
@@ -0,0 +1,45 @@
+namespace Eventual2PC
+{
+ ///
+ /// 事务发起方
+ ///
+ public interface ITransactionInitiator
+ {
+ ///
+ /// 添加预提交成功的参与者信息
+ ///
+ /// 事务ID
+ /// 事务类型
+ /// 事务参与方信息
+ void AddPreCommitSuccessParticipant(string transactionId, byte transactionType, TransactionParticipantInfo participantInfo);
+
+ ///
+ /// 添加预提交失败的参与者信息
+ ///
+ /// 事务ID
+ /// 事务类型
+ /// 事务参与方信息
+ void AddPreCommitFailedParticipant(string transactionId, byte transactionType, TransactionParticipantInfo participantInfo);
+
+ ///
+ /// 添加已提交的参与者信息
+ ///
+ /// 事务ID
+ /// 事务类型
+ /// 事务参与方信息
+ void AddCommittedParticipant(string transactionId, byte transactionType, TransactionParticipantInfo participantInfo);
+
+ ///
+ /// 添加已回滚的参与者信息
+ ///
+ ///
+ /// 事务类型
+ /// 事务参与方信息
+ void AddRolledbackParticipant(string transactionId, byte transactionType, TransactionParticipantInfo participantInfo);
+
+ ///
+ /// 是否事务在处理中
+ ///
+ bool IsTransactionProcessing { get; }
+ }
+}
diff --git a/src/Eventual2PC/ITransactionParticipant.cs b/src/Eventual2PC/ITransactionParticipant.cs
new file mode 100644
index 0000000..ca7c4c3
--- /dev/null
+++ b/src/Eventual2PC/ITransactionParticipant.cs
@@ -0,0 +1,26 @@
+namespace Eventual2PC
+{
+ ///
+ /// 事务参与方
+ ///
+ public interface ITransactionParticipant
+ {
+ ///
+ /// 预提交(产生预提交成功的领域事件,或抛出领域异常)
+ ///
+ ///
+ void PreCommit(ITransactionPreparation transactionPreparation);
+
+ ///
+ /// 提交(预提交反馈成功后,才能提交)
+ ///
+ ///
+ void Commit(string transactionId);
+
+ ///
+ /// 回滚(由事务发起方进行回滚)
+ ///
+ ///
+ void Rollback(string transactionId);
+ }
+}
diff --git a/src/Eventual2PC/ITransactionPreparation.cs b/src/Eventual2PC/ITransactionPreparation.cs
new file mode 100644
index 0000000..55d4395
--- /dev/null
+++ b/src/Eventual2PC/ITransactionPreparation.cs
@@ -0,0 +1,44 @@
+namespace Eventual2PC
+{
+ ///
+ /// 事务准备
+ ///
+ public interface ITransactionPreparation
+ {
+ ///
+ /// 事务参与方ID
+ ///
+ string ParticipantId { get; }
+
+ ///
+ /// 事务参与方类型
+ ///
+ byte ParticipantType { get; }
+
+ ///
+ /// 事务ID
+ ///
+ string TransactionId { get; }
+
+ ///
+ /// 事务类型
+ ///
+ byte TransactionType { get; }
+
+ ///
+ /// 事务发起方ID
+ ///
+ string InitiatorId { get; }
+
+ ///
+ /// 事务发起方类型
+ ///
+ byte InitiatorType { get; }
+
+ ///
+ /// 获取准备信息
+ ///
+ ///
+ TransactionPreparationInfo GetTransactionPreparationInfo();
+ }
+}
diff --git a/src/Eventual2PC/TransactionParticipantInfo.cs b/src/Eventual2PC/TransactionParticipantInfo.cs
new file mode 100644
index 0000000..116d11e
--- /dev/null
+++ b/src/Eventual2PC/TransactionParticipantInfo.cs
@@ -0,0 +1,56 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Eventual2PC
+{
+ ///
+ /// 事务参与方信息
+ ///
+ [Serializable]
+ public sealed class TransactionParticipantInfo
+ {
+ ///
+ /// 事务准备
+ ///
+ /// 事务参与方ID
+ /// 事务参与方类型
+ public TransactionParticipantInfo(string participantId, byte participantType)
+ {
+ ParticipantId = participantId;
+ ParticipantType = participantType;
+ }
+
+ ///
+ /// 事务参与方ID
+ ///
+ public string ParticipantId { get; private set; }
+
+ ///
+ /// 事务参与方类型
+ ///
+ public byte ParticipantType { get; private set; }
+
+ ///
+ /// 参与者是否已存在
+ ///
+ /// 参与者信息列表
+ ///
+ public bool IsParticipantAlreadyExists(IEnumerable participants)
+ {
+ return participants != null && participants.Any(a => a.ParticipantId == ParticipantId);
+ }
+
+ ///
+ /// 验证必须不存在
+ ///
+ /// 参与者信息列表
+ public void ValidateParticipantMustNotExists(IEnumerable participants)
+ {
+ if (IsParticipantAlreadyExists(participants))
+ {
+ throw new ApplicationException($"{ParticipantId} has already exists.");
+ }
+ }
+ }
+}
diff --git a/src/Eventual2PC/TransactionPreparationBase.cs b/src/Eventual2PC/TransactionPreparationBase.cs
new file mode 100644
index 0000000..64a8b87
--- /dev/null
+++ b/src/Eventual2PC/TransactionPreparationBase.cs
@@ -0,0 +1,74 @@
+using System;
+
+namespace Eventual2PC
+{
+ ///
+ /// 事务准备
+ ///
+ [Serializable]
+ public abstract class TransactionPreparationBase : ITransactionPreparation
+ {
+ ///
+ /// 事务准备
+ ///
+ protected TransactionPreparationBase() {}
+
+ ///
+ /// 事务准备
+ ///
+ /// 事务参与方ID
+ /// 事务参与方类型
+ /// 事务ID
+ /// 事务类型
+ /// 事务发起方ID
+ /// 事务发起方类型
+ protected TransactionPreparationBase(string participantId, byte participantType, string transactionId, byte transactionType, string initiatorId, byte initiatorType)
+ {
+ ParticipantId = participantId;
+ ParticipantType = participantType;
+ TransactionId = transactionId;
+ TransactionType = transactionType;
+ InitiatorId = initiatorId;
+ InitiatorType = initiatorType;
+ }
+
+ ///
+ /// 事务参与方ID
+ ///
+ public string ParticipantId { get; protected set; }
+
+ ///
+ /// 事务参与方类型
+ ///
+ public byte ParticipantType { get; protected set; }
+
+ ///
+ /// 事务ID
+ ///
+ public string TransactionId { get; protected set; }
+
+ ///
+ /// 事务类型
+ ///
+ public byte TransactionType { get; protected set; }
+
+ ///
+ /// 事务发起方ID
+ ///
+ public string InitiatorId { get; protected set; }
+
+ ///
+ /// 事务发起方类型
+ ///
+ public byte InitiatorType { get; protected set; }
+
+ ///
+ /// 获取准备信息
+ ///
+ ///
+ public TransactionPreparationInfo GetTransactionPreparationInfo()
+ {
+ return new TransactionPreparationInfo(ParticipantId, ParticipantType, TransactionId, TransactionType, InitiatorId, InitiatorType);
+ }
+ }
+}
diff --git a/src/Eventual2PC/TransactionPreparationInfo.cs b/src/Eventual2PC/TransactionPreparationInfo.cs
new file mode 100644
index 0000000..61b4454
--- /dev/null
+++ b/src/Eventual2PC/TransactionPreparationInfo.cs
@@ -0,0 +1,65 @@
+using System;
+
+namespace Eventual2PC
+{
+ ///
+ /// 事务准备信息
+ ///
+ [Serializable]
+ public sealed class TransactionPreparationInfo
+ {
+ ///
+ /// 事务准备信息
+ ///
+ public TransactionPreparationInfo() { }
+
+ ///
+ /// 事务准备
+ ///
+ /// 事务参与方ID
+ /// 事务参与方类型
+ /// 事务ID
+ /// 事务类型
+ /// 事务发起方ID
+ /// 事务发起方类型
+ public TransactionPreparationInfo(string participantId, byte participantType, string transactionId, byte transactionType, string initiatorId, byte initiatorType)
+ {
+ ParticipantId = participantId;
+ ParticipantType = participantType;
+ TransactionId = transactionId;
+ TransactionType = transactionType;
+ InitiatorId = initiatorId;
+ InitiatorType = initiatorType;
+ }
+
+ ///
+ /// 事务参与方ID
+ ///
+ public string ParticipantId { get; private set; }
+
+ ///
+ /// 事务参与方类型
+ ///
+ public byte ParticipantType { get; private set; }
+
+ ///
+ /// 事务ID
+ ///
+ public string TransactionId { get; private set; }
+
+ ///
+ /// 事务类型
+ ///
+ public byte TransactionType { get; private set; }
+
+ ///
+ /// 事务发起方ID
+ ///
+ public string InitiatorId { get; private set; }
+
+ ///
+ /// 事务发起方类型
+ ///
+ public byte InitiatorType { get; private set; }
+ }
+}
diff --git a/src/Eventual2PC/UnknownTransactionPreparationException.cs b/src/Eventual2PC/UnknownTransactionPreparationException.cs
new file mode 100644
index 0000000..3763cd8
--- /dev/null
+++ b/src/Eventual2PC/UnknownTransactionPreparationException.cs
@@ -0,0 +1,29 @@
+using System;
+
+namespace Eventual2PC
+{
+ ///
+ /// 未知的TransactionPreparation异常
+ ///
+ [Serializable]
+ public sealed class UnknownTransactionPreparationException : ApplicationException
+ {
+ ///
+ /// 未知的TransactionPreparation异常
+ ///
+ public UnknownTransactionPreparationException() : base() { }
+
+ ///
+ /// 未知的TransactionPreparation异常
+ ///
+ ///
+ public UnknownTransactionPreparationException(string message) : base(message) { }
+
+ ///
+ /// 未知的TransactionPreparation异常
+ ///
+ ///
+ ///
+ public UnknownTransactionPreparationException(string message, Exception innerException) : base(message, innerException) { }
+ }
+}