Skip to content

Commit 0829eba

Browse files
committed
Refactor MutationRequest with detail grouping
1 parent 5824a19 commit 0829eba

5 files changed

Lines changed: 161 additions & 62 deletions

File tree

src/Governance/Abstractions/Requests/Factory/MutationRequestFactory.cs

Lines changed: 49 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -78,19 +78,28 @@ public static MutationRequest Pending(
7878
{
7979
return new MutationRequest
8080
{
81-
StateId = stateId,
82-
StateType = stateType,
83-
MutationType = mutationType,
84-
Intent = intent,
85-
Context = context,
86-
Status = MutationRequestStatus.Pending,
87-
PendingReason = pendingReason,
81+
Scope = new MutationRequestScopeDetails
82+
{
83+
StateId = stateId,
84+
StateType = stateType,
85+
MutationType = mutationType
86+
},
87+
Payload = new MutationRequestPayloadDetails
88+
{
89+
Intent = intent,
90+
Context = context
91+
},
92+
Lifecycle = new MutationRequestLifecycleDetails
93+
{
94+
Status = MutationRequestStatus.Pending,
95+
PendingReason = pendingReason,
96+
ExpiresAt = expiresAt
97+
},
8898
Requirements = requirements ?? [],
8999
Versioning = new MutationRequestVersioningDetails
90100
{
91101
ExpectedStateVersion = expectedStateVersion
92102
},
93-
ExpiresAt = expiresAt,
94103
Metadata = metadata ?? new Dictionary<string, object>(),
95104
Decisions =
96105
[
@@ -171,20 +180,29 @@ public static MutationRequest PendingApproval(
171180

172181
return new MutationRequest
173182
{
174-
StateId = stateId,
175-
StateType = stateType,
176-
MutationType = mutationType,
177-
Intent = intent,
178-
Context = context,
179-
Status = MutationRequestStatus.Pending,
180-
PendingReason = PendingMutationReason.Approval,
183+
Scope = new MutationRequestScopeDetails
184+
{
185+
StateId = stateId,
186+
StateType = stateType,
187+
MutationType = mutationType
188+
},
189+
Payload = new MutationRequestPayloadDetails
190+
{
191+
Intent = intent,
192+
Context = context
193+
},
194+
Lifecycle = new MutationRequestLifecycleDetails
195+
{
196+
Status = MutationRequestStatus.Pending,
197+
PendingReason = PendingMutationReason.Approval,
198+
ExpiresAt = expiresAt
199+
},
181200
Requirements = requirements,
182201
ApprovalRequirements = approvalRequirements,
183202
Versioning = new MutationRequestVersioningDetails
184203
{
185204
ExpectedStateVersion = expectedStateVersion
186205
},
187-
ExpiresAt = expiresAt,
188206
Metadata = metadata ?? new Dictionary<string, object>(),
189207
Decisions =
190208
[
@@ -257,12 +275,21 @@ public static MutationRequest Approved(
257275
{
258276
return new MutationRequest
259277
{
260-
StateId = stateId,
261-
StateType = stateType,
262-
MutationType = mutationType,
263-
Intent = intent,
264-
Context = context,
265-
Status = MutationRequestStatus.Approved,
278+
Scope = new MutationRequestScopeDetails
279+
{
280+
StateId = stateId,
281+
StateType = stateType,
282+
MutationType = mutationType
283+
},
284+
Payload = new MutationRequestPayloadDetails
285+
{
286+
Intent = intent,
287+
Context = context
288+
},
289+
Lifecycle = new MutationRequestLifecycleDetails
290+
{
291+
Status = MutationRequestStatus.Approved
292+
},
266293
Versioning = new MutationRequestVersioningDetails
267294
{
268295
ExpectedStateVersion = expectedStateVersion
Lines changed: 36 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System.Text.Json.Serialization;
12
using ModularityKit.Mutator.Abstractions.Context;
23
using ModularityKit.Mutator.Abstractions.Effects;
34
using ModularityKit.Mutator.Abstractions.Intent;
@@ -19,45 +20,25 @@ public sealed record MutationRequest
1920
public string RequestId { get; init; } = Guid.NewGuid().ToString();
2021

2122
/// <summary>
22-
/// Identifier of the state targeted by this request.
23+
/// Target scope details for the governed request.
2324
/// </summary>
24-
public string StateId { get; init; } = string.Empty;
25+
public MutationRequestScopeDetails Scope { get; init; } = new();
2526

2627
/// <summary>
27-
/// Logical state type targeted by the request.
28+
/// Submitted mutation payload details for the governed request.
2829
/// </summary>
29-
public string StateType { get; init; } = string.Empty;
30+
public MutationRequestPayloadDetails Payload { get; init; } = new();
3031

3132
/// <summary>
32-
/// CLR type name of the underlying mutation.
33+
/// Lifecycle state and lifecycle timestamps associated with the request.
3334
/// </summary>
34-
public string MutationType { get; init; } = string.Empty;
35-
36-
/// <summary>
37-
/// Intent associated with the requested mutation.
38-
/// </summary>
39-
public MutationIntent Intent { get; init; } = null!;
40-
41-
/// <summary>
42-
/// Request context describing who requested the mutation and why.
43-
/// </summary>
44-
public MutationContext Context { get; init; } = null!;
35+
public MutationRequestLifecycleDetails Lifecycle { get; init; } = new();
4536

4637
/// <summary>
4738
/// Governed execution-specific details associated with this request.
4839
/// </summary>
4940
public GovernedExecutionDetails Execution { get; init; } = new();
5041

51-
/// <summary>
52-
/// Current lifecycle status of the request.
53-
/// </summary>
54-
public MutationRequestStatus Status { get; init; } = MutationRequestStatus.Created;
55-
56-
/// <summary>
57-
/// Reason why the request is pending, if it has not executed yet.
58-
/// </summary>
59-
public PendingMutationReason? PendingReason { get; init; }
60-
6142
/// <summary>
6243
/// Requirements that must be fulfilled before execution may proceed.
6344
/// </summary>
@@ -89,22 +70,37 @@ public sealed record MutationRequest
8970
public MutationRequestVersioningDetails Versioning { get; init; } = new();
9071

9172
/// <summary>
92-
/// Optional expiration time for pending requests.
73+
/// Additional governance metadata carried by the request.
9374
/// </summary>
94-
public DateTimeOffset? ExpiresAt { get; init; }
75+
public IReadOnlyDictionary<string, object> Metadata { get; init; } = new Dictionary<string, object>();
9576

96-
/// <summary>
97-
/// Timestamp when the request was first created.
98-
/// </summary>
99-
public DateTimeOffset CreatedAt { get; init; } = DateTimeOffset.UtcNow;
77+
[JsonIgnore]
78+
public string StateId => Scope.StateId;
10079

101-
/// <summary>
102-
/// Timestamp of the last lifecycle update applied to the request.
103-
/// </summary>
104-
public DateTimeOffset UpdatedAt { get; init; } = DateTimeOffset.UtcNow;
80+
[JsonIgnore]
81+
public string StateType => Scope.StateType;
10582

106-
/// <summary>
107-
/// Additional governance metadata carried by the request.
108-
/// </summary>
109-
public IReadOnlyDictionary<string, object> Metadata { get; init; } = new Dictionary<string, object>();
83+
[JsonIgnore]
84+
public string MutationType => Scope.MutationType;
85+
86+
[JsonIgnore]
87+
public MutationIntent Intent => Payload.Intent;
88+
89+
[JsonIgnore]
90+
public MutationContext Context => Payload.Context;
91+
92+
[JsonIgnore]
93+
public MutationRequestStatus Status => Lifecycle.Status;
94+
95+
[JsonIgnore]
96+
public PendingMutationReason? PendingReason => Lifecycle.PendingReason;
97+
98+
[JsonIgnore]
99+
public DateTimeOffset? ExpiresAt => Lifecycle.ExpiresAt;
100+
101+
[JsonIgnore]
102+
public DateTimeOffset CreatedAt => Lifecycle.CreatedAt;
103+
104+
[JsonIgnore]
105+
public DateTimeOffset UpdatedAt => Lifecycle.UpdatedAt;
110106
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
using ModularityKit.Mutator.Governance.Abstractions.Lifecycle.Model;
2+
3+
namespace ModularityKit.Mutator.Governance.Abstractions.Requests.Model;
4+
5+
/// <summary>
6+
/// Groups lifecycle state and lifecycle timestamps associated with a governed request.
7+
/// </summary>
8+
public sealed record MutationRequestLifecycleDetails
9+
{
10+
/// <summary>
11+
/// Current lifecycle status of the request.
12+
/// </summary>
13+
public MutationRequestStatus Status { get; init; } = MutationRequestStatus.Created;
14+
15+
/// <summary>
16+
/// Reason why the request is pending, if it has not executed yet.
17+
/// </summary>
18+
public PendingMutationReason? PendingReason { get; init; }
19+
20+
/// <summary>
21+
/// Optional expiration time for pending requests.
22+
/// </summary>
23+
public DateTimeOffset? ExpiresAt { get; init; }
24+
25+
/// <summary>
26+
/// Timestamp when the request was first created.
27+
/// </summary>
28+
public DateTimeOffset CreatedAt { get; init; } = DateTimeOffset.UtcNow;
29+
30+
/// <summary>
31+
/// Timestamp of the last lifecycle update applied to the request.
32+
/// </summary>
33+
public DateTimeOffset UpdatedAt { get; init; } = DateTimeOffset.UtcNow;
34+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using ModularityKit.Mutator.Abstractions.Context;
2+
using ModularityKit.Mutator.Abstractions.Intent;
3+
4+
namespace ModularityKit.Mutator.Governance.Abstractions.Requests.Model;
5+
6+
/// <summary>
7+
/// Groups the submitted mutation intent and requester context carried by a governed request.
8+
/// </summary>
9+
public sealed record MutationRequestPayloadDetails
10+
{
11+
/// <summary>
12+
/// Intent associated with the requested mutation.
13+
/// </summary>
14+
public MutationIntent Intent { get; init; } = null!;
15+
16+
/// <summary>
17+
/// Request context describing who requested the mutation and why.
18+
/// </summary>
19+
public MutationContext Context { get; init; } = null!;
20+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
namespace ModularityKit.Mutator.Governance.Abstractions.Requests.Model;
2+
3+
/// <summary>
4+
/// Groups target scope identifiers for a governed mutation request.
5+
/// </summary>
6+
public sealed record MutationRequestScopeDetails
7+
{
8+
/// <summary>
9+
/// Identifier of the state targeted by this request.
10+
/// </summary>
11+
public string StateId { get; init; } = string.Empty;
12+
13+
/// <summary>
14+
/// Logical state type targeted by the request.
15+
/// </summary>
16+
public string StateType { get; init; } = string.Empty;
17+
18+
/// <summary>
19+
/// CLR type name of the underlying mutation.
20+
/// </summary>
21+
public string MutationType { get; init; } = string.Empty;
22+
}

0 commit comments

Comments
 (0)