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

Dotnet Update Features #418

Merged
merged 5 commits into from
Jan 31, 2024
Merged

Dotnet Update Features #418

merged 5 commits into from
Jan 31, 2024

Conversation

Sushisource
Copy link
Member

What was changed

Added update features for .net

Why?

Checklist

  1. Closes [Feature Request] Update feature tests #266

  2. How was this tested:

  1. Any docs updates needed?

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.

Only minor things. Overally I'm happy to see how legible the C# logic and workflows are.

features/update/basic/feature.cs Show resolved Hide resolved
Comment on lines 1 to 3
using Temporalio.Exceptions;

namespace update.basic_async;
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
using Temporalio.Exceptions;
namespace update.basic_async;
namespace update.basic_async;
using Temporalio.Exceptions;

Namespace first usually

Copy link
Member Author

Choose a reason for hiding this comment

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

yeah, stupid IDE kept doing this

features/update/deduplication/feature.cs Outdated Show resolved Hide resolved
harness/dotnet/Temporalio.Features.Harness/Runner.cs Outdated Show resolved Hide resolved
/// <summary>
/// Stop the worker.
/// </summary>
public void StartWorker()
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 if there would be value in a single RestartWorker call.

Copy link
Member Author

Choose a reason for hiding this comment

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

Maybe, but, it's a bit less flexible

Comment on lines 96 to 100
catch (OperationCanceledException)
{
// No good option here to not get an exception thrown when waiting on potentially
// different worker instances.
}
Copy link
Member

Choose a reason for hiding this comment

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

Might as well move this duplicated exception swallower to inside StopAndWait

)
{
this.workerStopper = workerStopper;
workerTask = worker.ExecuteAsync(workerStopper.Token);
Copy link
Member

@cretz cretz Jan 31, 2024

Choose a reason for hiding this comment

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

Suggested change
workerTask = worker.ExecuteAsync(workerStopper.Token);
workerTask = Task.Run(
async () =>
{
try
{
await worker.ExecuteAsync(workerStopper.Token);
}
catch (Exception e)
{
// Log e
throw;
}
});

The existing code is benefitted by the way we wrote the internals of this call that it's not an async, but by default in .NET tasks don't start just because you invoke a method that returns a task, so Task.Run is best.

Also, technically the problem with the split start/stop approach (and why we avoided it in the .NET worker API) is because you can't see fatal worker exceptions. So that's what the catch here is for. But if we aren't concerned with that, no prob. But you might as well swallow the cancelled exception here.

Copy link
Member Author

Choose a reason for hiding this comment

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

It's not a matter of not being concerned with it - it's that if I need to stop a worker and start a new one at any time, the RunUntil approach just doesn't really fit.

In fact it would be really nice to have a way to stop the worker that doesn't force an exception to be thrown. That feels like a bit of an artificial burden.

Copy link
Member Author

Choose a reason for hiding this comment

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

This seems to work jut fine without Task.Run too - I thought .NET always eagerly Ran tasks? In any case I put it inside Task.Run but w/o the try/catch since that would log every time it's cancelled and would need the special-case for that too, and the task gets awaited on anyway, so any thrown exception will bubble up.

Copy link
Member

@cretz cretz Jan 31, 2024

Choose a reason for hiding this comment

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

In fact it would be really nice to have a way to stop the worker that doesn't force an exception to be thrown. That feels like a bit of an artificial burden.

You can by having something like a task completion source and waiting on it in the lambda passed to worker execute. It's just that normal .NET code that relies on cancellation token is expected to throw that exception, that's why I had to.

I thought .NET always eagerly Ran tasks?

No, unfortunately not (same with Python), but if you write a method that returns a Task instead of an async method that returns a task, that runs eagerly. That's why this worked before, because that's what we did internally.

but w/o the try/catch since that would log every time it's cancelled and would need the special-case for that too, and the task gets awaited on anyway, so any thrown exception will bubble up.

But the exception isn't bubbled up anywhere until StopAndWait. That's why I mentioned logging, just in case of fatal worker failure before we ask it to stop. But I am fine with that if you are.

)
{
this.workerStopper = workerStopper;
workerTask = Task.Run(async () => await worker.ExecuteAsync(workerStopper.Token));
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
workerTask = Task.Run(async () => await worker.ExecuteAsync(workerStopper.Token));
workerTask = Task.Run(() => worker.ExecuteAsync(workerStopper.Token));

I think this should also work, but it's basically the same thing so no need to change.

@Sushisource Sushisource merged commit 69ca251 into main Jan 31, 2024
19 checks passed
@Sushisource Sushisource deleted the dotnet-update-feats branch January 31, 2024 21:43
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.

[Feature Request] Update feature tests
2 participants