-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix serialization of subclasses (#92)
* Add integration test for catching Exception instead of StepError This is the reproduction of an error reported by a user. Because StepError contains additional fields to a generic Exception, deserialization fails. * Add integration test for the general case of deserializing a subclass This shows that the issue is not limited to StepError/Exception. * Fix deserialization of subclasses Previously we were deserializing step data based on the T provided by the compiler. However, this could be lossy if the step data was actually a subclass of T with additional fields and is semantically incorrect if we try to deserialize it as the parent class. To remedy this, we need to know what the actual class of the step data was before it was memoized with the Inngest server. We are adding this as an additional field `class` on the JSON when serializing, then reading (and deleting) this field and using it with reflection to deserialize using the proper class. It might make sense to put the field `class` in some kind of meta/extension section of the payload to avoid conflict, but it's highly unlikely a field will legitimately be named class in the user code since it is a reserved keyword in Java. This strategy doesn't entirely work for schema evolution because it's still possible the classes have changed to the point where deserialization would fail. We should follow up here and probably have a fallback mechanism of returning a generic hash if deserialization fails. --------- Co-authored-by: Albert Chae <albertchae@users.noreply.github.com> Co-authored-by: Riadh <22998716+KiKoS0@users.noreply.github.com>
- Loading branch information
1 parent
bdb3a11
commit 76cd8f9
Showing
7 changed files
with
185 additions
and
5 deletions.
There are no files selected for viewing
49 changes: 49 additions & 0 deletions
49
...o/src/main/java/com/inngest/springbootdemo/testfunctions/DeserializeSubclassFunction.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package com.inngest.springbootdemo.testfunctions; | ||
|
||
import com.fasterxml.jackson.annotation.JsonProperty; | ||
import com.inngest.FunctionContext; | ||
import com.inngest.InngestFunction; | ||
import com.inngest.InngestFunctionConfigBuilder; | ||
import com.inngest.Step; | ||
import org.jetbrains.annotations.NotNull; | ||
|
||
class Dog { | ||
@JsonProperty("legs") | ||
public int legs; | ||
|
||
public Dog(@JsonProperty("legs") int legs) { | ||
this.legs = legs; | ||
} | ||
} | ||
|
||
class Corgi extends Dog { | ||
@JsonProperty("stumpy") | ||
public boolean stumpy; | ||
|
||
public Corgi(@JsonProperty("legs") int legs, @JsonProperty("stumpy") boolean stumpy) { | ||
super(legs); | ||
|
||
this.stumpy = stumpy; | ||
} | ||
} | ||
|
||
public class DeserializeSubclassFunction extends InngestFunction { | ||
@NotNull | ||
@Override | ||
public InngestFunctionConfigBuilder config(InngestFunctionConfigBuilder builder) { | ||
return builder | ||
.id("DeserializeSubclassFunction") | ||
.name("Deserialize subclass function") | ||
.triggerEvent("test/deserialize.subclass") | ||
.retries(0); | ||
} | ||
|
||
@Override | ||
public String execute(FunctionContext ctx, Step step) { | ||
Dog corgi = step.run("get-corgi", () -> new Corgi(4, true), Dog.class); | ||
|
||
assert(((Corgi) corgi).stumpy == true); | ||
|
||
return "Successfully cast Corgi"; | ||
} | ||
} |
30 changes: 30 additions & 0 deletions
30
.../main/java/com/inngest/springbootdemo/testfunctions/TryCatchGenericExceptionFunction.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package com.inngest.springbootdemo.testfunctions; | ||
|
||
import com.inngest.*; | ||
import org.jetbrains.annotations.NotNull; | ||
|
||
public class TryCatchGenericExceptionFunction extends InngestFunction { | ||
@NotNull | ||
@Override | ||
public InngestFunctionConfigBuilder config(InngestFunctionConfigBuilder builder) { | ||
return builder | ||
.id("try-catch-deserialize-exception-function") | ||
.name("Try Catch Deserialize Exception Function") | ||
.triggerEvent("test/try.catch.deserialize.exception") | ||
.retries(0); | ||
} | ||
|
||
@Override | ||
public String execute(FunctionContext ctx, Step step) { | ||
try { | ||
step.run("fail-step", () -> { | ||
throw new CustomException("Something fatally went wrong"); | ||
}, String.class); | ||
} catch (Exception originalException) { | ||
Exception e = step.run("handle-error", () -> originalException, Exception.class); | ||
return e.getMessage(); | ||
} | ||
|
||
return "An error should have been thrown and this message should not be returned"; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
42 changes: 42 additions & 0 deletions
42
...ng-boot-demo/src/test/java/com/inngest/springbootdemo/DeserializationIntegrationTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package com.inngest.springbootdemo; | ||
|
||
import com.inngest.Inngest; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.api.parallel.Execution; | ||
import org.junit.jupiter.api.parallel.ExecutionMode; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
|
||
import java.util.LinkedHashMap; | ||
|
||
import static org.junit.jupiter.api.Assertions.*; | ||
|
||
@IntegrationTest | ||
@Execution(ExecutionMode.CONCURRENT) | ||
class DeserializationIntegrationTest { | ||
@Autowired | ||
private DevServerComponent devServer; | ||
|
||
static int sleepTime = 5000; | ||
|
||
@Autowired | ||
private Inngest client; | ||
|
||
@Test | ||
void testShouldDeserializeSubclassCorrectly() throws Exception { | ||
String eventId = InngestFunctionTestHelpers.sendEvent(client, "test/deserialize.subclass").getIds()[0]; | ||
|
||
Thread.sleep(sleepTime); | ||
|
||
RunEntry<Object> run = devServer.runsByEvent(eventId).first(); | ||
Object output = run.getOutput(); | ||
if (output instanceof LinkedHashMap) { | ||
fail("Run threw an exception serialized into a LinkedHashMap:" + output); | ||
} | ||
String outputString = (String) output; | ||
|
||
assertEquals("Completed", run.getStatus() ); | ||
assertNotNull(run.getEnded_at()); | ||
|
||
assertEquals("Successfully cast Corgi", outputString); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters