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

Improvement: Make interfaces serializable #2142

Open
thisdotnull opened this issue Mar 26, 2024 · 0 comments
Open

Improvement: Make interfaces serializable #2142

thisdotnull opened this issue Mar 26, 2024 · 0 comments

Comments

@thisdotnull
Copy link

thisdotnull commented Mar 26, 2024

Resilience4j version: 1.7.1

Java version: 1.11

What am I trying to do?
We are using Apache Flink which requires all classes (user-defined functions) and their members to be serializable. I'm trying to decorate all the functions with a Retry.of(Function<I, O>) and subscribe to its events.

The Problem
The Function decorated with Retry.decorateFunction(Retry, Function) is a class-level field to avoid duplicate subscriptions to events.
The flink program fails to bootstrap because the class-level field Function is not serializable. This is because the Retry.decorateFunction(Retry, Function) captures the Retry param(see this).

While the configuration classes are marked serializable (thanks to #1046), the corresponding interfaces like Retry and their implementations like RetryImpl are still not serializable.

Current Workaround
To overcome this, I have to mark the decorated function as transient and specify deserialization behavior by overriding the readObject(ObjectInputStream).

class CustomWrapper<I, O> {
    private Function<I, O> actualFunction;
    private transient Function<I, O> decoratedFunction;

    public CustomFunction (Function<I, O> someFunction) {
        this.actualFunction = someFunction;

        // instantiate the Retry
        RetryRegistry registry = RetryRegistry.ofDefaults();
        Retry retry = registry.retry("name2");
        subscribeToRetryEvents(retry);

        // The returned function captures `Retry` passed in params.
        this.decoratedFunction = Retry.decorateFunction(retry, someFunction);
    }

    // Override default deserialization behavior
    private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
        stream.defaultReadObject();

        // Re-wire the transient field decoratedFunction
        RetryRegistry registry = RetryRegistry.ofDefaults();
        Retry retry = registry.retry("name2");
        subscribeToRetryEvents(retry);
        this.decoratedFunction = Retry.decorateFunction(retry, this.actualFunction);
    }

    public O doSomething(I input) {
        return decoratedFunction.apply(input);
    }
}

Proposed Solution
Mark the interfaces as serializable so that all the implementations are serializable by default.

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

No branches or pull requests

1 participant