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

Introducing ControllerToAgentCallable and ControllerToAgentFileCallable #9921

Merged
merged 7 commits into from
Nov 9, 2024

Conversation

jglick
Copy link
Member

@jglick jglick commented Oct 28, 2024

While updating some plugin code to take advantage of Java 17 records, I noticed that one major use case for a static final class with all final fields was MasterToSlaveCallables. Unfortunately these cannot be converted to record since that cannot extend another class. I thought it would be nicer to introduce a similar interface (with updated naming, while we are here!) that is friendlier to records.

I picked RemoteLaunchCallable as an example of substantial legibility improvements from this conversion, but could try doing more as well. (OpenRewrite would be great though I am not experienced in that yet.)

Similarly, MasterToSlaveFileCallable was unnecessarily awkward to use; FilePath.Archive can be simplified this way as an example.

Testing done

None, just presuming that RemoteLaunchCallable and FilePath.Archive are well covered by existing functional tests.

Note that the version of SpotBugs we are currently running suffers from spotbugs/spotbugs#2795 which is relevant for this use case: these records are Serializable (transiently), but no serialVersionUID is meaningful since Java serialization for records is handled specially. The SpotBugs check for jenkins-core does not seem to complain for whatever reason (maybe this bug priority is already suppressed?); in my plugin doing similar work I needed to

@SuppressFBWarnings(value = "SE_NO_SERIALVERSIONID", justification = "TODO https://github.com/spotbugs/spotbugs/pull/2795 4.8.4+")

I do not feel very comfortable with the idea of reducing the typical idiom further to that using a static method as in jenkinsci/jenkins-test-harness#671 because production code might involve different Java versions (or even vendors!) between controller and agent and it is not obvious to me that this would be safe. Given

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.nio.file.Files;
import java.nio.file.Path;
import org.junit.Test;
public class XTest {
    @Test public void x() throws Exception {
        FI fi = XTest::m;
        assertThat(fi.ap(1), is(2));
        byte[] data;
        try (var baos = new ByteArrayOutputStream(); var oos = new ObjectOutputStream(baos)) {
            oos.writeObject(fi);
            data = baos.toByteArray();
        }
        Files.write(Path.of("/tmp/fi.ser"), data);
        Object o;
        try (var bais = new ByteArrayInputStream(data); var ois = new ObjectInputStream(bais)) {
            o = ois.readObject();
        }
        fi = (FI) o;
        assertThat(fi.ap(1), is(2));
    }
    private static int m(int x) {
        return x + 1;
    }
    @FunctionalInterface interface FI extends Serializable {
        int ap(int x);
    }
}

you can see a rather complex serial form

$ strings /tmp/fi.ser 
!java.lang.invoke.SerializedLambdaoa
implMethodKind[
capturedArgst
[Ljava/lang/Object;L
capturingClasst
Ljava/lang/Class;L
functionalInterfaceClasst
Ljava/lang/String;L
functionalInterfaceMethodNameq
"functionalInterfaceMethodSignatureq
	implClassq
implMethodNameq
implMethodSignatureq
instantiatedMethodTypeq
[Ljava.lang.Object;
XTest
XTest$FIt
(I)It
XTestt

Proposed changelog entries

  • Developer: Introducing ControllerToAgentCallable and ControllerToAgentFileCallable with support for records in controller to agent callables

Proposed upgrade guidelines

N/A

Submitter checklist

Desired reviewers

@Vlatombe @nevingeorgesunny @gbhat618

Before the changes are marked as ready-for-merge:

Maintainer checklist

@jglick jglick requested a review from Vlatombe October 28, 2024 15:27
}

@Restricted(NoExternalUse.class)
public void setEnvVarsFilterRuleWrapper(EnvVarsFilterRuleWrapper envVarsFilterRuleWrapper) {
Copy link
Member Author

Choose a reason for hiding this comment

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

@daniel-beck in #4683 you added this as a setter rather than constructor parameter, perhaps out of confusion with the similarly-named field in Launcher which actually needs to be mutable?

Copy link
Member

Choose a reason for hiding this comment

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

Maybe, the original code is by Wadeck and it's been far too long at this point. If this works, the setter is restricted, so any cleanup is fine.

Copy link
Member Author

Choose a reason for hiding this comment

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

the setter is restricted

Not that it needed to be: the class was private to begin with.

@jglick jglick changed the title Introducing ControllerToAgentCallable Introducing ControllerToAgentCallable and ControllerToAgentFileCallable Nov 1, 2024
Comment on lines +8 to +9
* For new code, implement {@link ControllerToAgentFileCallable}
* which has the advantage that it can be used on {@code record}s.
Copy link
Member

@Vlatombe Vlatombe Nov 4, 2024

Choose a reason for hiding this comment

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

Given that, should this class be deprecated to discourage any new usage, or hint existing ones to move to records?

Copy link
Member Author

Choose a reason for hiding this comment

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

I suppose it could be, though it feels like overkill to deprecate it merely because an aesthetically preferable alternative is now available.

@jglick jglick requested a review from a team November 4, 2024 18:18
Copy link
Member

@timja timja left a comment

Choose a reason for hiding this comment

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

LGTM


/label ready-for-merge


This PR is now ready for merge, after ~24 hours, we will merge it if there's no negative feedback.

Thanks!

@comment-ops-bot comment-ops-bot bot added the ready-for-merge The PR is ready to go, and it will be merged soon if there is no negative feedback label Nov 4, 2024
@timja timja added the developer Changes which impact plugin developers label Nov 4, 2024
@timja timja merged commit abef2cc into jenkinsci:master Nov 9, 2024
16 checks passed
@jglick jglick deleted the ControllerToAgentCallable branch November 12, 2024 19:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
developer Changes which impact plugin developers ready-for-merge The PR is ready to go, and it will be merged soon if there is no negative feedback
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants