Skip to content

Commit b88dc13

Browse files
Improve formatting of journal mismatch (#514)
1 parent 3766d8a commit b88dc13

File tree

4 files changed

+78
-104
lines changed

4 files changed

+78
-104
lines changed

sdk-core/src/main/java/dev/restate/sdk/core/ProtocolException.java

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,9 @@ public class ProtocolException extends RuntimeException {
2020
public static final int INTERNAL_CODE = 500;
2121
public static final int JOURNAL_MISMATCH_CODE = 570;
2222
static final int PROTOCOL_VIOLATION_CODE = 571;
23-
static final int CLOSED_CODE = 598;
24-
25-
@SuppressWarnings("StaticAssignmentOfThrowable")
26-
static final ProtocolException CLOSED = new ProtocolException("Invocation closed", CLOSED_CODE);
2723

2824
private final int code;
2925

30-
private ProtocolException(String message) {
31-
this(message, TerminalException.INTERNAL_SERVER_ERROR_CODE);
32-
}
33-
3426
public ProtocolException(String message, int code) {
3527
this(message, code, null);
3628
}

sdk-core/src/main/java/dev/restate/sdk/core/statemachine/CommandType.java

Lines changed: 20 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -32,46 +32,25 @@ enum CommandType {
3232

3333
/** Convert a CommandType to a MessageType. */
3434
public MessageType toMessageType() {
35-
switch (this) {
36-
case INPUT:
37-
return MessageType.InputCommandMessage;
38-
case OUTPUT:
39-
return MessageType.OutputCommandMessage;
40-
case GET_STATE:
41-
return MessageType.GetLazyStateCommandMessage;
42-
case GET_STATE_KEYS:
43-
return MessageType.GetLazyStateKeysCommandMessage;
44-
case SET_STATE:
45-
return MessageType.SetStateCommandMessage;
46-
case CLEAR_STATE:
47-
return MessageType.ClearStateCommandMessage;
48-
case CLEAR_ALL_STATE:
49-
return MessageType.ClearAllStateCommandMessage;
50-
case GET_PROMISE:
51-
return MessageType.GetPromiseCommandMessage;
52-
case PEEK_PROMISE:
53-
return MessageType.PeekPromiseCommandMessage;
54-
case COMPLETE_PROMISE:
55-
return MessageType.CompletePromiseCommandMessage;
56-
case SLEEP:
57-
return MessageType.SleepCommandMessage;
58-
case CALL:
59-
return MessageType.CallCommandMessage;
60-
case ONE_WAY_CALL:
61-
return MessageType.OneWayCallCommandMessage;
62-
case SEND_SIGNAL:
63-
case CANCEL_INVOCATION:
64-
return MessageType.SendSignalCommandMessage;
65-
case RUN:
66-
return MessageType.RunCommandMessage;
67-
case ATTACH_INVOCATION:
68-
return MessageType.AttachInvocationCommandMessage;
69-
case GET_INVOCATION_OUTPUT:
70-
return MessageType.GetInvocationOutputCommandMessage;
71-
case COMPLETE_AWAKEABLE:
72-
return MessageType.CompleteAwakeableCommandMessage;
73-
default:
74-
throw new IllegalStateException("Unexpected command type: " + this);
75-
}
35+
return switch (this) {
36+
case INPUT -> MessageType.InputCommandMessage;
37+
case OUTPUT -> MessageType.OutputCommandMessage;
38+
case GET_STATE -> MessageType.GetLazyStateCommandMessage;
39+
case GET_STATE_KEYS -> MessageType.GetLazyStateKeysCommandMessage;
40+
case SET_STATE -> MessageType.SetStateCommandMessage;
41+
case CLEAR_STATE -> MessageType.ClearStateCommandMessage;
42+
case CLEAR_ALL_STATE -> MessageType.ClearAllStateCommandMessage;
43+
case GET_PROMISE -> MessageType.GetPromiseCommandMessage;
44+
case PEEK_PROMISE -> MessageType.PeekPromiseCommandMessage;
45+
case COMPLETE_PROMISE -> MessageType.CompletePromiseCommandMessage;
46+
case SLEEP -> MessageType.SleepCommandMessage;
47+
case CALL -> MessageType.CallCommandMessage;
48+
case ONE_WAY_CALL -> MessageType.OneWayCallCommandMessage;
49+
case SEND_SIGNAL, CANCEL_INVOCATION -> MessageType.SendSignalCommandMessage;
50+
case RUN -> MessageType.RunCommandMessage;
51+
case ATTACH_INVOCATION -> MessageType.AttachInvocationCommandMessage;
52+
case GET_INVOCATION_OUTPUT -> MessageType.GetInvocationOutputCommandMessage;
53+
case COMPLETE_AWAKEABLE -> MessageType.CompleteAwakeableCommandMessage;
54+
};
7655
}
7756
}

sdk-core/src/main/java/dev/restate/sdk/core/statemachine/EntryHeaderChecker.java

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,11 @@ public static <E extends MessageLite> EntryHeaderChecker<E> check(
4747
throw new ProtocolException(
4848
"Found a mismatch between the code paths taken during the previous execution and the paths taken during this execution.\n"
4949
+ "This typically happens when some parts of the code are non-deterministic.\n"
50-
+ "- The mismatch happened with message types not matching\n"
51-
+ "- Difference:\n"
52-
+ " Message types don't match: expected "
53-
+ expectedClass.getSimpleName()
54-
+ ", actual "
55-
+ actual.getClass().getSimpleName()
56-
+ "\n",
50+
+ "- Expecting command '"
51+
+ Util.commandMessageToString(expected)
52+
+ "' but was '"
53+
+ Util.commandMessageToString(actual)
54+
+ "'",
5755
JOURNAL_MISMATCH_CODE);
5856
}
5957
return new EntryHeaderChecker<>(expected, (E) actual);
@@ -98,18 +96,18 @@ private ProtocolException createMismatchException() {
9896
"Found a mismatch between the code paths taken during the previous execution and the paths taken during this execution.\n"
9997
+ "This typically happens when some parts of the code are non-deterministic.\n"
10098
+ "- The mismatch happened while executing '"
101-
+ expected.getClass().getSimpleName()
99+
+ Util.commandMessageToString(expected)
102100
+ "'\n"
103-
+ "- Difference:\n");
101+
+ "- Difference:");
104102
for (FieldMismatch mismatch : mismatches) {
105103
customMessage
106-
.append(" ")
104+
.append("\n ")
107105
.append(mismatch.fieldName)
108106
.append(": '")
109107
.append(mismatch.expectedValue)
110108
.append("' != '")
111109
.append(mismatch.actualValue)
112-
.append("'\n");
110+
.append("'");
113111
}
114112

115113
return new ProtocolException(customMessage.toString(), JOURNAL_MISMATCH_CODE);

sdk-core/src/main/java/dev/restate/sdk/core/statemachine/Util.java

Lines changed: 49 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,14 @@
99
package dev.restate.sdk.core.statemachine;
1010

1111
import com.google.protobuf.ByteString;
12+
import com.google.protobuf.MessageLite;
1213
import com.google.protobuf.UnsafeByteOperations;
1314
import dev.restate.common.Slice;
1415
import dev.restate.sdk.common.TerminalException;
15-
import dev.restate.sdk.core.ProtocolException;
1616
import dev.restate.sdk.core.generated.protocol.Protocol;
17-
import java.io.PrintWriter;
18-
import java.io.StringWriter;
1917
import java.nio.ByteBuffer;
2018
import java.time.Duration;
2119
import java.util.Objects;
22-
import org.jspecify.annotations.Nullable;
2320

2421
public class Util {
2522

@@ -38,46 +35,6 @@ static Protocol.Failure toProtocolFailure(Throwable throwable) {
3835
return toProtocolFailure(TerminalException.INTERNAL_SERVER_ERROR_CODE, throwable.toString());
3936
}
4037

41-
static Protocol.ErrorMessage toErrorMessage(
42-
Throwable throwable,
43-
int currentCommandIndex,
44-
@Nullable String currentCommandName,
45-
@Nullable MessageType currentCommandType) {
46-
Protocol.ErrorMessage.Builder msg = Protocol.ErrorMessage.newBuilder();
47-
48-
if (throwable.getMessage() == null) {
49-
// This happens only with few common exceptions, but anyway
50-
msg.setMessage(throwable.toString());
51-
} else {
52-
msg.setMessage(throwable.getMessage());
53-
}
54-
55-
if (throwable instanceof ProtocolException) {
56-
msg.setCode(((ProtocolException) throwable).getCode());
57-
} else {
58-
msg.setCode(TerminalException.INTERNAL_SERVER_ERROR_CODE);
59-
}
60-
61-
// Convert stacktrace to string
62-
StringWriter sw = new StringWriter();
63-
PrintWriter pw = new PrintWriter(sw);
64-
throwable.printStackTrace(pw);
65-
msg.setStacktrace(sw.toString());
66-
67-
// Add journal entry info
68-
if (currentCommandIndex >= 0) {
69-
msg.setRelatedCommandIndex(currentCommandIndex);
70-
}
71-
if (currentCommandName != null) {
72-
msg.setRelatedCommandName(currentCommandName);
73-
}
74-
if (currentCommandType != null) {
75-
msg.setRelatedCommandType(currentCommandType.encode());
76-
}
77-
78-
return msg.build();
79-
}
80-
8138
static TerminalException toRestateException(Protocol.Failure failure) {
8239
return new TerminalException(failure.getCode(), failure.getMessage());
8340
}
@@ -100,6 +57,54 @@ static Duration durationMin(Duration a, Duration b) {
10057
return (a.compareTo(b) <= 0) ? a : b;
10158
}
10259

60+
/**
61+
* Returns a string representation of a command message.
62+
*
63+
* @param message The command message
64+
* @return A string representation of the command message
65+
*/
66+
static String commandMessageToString(MessageLite message) {
67+
if (message instanceof Protocol.InputCommandMessage) {
68+
return "handler input";
69+
} else if (message instanceof Protocol.OutputCommandMessage) {
70+
return "handler return";
71+
} else if (message instanceof Protocol.GetLazyStateCommandMessage) {
72+
return "get state";
73+
} else if (message instanceof Protocol.GetLazyStateKeysCommandMessage) {
74+
return "get state keys";
75+
} else if (message instanceof Protocol.SetStateCommandMessage) {
76+
return "set state";
77+
} else if (message instanceof Protocol.ClearStateCommandMessage) {
78+
return "clear state";
79+
} else if (message instanceof Protocol.ClearAllStateCommandMessage) {
80+
return "clear all state";
81+
} else if (message instanceof Protocol.GetPromiseCommandMessage) {
82+
return "get promise";
83+
} else if (message instanceof Protocol.PeekPromiseCommandMessage) {
84+
return "peek promise";
85+
} else if (message instanceof Protocol.CompletePromiseCommandMessage) {
86+
return "complete promise";
87+
} else if (message instanceof Protocol.SleepCommandMessage) {
88+
return "sleep";
89+
} else if (message instanceof Protocol.CallCommandMessage) {
90+
return "call";
91+
} else if (message instanceof Protocol.OneWayCallCommandMessage) {
92+
return "one way call/send";
93+
} else if (message instanceof Protocol.SendSignalCommandMessage) {
94+
return "send signal";
95+
} else if (message instanceof Protocol.RunCommandMessage) {
96+
return "run";
97+
} else if (message instanceof Protocol.AttachInvocationCommandMessage) {
98+
return "attach invocation";
99+
} else if (message instanceof Protocol.GetInvocationOutputCommandMessage) {
100+
return "get invocation output";
101+
} else if (message instanceof Protocol.CompleteAwakeableCommandMessage) {
102+
return "complete awakeable";
103+
}
104+
105+
return message.getClass().getSimpleName();
106+
}
107+
103108
private static final class ByteStringSlice implements Slice {
104109
private final ByteString byteString;
105110

0 commit comments

Comments
 (0)