-
Notifications
You must be signed in to change notification settings - Fork 192
Worker Versioning Annotations & Options #2463
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
Changes from all commits
cacbcb3
1542d02
355b52f
4c4c888
3d013e2
1c52169
0e6eefd
b1771a8
b9130ac
60f0c80
a58ce73
12c74fd
970b092
dc248a0
5af7560
928da52
47af3eb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| /* | ||
| * Copyright (C) 2022 Temporal Technologies, Inc. All Rights Reserved. | ||
| * | ||
| * Copyright (C) 2012-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
| * | ||
| * Modifications copyright (C) 2017 Uber Technologies, Inc. | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this material except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
|
|
||
| package io.temporal.common; | ||
|
|
||
| import io.temporal.worker.WorkerDeploymentOptions; | ||
|
|
||
| /** Specifies when a workflow might move from a worker of one Build Id to another. */ | ||
| @Experimental | ||
| public enum VersioningBehavior { | ||
| /** | ||
| * An unspecified versioning behavior. By default, workers opting into worker versioning will be | ||
| * required to specify a behavior. See {@link | ||
| * io.temporal.worker.WorkerOptions.Builder#setDeploymentOptions(WorkerDeploymentOptions)}. | ||
| */ | ||
| UNSPECIFIED, | ||
| /** The workflow will be pinned to the current Build ID unless manually moved. */ | ||
| PINNED, | ||
| /** | ||
| * The workflow will automatically move to the latest version (default Build ID of the task queue) | ||
| * when the next task is dispatched. | ||
| */ | ||
| AUTO_UPGRADE | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,103 @@ | ||
| /* | ||
| * Copyright (C) 2022 Temporal Technologies, Inc. All Rights Reserved. | ||
| * | ||
| * Copyright (C) 2012-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
| * | ||
| * Modifications copyright (C) 2017 Uber Technologies, Inc. | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this material except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
|
|
||
| package io.temporal.common; | ||
|
|
||
| import java.util.Objects; | ||
| import javax.annotation.Nonnull; | ||
| import javax.annotation.Nullable; | ||
|
|
||
| /** Represents the version of a specific worker deployment. */ | ||
| @Experimental | ||
| public class WorkerDeploymentVersion { | ||
| private final String deploymentName; | ||
| private final String buildId; | ||
|
|
||
| /** Build a worker deployment version from an explicit deployment name and build ID. */ | ||
| public WorkerDeploymentVersion(@Nonnull String deploymentName, @Nonnull String buildId) { | ||
| this.deploymentName = deploymentName; | ||
| this.buildId = buildId; | ||
| } | ||
|
|
||
| /** | ||
| * Build a worker deployment version from a canonical string representation. | ||
| * | ||
| * @param canonicalString The canonical string representation of the worker deployment version, | ||
| * formatted as "deploymentName.buildId". Deployment name must not have a "." in it. | ||
| * @return A new instance of {@link WorkerDeploymentVersion}. | ||
| * @throws IllegalArgumentException if the input string is not in the expected format. | ||
| */ | ||
| public static WorkerDeploymentVersion fromCanonicalString(String canonicalString) { | ||
| String[] parts = canonicalString.split("\\.", 2); | ||
| if (parts.length != 2) { | ||
| throw new IllegalArgumentException( | ||
| "Invalid canonical string format. Expected 'deploymentName.buildId'"); | ||
| } | ||
| return new WorkerDeploymentVersion(parts[0], parts[1]); | ||
| } | ||
|
|
||
| /** | ||
| * @return The canonical string representation of this worker deployment version. | ||
| */ | ||
| public String toCanonicalString() { | ||
| return deploymentName + "." + buildId; | ||
| } | ||
|
Comment on lines
+56
to
+61
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For this specific class, I think just having this be the
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I prefer the current approach since the canonical format is different then the standard
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Meh, not sure there is such thing as a "standard"
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I looked into this when I wrote it and it seems the consensus is that toString is more for debugging than canonical representations
Sushisource marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| /** | ||
| * @return The name of the deployment. | ||
| */ | ||
| @Nullable // Marked nullable for future compatibility with custom strings | ||
| public String getDeploymentName() { | ||
| return deploymentName; | ||
| } | ||
|
|
||
| /** | ||
| * @return The Build ID of this version. | ||
| */ | ||
| @Nullable // Marked nullable for future compatibility with custom strings | ||
| public String getBuildId() { | ||
| return buildId; | ||
| } | ||
|
|
||
| @Override | ||
| public boolean equals(Object o) { | ||
| if (o == null || getClass() != o.getClass()) return false; | ||
| WorkerDeploymentVersion that = (WorkerDeploymentVersion) o; | ||
| return Objects.equals(deploymentName, that.deploymentName) | ||
| && Objects.equals(buildId, that.buildId); | ||
| } | ||
|
|
||
| @Override | ||
| public int hashCode() { | ||
| return Objects.hash(deploymentName, buildId); | ||
| } | ||
|
|
||
| @Override | ||
| public String toString() { | ||
| return "WorkerDeploymentVersion{" | ||
| + "deploymentName='" | ||
| + deploymentName | ||
| + '\'' | ||
| + ", buildId='" | ||
| + buildId | ||
| + '\'' | ||
| + '}'; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -22,9 +22,12 @@ | |
|
|
||
| import com.google.common.collect.ImmutableList; | ||
| import io.temporal.common.Experimental; | ||
| import io.temporal.common.VersioningBehavior; | ||
| import io.temporal.internal.common.InternalUtils; | ||
| import io.temporal.internal.common.env.ReflectionUtils; | ||
| import io.temporal.workflow.WorkflowVersioningBehavior; | ||
| import java.lang.reflect.Constructor; | ||
| import java.lang.reflect.Method; | ||
| import java.util.*; | ||
| import java.util.stream.Collectors; | ||
| import javax.annotation.Nullable; | ||
|
|
@@ -68,6 +71,7 @@ public int hashCode() { | |
| } | ||
| } | ||
|
|
||
| private final Class<?> implementationClass; | ||
| private final List<POJOWorkflowInterfaceMetadata> workflowInterfaces; | ||
| private final List<POJOWorkflowMethodMetadata> workflowMethods; | ||
| private final List<POJOWorkflowMethodMetadata> signalMethods; | ||
|
|
@@ -111,6 +115,7 @@ private POJOWorkflowImplMetadata( | |
| throw new IllegalArgumentException("concrete class expected: " + implClass); | ||
| } | ||
|
|
||
| implementationClass = implClass; | ||
| List<POJOWorkflowInterfaceMetadata> workflowInterfaces = new ArrayList<>(); | ||
| Map<String, POJOWorkflowMethodMetadata> workflowMethods = new HashMap<>(); | ||
| Map<String, POJOWorkflowMethodMetadata> queryMethods = new HashMap<>(); | ||
|
|
@@ -238,4 +243,35 @@ public List<POJOWorkflowMethodMetadata> getUpdateValidatorMethods() { | |
| public @Nullable Constructor<?> getWorkflowInit() { | ||
| return workflowInit; | ||
| } | ||
|
|
||
| /** | ||
| * @return The {@link VersioningBehavior} for the workflow method on the implementation class. If | ||
| * the method is annotated with {@link WorkflowVersioningBehavior}. | ||
| * @throws RuntimeException if the method is not found on the implementation class or is not a | ||
| * workflow method. | ||
| */ | ||
| @Experimental | ||
| @Nullable | ||
| public static VersioningBehavior getVersioningBehaviorForMethod( | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We may want to make this a bit more generic if we plan to add other annotations to workflow impl. methods. Since this is experimental I am fine leaving it as is. |
||
| Class<?> implementationClass, POJOWorkflowMethodMetadata workflowMethod) { | ||
| Method method = workflowMethod.getWorkflowMethod(); | ||
| // Find the same method on the implementation class | ||
| Method implMethod; | ||
| try { | ||
| implMethod = implementationClass.getMethod(method.getName(), method.getParameterTypes()); | ||
| } catch (NoSuchMethodException e) { | ||
| throw new RuntimeException( | ||
| "Unable to find workflow method " | ||
| + workflowMethod.getName() | ||
| + " in implementation class " | ||
| + implementationClass.getName(), | ||
| e); | ||
| } | ||
| if (implMethod.isAnnotationPresent(WorkflowVersioningBehavior.class)) { | ||
| WorkflowVersioningBehavior vb = implMethod.getAnnotation(WorkflowVersioningBehavior.class); | ||
| return vb.value(); | ||
| } else { | ||
| return null; | ||
| } | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there an issue tracking the client-side changes? Specifically, version info for list, describe, and scheduling, and the new versioning calls on the client. (asking at top of this file because this stuff is easier in a thread than PR comment and there's no better place)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#2469