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

Workflow-friendly concurrency primitives #2133

Merged
merged 4 commits into from
Jul 30, 2024

Conversation

Quinn-With-Two-Ns
Copy link
Contributor

Add Workflow-friendly concurrency primitives. This PR adds a workflow safe Mutex and Semaphore based on the Java interfaces

@Quinn-With-Two-Ns Quinn-With-Two-Ns requested a review from a team as a code owner July 3, 2024 19:08
Copy link
Member

@cretz cretz left a comment

Choose a reason for hiding this comment

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

LGTM, just one minor check on the cancellation throw inside the await callback

WorkflowInternal.await(
"WorkflowLock.lock",
() -> {
CancellationScope.throwCanceled();
Copy link
Member

Choose a reason for hiding this comment

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

Looking at javadoc for Workflow.await it should automatically cancel the await and throw if outer scoped is cancelled right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, but this is calling WorkflowInternal.await which does not cancel by default. I use WorkflowInternal.await to override the wait message.

Copy link
Member

Choose a reason for hiding this comment

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

I wonder then if this should just return if cancelled or lock available, and then issue the actual throw outside of the lambda. But so long as the exception propagates to the user, works for me.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah it will be propagated, this is how Workflow.await is implemented by the java SDK

@Override
public void acquire(int permits) {
Preconditions.checkArgument(
permits > 0, "WorkflowSemaphore.acquire called with negative permits");
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
permits > 0, "WorkflowSemaphore.acquire called with negative permits");
permits > 0, "WorkflowSemaphore.acquire called with non-positive permits");

Pedantic though

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Checking Java's semaphore, the exception message was correct the check should be >=

Copy link
Member

Choose a reason for hiding this comment

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

To me it's a bit strange to allow 0 permits (I can't think of a a use case), but it's harmless.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah just copying Java's Semaphore here

assertNotReadOnly("WorkflowSemaphore.release");
Preconditions.checkArgument(
permits > 0, "WorkflowSemaphore.release called with negative permits");
currentPermits += permits;
Copy link
Member

Choose a reason for hiding this comment

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

Not a big deal, but could add a final field for the number initially given and throw if this exceeds that number (but again not a big deal and maybe existing Java semaphore doesn't)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I didn't add that to match Java's semaphore. I also documented and tested this part of the API.

*
* @return true if the lock is held and false otherwise.
*/
boolean isHeld();
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@cretz I added this API since you reviewed, I added it to support checking the mutex in a validator.

Copy link
Member

Choose a reason for hiding this comment

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

LGTM. Arguably semaphore should also provide its currently held/acquired count to users.

*
* @return true if the lock is held and false otherwise.
*/
boolean isHeld();
Copy link
Member

Choose a reason for hiding this comment

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

LGTM. Arguably semaphore should also provide its currently held/acquired count to users.

@Quinn-With-Two-Ns Quinn-With-Two-Ns merged commit b92c97d into temporalio:master Jul 30, 2024
8 checks passed
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.

2 participants