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

Add Queue.QueueCancellableInvocableWithPayload method #209

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

mrb0nj
Copy link

@mrb0nj mrb0nj commented Jan 2, 2021

Implements both ICancellableTask and IInvocableWithPayload for Issue #182

mrb0nj added 2 commits January 2, 2021 07:08
Implements both ICancellableTask and IInvocableWithPayload<TParams>
@jamesmh
Copy link
Owner

jamesmh commented Jan 7, 2021

Thanks! I'm going to be away for a few weeks most likely, just FYI. Will check this out when things settle down for me 👍

@achmstein
Copy link

Hi,

I cannot find QueueCancellableInovcableWithPayload method in Coravel package.

Can you help me?

@lengockyquang
Copy link

Waiting for this pull request merge !

@jamesmh
Copy link
Owner

jamesmh commented Jan 5, 2022

Thanks again for this. I have some minor suggestions :)

What if instead of returning the CancellationToken to the caller, we would add a new method on the IQueue like void Cancel(string uniqueIdentifier). Since the queue does "stuff" like cancel tokens and removes them from the collection of "tracked" tokens, returning a token to the caller is much like a leaky abstraction. It could potentially also lead to unexpected issues like:

  1. Caller gets the token back
  2. Queue runs, disposes the token
  3. Caller tries to cancel but gets an exception.
  4. Even if the caller wraps their cancellation calls with a "check", the queue, concurrently, could still dispose that token, leading to intermittent exceptions even if the caller is doing "proper" checks.

So I think it best to keep cancellation logic internal, so that we have more control over the concurrency, etc. of these things.

If the token exists and is not cancelled, then cancel it. Like this existing method does. You won't have to remove the token since that logic already exists whenever the jobs are invoked. By using the concurrent dict you'll just have to make sure you use this method to get access to the token (otherwise, if you used ContainsKey() and then tried to fetch the value via an index method you might get a concurrency exception. The item could be removed by another thread just after the call to ContainsKey() but before you fetch the value. TryGetValue() makes sure you just do the "check" and "fetch" atomically.)

Also, internally it's possible to have the same concurrency issue as mentioned at the beginning of my comment. It might be worth catching ObjectDisposedException as mentioned here.

What do you think? Did I miss something? Does that make sense?

@jamesmh
Copy link
Owner

jamesmh commented Jan 5, 2022

More on the comment above, eventually I actually think removing QueueCancellableInvocable might make sense.

In the other queue methods, we would simply check if the invocable in question implements ICancellableTask.

Doing this right now might make sense - don't create a new method QueueCancellableInvocableWithPayload, but check within QueueInvocableWithPayload if the task implements ICancellableTask and add a new token internally + the new method mentioned in the comment above. In fact, doing this for all existing "queue" methods now would work well, and then I'll look at setting up a long-term schedule to depreciate the other methods as part of a major release, etc.

The existing logic, I believe, is susceptible right now to the ObjectDisposedException... so that is just one other reason why keeping all this logic internal has a benefit (e.g. we can handle that exception internally and the caller doesn't need to know about how to use tokens. The UX becomes way simpler for the caller).

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.

4 participants