Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(java): Invoke callback on read failure #1870

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

yoohaemin
Copy link
Contributor

@yoohaemin yoohaemin commented Oct 6, 2024

What does this PR do?

See discussion: #1848 (comment)

When Fury encounters a value that does not exist in the current class definition, it can still read the value. This PR allows the user of the library to specify what to do with the value. The user can specify a function Object -> Object to update the value, and also specify a Field for that adjusted value to be set.

Related issues

#1848

Does this PR introduce any user-facing change?

  • Does this PR introduce any public API change?
  • Does this PR introduce any binary protocol compatibility change?

Benchmark

TODO

@yoohaemin yoohaemin force-pushed the yoohaemin/callback-on-read-failure branch from b1e75ba to 63ac97a Compare October 6, 2024 11:50
Comment on lines +209 to +215
// Field doesn't exist in current class, invoke field mismatch callback.
Expression fieldMismatchCallback =
Expression.Invoke.inlineInvoke(
new Expression.Reference(FURY_NAME, TypeRef.of(Fury.class)),
"getFieldMismatchCallback",
TypeRef.of(FieldMismatchCallback.class),
/* needTryCatch */ false);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be a private field, instead of being instantiated every time. I'm not used to this kind of metaprogramming so I need to figure out how to do this.

@@ -336,6 +345,11 @@ public FuryBuilder withName(String name) {
return this;
}

public FuryBuilder withFieldMismatchCallback(FieldMismatchCallback callback) {
this.fieldMismatchCallback = callback;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it can be confusing that the callback can be overridden, not added on top of already registered ones?

@@ -784,6 +784,135 @@ static boolean readBasicObjectFieldValueFailed(
}
}

static Object readFieldValue(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a rather big method; I'm not sure if HotSpot can compile this. In any case, this shouldn't be in the hot path.

@DemonJun
Copy link

DemonJun commented Oct 8, 2024

Is it possible to deserialize again by taking fields that don't exist in the class and unifying them in a map property?

if (buffer.readByte() == Fury.NULL_FLAG) {
return null;
} else if (fury.isBasicTypesRefIgnored()) {
return readFinalObjectFieldValue(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems this branch can be removed

if (buffer.readByte() == Fury.NULL_FLAG) {
return null;
} else if (fury.isBasicTypesRefIgnored()) {
return readFinalObjectFieldValue(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

if (buffer.readByte() == Fury.NULL_FLAG) {
return null;
} else if (fury.isBasicTypesRefIgnored()) {
return readFinalObjectFieldValue(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

new Literal(descriptor.getTypeName()),
new Literal(descriptor.getName()));

Expression invokeHandler =
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The onMismatch can be cached as a field using getOrCreateField function

"forName",
TypeRef.of(Class.class),
true,
new Literal(beanClass.getName())),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use Literal.ofXXX instead

fieldMismatchCallback,
"onMismatch",
TypeRef.of(FieldMismatchCallback.FieldAdjustment.class),
new Expression.StaticInvoke(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use org.apache.fury.builder.CodecBuilder#beanClassExpr(java.lang.Class<?>) instead

@chaokunyang
Copy link
Collaborator

Hi @yoohaemin , is there anything I can help to put this PR forward?

@yoohaemin
Copy link
Contributor Author

@chaokunyang hey, thanks for the ping.

I haven't forgotten about this PR, but I am a bit swamped with other things personally and have no time to push it forward.

If you want to push it forward yourself, please feel free to do so. Otherwise, I will work on it when I have time.

Unfortunately, I can't tell you when exactly I will have time, but probably this month would be hard.

@chaokunyang
Copy link
Collaborator

@yoohaemin thanks for continuing working on this pr. This ia not urgent, you can take your time. I will take a look at the ci failures to see whether I can provide more inputs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants