forked from microsoft/durabletask-java
-
Notifications
You must be signed in to change notification settings - Fork 10
Improve GrpcWorker shutdown #30
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
Merged
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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,3 @@ | ||
| # Enable auto-env through the sdkman_auto_env config | ||
| # Add key=value pairs of SDKs to use below | ||
| java=11.0.27-tem |
This file contains hidden or 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 |
|---|---|---|
|
|
@@ -20,7 +20,8 @@ | |
| import java.util.logging.Logger; | ||
|
|
||
| /** | ||
| * Task hub worker that connects to a sidecar process over gRPC to execute orchestrator and activity events. | ||
| * Task hub worker that connects to a sidecar process over gRPC to execute | ||
| * orchestrator and activity events. | ||
| */ | ||
| public final class DurableTaskGrpcWorker implements AutoCloseable { | ||
|
|
||
|
|
@@ -39,6 +40,7 @@ public final class DurableTaskGrpcWorker implements AutoCloseable { | |
| private final TaskHubSidecarServiceBlockingStub sidecarClient; | ||
| private final boolean isExecutorServiceManaged; | ||
| private volatile boolean isNormalShutdown = false; | ||
| private Thread workerThread; | ||
|
|
||
| DurableTaskGrpcWorker(DurableTaskGrpcWorkerBuilder builder) { | ||
| this.orchestrationFactories.putAll(builder.orchestrationFactories); | ||
|
|
@@ -66,43 +68,58 @@ public final class DurableTaskGrpcWorker implements AutoCloseable { | |
|
|
||
| this.sidecarClient = TaskHubSidecarServiceGrpc.newBlockingStub(sidecarGrpcChannel); | ||
| this.dataConverter = builder.dataConverter != null ? builder.dataConverter : new JacksonDataConverter(); | ||
| this.maximumTimerInterval = builder.maximumTimerInterval != null ? builder.maximumTimerInterval : DEFAULT_MAXIMUM_TIMER_INTERVAL; | ||
| this.maximumTimerInterval = builder.maximumTimerInterval != null ? builder.maximumTimerInterval | ||
| : DEFAULT_MAXIMUM_TIMER_INTERVAL; | ||
| this.workerPool = builder.executorService != null ? builder.executorService : Executors.newCachedThreadPool(); | ||
| this.isExecutorServiceManaged = builder.executorService == null; | ||
| } | ||
|
|
||
| /** | ||
| * Establishes a gRPC connection to the sidecar and starts processing work-items in the background. | ||
| * Establishes a gRPC connection to the sidecar and starts processing work-items | ||
| * in the background. | ||
| * <p> | ||
| * This method retries continuously to establish a connection to the sidecar. If a connection fails, | ||
| * a warning log message will be written and a new connection attempt will be made. This process | ||
| * continues until either a connection succeeds or the process receives an interrupt signal. | ||
| * This method retries continuously to establish a connection to the sidecar. If | ||
| * a connection fails, | ||
| * a warning log message will be written and a new connection attempt will be | ||
| * made. This process | ||
| * continues until either a connection succeeds or the process receives an | ||
| * interrupt signal. | ||
| */ | ||
| public void start() { | ||
| new Thread(this::startAndBlock).start(); | ||
| this.workerThread = new Thread(this::startAndBlock); | ||
| this.workerThread.start(); | ||
|
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. This is the real change |
||
| } | ||
|
|
||
| /** | ||
| * Closes the internally managed gRPC channel and executor service, if one exists. | ||
| * Closes the internally managed gRPC channel and executor service, if one | ||
| * exists. | ||
| * <p> | ||
| * Only the internally managed GRPC Channel and Executor services are closed. If any of them are supplied, | ||
| * Only the internally managed GRPC Channel and Executor services are closed. If | ||
| * any of them are supplied, | ||
| * it is the responsibility of the supplier to take care of them. | ||
| */ | ||
| public void close() { | ||
| this.workerThread.interrupt(); | ||
|
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. This is the real change |
||
| this.isNormalShutdown = true; | ||
| this.shutDownWorkerPool(); | ||
| this.closeSideCarChannel(); | ||
| } | ||
|
|
||
| /** | ||
| * Establishes a gRPC connection to the sidecar and starts processing work-items on the current thread. | ||
| * This method call blocks indefinitely, or until the current thread is interrupted. | ||
| * Establishes a gRPC connection to the sidecar and starts processing work-items | ||
| * on the current thread. | ||
| * This method call blocks indefinitely, or until the current thread is | ||
| * interrupted. | ||
| * <p> | ||
| * Use can alternatively use the {@link #start} method to run orchestration processing in a background thread. | ||
| * Use can alternatively use the {@link #start} method to run orchestration | ||
| * processing in a background thread. | ||
| * <p> | ||
| * This method retries continuously to establish a connection to the sidecar. If a connection fails, | ||
| * a warning log message will be written and a new connection attempt will be made. This process | ||
| * continues until either a connection succeeds or the process receives an interrupt signal. | ||
| * This method retries continuously to establish a connection to the sidecar. If | ||
| * a connection fails, | ||
| * a warning log message will be written and a new connection attempt will be | ||
| * made. This process | ||
| * continues until either a connection succeeds or the process receives an | ||
| * interrupt signal. | ||
| */ | ||
| public void startAndBlock() { | ||
| logger.log(Level.INFO, "Durable Task worker is connecting to sidecar at {0}.", this.getSidecarAddress()); | ||
|
|
@@ -117,7 +134,6 @@ public void startAndBlock() { | |
| this.dataConverter, | ||
| logger); | ||
|
|
||
| // TODO: How do we interrupt manually? | ||
| while (true) { | ||
| try { | ||
| GetWorkItemsRequest getWorkItemsRequest = GetWorkItemsRequest.newBuilder().build(); | ||
|
|
@@ -145,11 +161,17 @@ public void startAndBlock() { | |
| this.sidecarClient.completeOrchestratorTask(response); | ||
| } catch (StatusRuntimeException e) { | ||
| if (e.getStatus().getCode() == Status.Code.UNAVAILABLE) { | ||
| logger.log(Level.WARNING, "The sidecar at address {0} is unavailable while completing the orchestrator task.", this.getSidecarAddress()); | ||
| logger.log(Level.WARNING, | ||
| "The sidecar at address {0} is unavailable while completing the orchestrator task.", | ||
| this.getSidecarAddress()); | ||
| } else if (e.getStatus().getCode() == Status.Code.CANCELLED) { | ||
| logger.log(Level.WARNING, "Durable Task worker has disconnected from {0} while completing the orchestrator task.", this.getSidecarAddress()); | ||
| logger.log(Level.WARNING, | ||
| "Durable Task worker has disconnected from {0} while completing the orchestrator task.", | ||
| this.getSidecarAddress()); | ||
| } else { | ||
| logger.log(Level.WARNING, "Unexpected failure completing the orchestrator task at {0}.", this.getSidecarAddress()); | ||
| logger.log(Level.WARNING, | ||
| "Unexpected failure completing the orchestrator task at {0}.", | ||
| this.getSidecarAddress()); | ||
| } | ||
| } | ||
| }); | ||
|
|
@@ -189,29 +211,35 @@ public void startAndBlock() { | |
| this.sidecarClient.completeActivityTask(responseBuilder.build()); | ||
| } catch (StatusRuntimeException e) { | ||
| if (e.getStatus().getCode() == Status.Code.UNAVAILABLE) { | ||
| logger.log(Level.WARNING, "The sidecar at address {0} is unavailable while completing the activity task.", this.getSidecarAddress()); | ||
| logger.log(Level.WARNING, | ||
| "The sidecar at address {0} is unavailable while completing the activity task.", | ||
| this.getSidecarAddress()); | ||
| } else if (e.getStatus().getCode() == Status.Code.CANCELLED) { | ||
| logger.log(Level.WARNING, "Durable Task worker has disconnected from {0} while completing the activity task.", this.getSidecarAddress()); | ||
| logger.log(Level.WARNING, | ||
| "Durable Task worker has disconnected from {0} while completing the activity task.", | ||
| this.getSidecarAddress()); | ||
| } else { | ||
| logger.log(Level.WARNING, "Unexpected failure completing the activity task at {0}.", this.getSidecarAddress()); | ||
| logger.log(Level.WARNING, "Unexpected failure completing the activity task at {0}.", | ||
| this.getSidecarAddress()); | ||
| } | ||
| } | ||
| }); | ||
| } | ||
| else if (requestType == RequestCase.HEALTHPING) | ||
| { | ||
| } else if (requestType == RequestCase.HEALTHPING) { | ||
| // No-op | ||
| } else { | ||
| logger.log(Level.WARNING, "Received and dropped an unknown '{0}' work-item from the sidecar.", requestType); | ||
| logger.log(Level.WARNING, "Received and dropped an unknown '{0}' work-item from the sidecar.", | ||
| requestType); | ||
| } | ||
| } | ||
| } catch (StatusRuntimeException e) { | ||
| if (e.getStatus().getCode() == Status.Code.UNAVAILABLE) { | ||
| logger.log(Level.INFO, "The sidecar at address {0} is unavailable. Will continue retrying.", this.getSidecarAddress()); | ||
| logger.log(Level.INFO, "The sidecar at address {0} is unavailable. Will continue retrying.", | ||
| this.getSidecarAddress()); | ||
| } else if (e.getStatus().getCode() == Status.Code.CANCELLED) { | ||
| logger.log(Level.INFO, "Durable Task worker has disconnected from {0}.", this.getSidecarAddress()); | ||
| } else { | ||
| logger.log(Level.WARNING, String.format("Unexpected failure connecting to %s", this.getSidecarAddress()), e); | ||
| logger.log(Level.WARNING, | ||
| String.format("Unexpected failure connecting to %s", this.getSidecarAddress()), e); | ||
| } | ||
|
|
||
| // Retry after 5 seconds | ||
|
|
@@ -225,7 +253,8 @@ else if (requestType == RequestCase.HEALTHPING) | |
| } | ||
|
|
||
| /** | ||
| * Stops the current worker's listen loop, preventing any new orchestrator or activity events from being processed. | ||
| * Stops the current worker's listen loop, preventing any new orchestrator or | ||
| * activity events from being processed. | ||
| */ | ||
| public void stop() { | ||
| this.close(); | ||
|
|
@@ -246,7 +275,8 @@ private void closeSideCarChannel() { | |
| private void shutDownWorkerPool() { | ||
| if (this.isExecutorServiceManaged) { | ||
| if (!this.isNormalShutdown) { | ||
| logger.log(Level.WARNING, "ExecutorService shutdown initiated unexpectedly. No new tasks will be accepted"); | ||
| logger.log(Level.WARNING, | ||
| "ExecutorService shutdown initiated unexpectedly. No new tasks will be accepted"); | ||
| } | ||
|
|
||
| this.workerPool.shutdown(); | ||
|
|
||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
This is the real change