22
22
23
23
import com .google .protobuf .Any ;
24
24
import com .google .protobuf .InvalidProtocolBufferException ;
25
+ import io .temporal .api .command .v1 .Command ;
26
+ import io .temporal .api .command .v1 .ProtocolMessageCommandAttributes ;
25
27
import io .temporal .api .common .v1 .Payloads ;
28
+ import io .temporal .api .enums .v1 .CommandType ;
29
+ import io .temporal .api .enums .v1 .EventType ;
26
30
import io .temporal .api .failure .v1 .Failure ;
27
31
import io .temporal .api .protocol .v1 .Message ;
28
32
import io .temporal .api .update .v1 .Acceptance ;
@@ -53,7 +57,14 @@ enum State {
53
57
NEW ,
54
58
REQUEST_INITIATED ,
55
59
ACCEPTED ,
60
+ ACCEPTED_COMMAND_CREATED ,
61
+ ACCEPTED_COMMAND_RECORDED ,
56
62
COMPLETED ,
63
+ COMPLETED_COMMAND_CREATED ,
64
+ COMPLETED_COMMAND_RECORDED ,
65
+ COMPLETED_IMMEDIATELY ,
66
+ COMPLETED_IMMEDIATELY_COMMAND_CREATED ,
67
+ COMPLETED_IMMEDIATELY_COMMAND_RECORDED
57
68
}
58
69
59
70
private static final Logger log = LoggerFactory .getLogger (UpdateProtocolStateMachine .class );
@@ -67,19 +78,74 @@ enum State {
67
78
private String requestMsgId ;
68
79
private long requestSeqID ;
69
80
private Request initialRequest ;
81
+ private String messageId ;
70
82
71
83
public static final StateMachineDefinition <State , ExplicitEvent , UpdateProtocolStateMachine >
72
84
STATE_MACHINE_DEFINITION =
73
85
StateMachineDefinition .<State , ExplicitEvent , UpdateProtocolStateMachine >newInstance (
74
- "Update" , State .NEW , State .COMPLETED )
86
+ "Update" , State .NEW , State .COMPLETED_COMMAND_RECORDED )
75
87
.add (
76
88
State .NEW ,
77
89
ProtocolType .UPDATE_V1 ,
78
90
State .REQUEST_INITIATED ,
79
91
UpdateProtocolStateMachine ::triggerUpdate )
80
- .add (State .REQUEST_INITIATED , ExplicitEvent .ACCEPT , State .ACCEPTED )
81
- .add (State .REQUEST_INITIATED , ExplicitEvent .REJECT , State .COMPLETED )
82
- .add (State .ACCEPTED , ExplicitEvent .COMPLETE , State .COMPLETED );
92
+ .add (
93
+ State .REQUEST_INITIATED ,
94
+ ExplicitEvent .ACCEPT ,
95
+ State .ACCEPTED ,
96
+ UpdateProtocolStateMachine ::sendCommandMessage )
97
+ .add (
98
+ State .ACCEPTED ,
99
+ CommandType .COMMAND_TYPE_PROTOCOL_MESSAGE ,
100
+ State .ACCEPTED_COMMAND_CREATED )
101
+ .add (
102
+ State .ACCEPTED_COMMAND_CREATED ,
103
+ EventType .EVENT_TYPE_WORKFLOW_EXECUTION_UPDATE_ACCEPTED ,
104
+ State .ACCEPTED_COMMAND_RECORDED )
105
+ .add (
106
+ State .ACCEPTED_COMMAND_RECORDED ,
107
+ ExplicitEvent .COMPLETE ,
108
+ State .COMPLETED ,
109
+ UpdateProtocolStateMachine ::sendCommandMessage )
110
+ .add (
111
+ State .COMPLETED ,
112
+ CommandType .COMMAND_TYPE_PROTOCOL_MESSAGE ,
113
+ State .COMPLETED_COMMAND_CREATED )
114
+ .add (
115
+ State .COMPLETED_COMMAND_CREATED ,
116
+ EventType .EVENT_TYPE_WORKFLOW_EXECUTION_UPDATE_COMPLETED ,
117
+ State .COMPLETED_COMMAND_RECORDED )
118
+ // Handle the validation failure case
119
+ .add (State .REQUEST_INITIATED , ExplicitEvent .REJECT , State .COMPLETED_COMMAND_RECORDED )
120
+ // Handle an edge case when the update handle completes immediately. The state machine
121
+ // should then expect
122
+ // to see two protocol command messages back to back then two update events.
123
+ .add (
124
+ State .ACCEPTED ,
125
+ ExplicitEvent .COMPLETE ,
126
+ State .COMPLETED_IMMEDIATELY ,
127
+ UpdateProtocolStateMachine ::sendCommandMessage )
128
+ .add (
129
+ State .COMPLETED_IMMEDIATELY ,
130
+ CommandType .COMMAND_TYPE_PROTOCOL_MESSAGE ,
131
+ State .COMPLETED_IMMEDIATELY_COMMAND_CREATED )
132
+ .add (
133
+ State .COMPLETED_IMMEDIATELY_COMMAND_CREATED ,
134
+ CommandType .COMMAND_TYPE_PROTOCOL_MESSAGE ,
135
+ State .COMPLETED_IMMEDIATELY_COMMAND_RECORDED )
136
+ .add (
137
+ State .COMPLETED_IMMEDIATELY_COMMAND_RECORDED ,
138
+ EventType .EVENT_TYPE_WORKFLOW_EXECUTION_UPDATE_ACCEPTED ,
139
+ State .COMPLETED_COMMAND_CREATED )
140
+ // Handle an edge case when an update handle completes after it has sent the protocol
141
+ // message command
142
+ // but has not seen the corresponding event. This can happen if the update handle runs
143
+ // a local activity
144
+ .add (
145
+ State .ACCEPTED_COMMAND_CREATED ,
146
+ ExplicitEvent .COMPLETE ,
147
+ State .COMPLETED_IMMEDIATELY_COMMAND_CREATED ,
148
+ UpdateProtocolStateMachine ::sendCommandMessage );
83
149
84
150
public static UpdateProtocolStateMachine newInstance (
85
151
Functions .Func <Boolean > replaying ,
@@ -115,10 +181,18 @@ void triggerUpdate() {
115
181
UpdateMessage updateMessage =
116
182
new UpdateMessage (this .currentMessage , new UpdateProtocolCallbackImpl ());
117
183
118
- // TODO send ProtocolMessage command when server supports
119
184
updateHandle .apply (updateMessage );
120
185
}
121
186
187
+ void sendCommandMessage () {
188
+ addCommand (
189
+ Command .newBuilder ()
190
+ .setCommandType (CommandType .COMMAND_TYPE_PROTOCOL_MESSAGE )
191
+ .setProtocolMessageCommandAttributes (
192
+ ProtocolMessageCommandAttributes .newBuilder ().setMessageId (messageId ))
193
+ .build ());
194
+ }
195
+
122
196
public void accept () {
123
197
Acceptance acceptResponse =
124
198
Acceptance .newBuilder ()
@@ -127,13 +201,13 @@ public void accept() {
127
201
.setAcceptedRequest (initialRequest )
128
202
.build ();
129
203
204
+ messageId = requestMsgId + "/accept" ;
130
205
sendHandle .apply (
131
206
Message .newBuilder ()
132
- .setId (requestMsgId + "/accept" )
207
+ .setId (messageId )
133
208
.setProtocolInstanceId (protoInstanceID )
134
209
.setBody (Any .pack (acceptResponse ))
135
210
.build ());
136
- // TODO send ProtocolMessage command when server supports
137
211
explicitEvent (ExplicitEvent .ACCEPT );
138
212
}
139
213
@@ -146,9 +220,10 @@ public void reject(Failure failure) {
146
220
.setFailure (failure )
147
221
.build ();
148
222
223
+ String messageId = requestMsgId + "/reject" ;
149
224
sendHandle .apply (
150
225
Message .newBuilder ()
151
- .setId (requestMsgId + "/reject" )
226
+ .setId (messageId )
152
227
.setProtocolInstanceId (protoInstanceID )
153
228
.setBody (Any .pack (rejectResponse ))
154
229
.build ());
@@ -165,10 +240,11 @@ public void complete(Optional<Payloads> payload, Failure failure) {
165
240
166
241
Response outcomeResponse =
167
242
Response .newBuilder ().setOutcome (outcome ).setMeta (initialRequest .getMeta ()).build ();
168
- // TODO send ProtocolMessage command when server supports
243
+
244
+ messageId = requestMsgId + "/complete" ;
169
245
sendHandle .apply (
170
246
Message .newBuilder ()
171
- .setId (requestMsgId + "/complete" )
247
+ .setId (messageId )
172
248
.setProtocolInstanceId (protoInstanceID )
173
249
.setBody (Any .pack (outcomeResponse ))
174
250
.build ());
0 commit comments