Cancellation token is a light weight struct. Its copied by value. And it is meant to be passed down to separate levels of the functions.
So It is okay to pass cancellation token as much as you want.
But make sure your cancellation is always tied with a single operation. If the operation is cancelled, it is cancelled. You cant revert the cancellation and re use the token.
As long as you keep that in mind for the design, it seems your way of passing the cancellation token is correct.
And the other option you have is to create a separate cancellation token. To do so you will need to create a new CancellationTokenSource. This is a disposable object. So you will have to carefully dispose it after its usage is ended. And it is not light weight compared to CancellationToken. Therefore if you are not logically starting a new operation that can be cancelled, I do not recommend to use a new CancellationTokenSource.
For more information have a look at documentation
Important parts extracted from documentation,
1)
The object that invokes one or more cancelable operations, for example by creating new threads or tasks, passes the token to each operation. Individual operations can in turn pass copies of the token to other operations. At some later time, the object that created the token can use it to request that the operations stop what they are doing.
2)
In the new cancellation framework, cancellation refers to operations, not objects. The cancellation request means that the operation should stop as soon as possible after any required cleanup is performed. One cancellation token should refer to one "cancelable operation," however that operation may be implemented in your program. After the IsCancellationRequested property of the token has been set to true, it cannot be reset to false. Therefore, cancellation tokens cannot be reused after they have been canceled.
3)
The CancellationTokenSource class implements the IDisposable interface. You should be sure to call the CancellationTokenSource.Dispose method when you have finished using the cancellation token source to free any unmanaged resources it holds
TLDR;
Simply pass the token to all layers that may need it, and in each layer check whether IsCancellationIsRequested is true.
Long... requires some thought across sessions and requests...
On the request side, you need to have some sort of key. This key could be a GUID or some other unique, munged ID associated with the request. This is quite literally the key to everything that a particular user may do soon. This key (string) must map back to a . It can be stored in CancellationTokenSource or some other ephemeral store associated back to your user.HttpContext.Session
This means a few things.
Start the (possibly cancellable) Web API request (Db access or whatever) as an awaitable task, and, using this keyed task (This should run in the backgound), immediately return a HTTP or DELETE response with the cancelled task's info (it wasn't clear from your question whether the operation was a delete or a modify... I'm wording this as a delete, but the principle should be the same).POST
With this key, you've got it in the session state, and you can pass it on through any other layers of your solution. For example, you can
This cancellation token can be propagated to any or all layers of your software solution (see: https://devblogs.microsoft.com/premier-developer/recommended-patterns-for-cancellationtoken/).
Cancellation is done, on demand, by the user or a system call; in your case that could be a simple button click. At that point, any calls on any threads that check for cancellation will cancel their operations (if you so code, and you should). Why/how? You literally pass this token through every layer as part of a constructor call or other method, and in every layer check to see if the operation is cancelled (cooperative) or skip the checks and handle OperationCancelledOperation.
Promises have settled (hah) and it appears like it will never be possible to cancel a (pending) promise.
Instead, there is a cross-platform (Node, Browsers etc) cancellation primitive as part of WHATWG (a standards body that also builds HTML) called . You can use it to cancel functions that return promises rather than promises themselves:AbortController
// Take a signal parameter in the function that needs cancellation
async function somethingIWantToCancel({ signal } = {}) {
// either pass it directly to APIs that support it
// (fetch and most Node APIs do)
const response = await fetch('.../', { signal });
// return response.json;
// or if the API does not already support it -
// manually adapt your code to support signals:
const onAbort = (e) => {
// run any code relating to aborting here
};
signal.addEventListener('abort', onAbort, { once: true });
// and be sure to clean it up when the action you are performing
// is finished to avoid a leak
// ... sometime later ...
signal.removeEventListener('abort', onAbort);
}
// Usage
const ac = new AbortController();
setTimeout(() => ac.abort(), 1000); // give it a 1s timeout
try {
await somethingIWantToCancel({ signal: ac.signal });
} catch (e) {
if (e.name === 'AbortError') {
// deal with cancellation in caller, or ignore
} else {
throw e; // don't swallow errors :)
}
}
ES6 promises do not support cancellation yet. It's on its way, and its design is something a lot of people worked really hard on. Sound cancellation semantics are hard to get right and this is work in progress. There are interesting debates on the "fetch" repo, on esdiscuss and on several other repos on GH but I'd just be patient if I were you.
It is, the reality of the matter is cancellation is really an important scenario in client-side programming. The cases you describe like aborting web requests are important and they're everywhere.
Yeah, sorry about that. Promises had to get in first before further things were specified - so they went in without some useful stuff like and .finally - it's on its way though, to the spec through the DOM. Cancellation is not an afterthought it's just a time constraint and a more iterative approach to API design..cancel
You have several alternatives:
Using a third party library is pretty obvious. As for a token, you can make your method take a function in and then call it, as such:
function getWithCancel(url, token) { // the token is for cancellation
var xhr = new XMLHttpRequest;
xhr.open("GET", url);
return new Promise(function(resolve, reject) {
xhr.onload = function() { resolve(xhr.responseText); });
token.cancel = function() { // SPECIFY CANCELLATION
xhr.abort(); // abort request
reject(new Error("Cancelled")); // reject the promise
};
xhr.onerror = reject;
});
};
Which would let you do:
var token = {};
var promise = getWithCancel("/someUrl", token);
// later we want to abort the promise:
token.cancel();
lastThis isn't too hard with the token approach:
function last(fn) {
var lastToken = { cancel: function(){} }; // start with no op
return function() {
lastToken.cancel();
var args = Array.prototype.slice.call(arguments);
args.push(lastToken);
return fn.apply(this, args);
};
}
Which would let you do:
var synced = last(getWithCancel);
synced("/url1?q=a"); // this will get canceled
synced("/url1?q=ab"); // this will get canceled too
synced("/url1?q=abc"); // this will get canceled too
synced("/url1?q=abcd").then(function() {
// only this will run
});
And no, libraries like Bacon and Rx don't "shine" here because they're observable libraries, they just have the same advantage user level promise libraries have by not being spec bound. I guess we'll wait to have and see in ES2016 when observables go native. They are nifty for typeahead though.
I think you are thinking in a great way, I do not think you need to regret or repent.
This is a great idea, I also thought about it, and I implement my own solutionpublic abstract class RequestCancellationBase
{
public abstract CancellationToken Token { get; }
public static implicit operator CancellationToken(RequestCancellationBase requestCancellation) =>
requestCancellation.Token;
}
public class RequestCancellation : RequestCancellationBase
{
private readonly IHttpContextAccessor _context;
public RequestCancellation(IHttpContextAccessor context)
{
_context = context;
}
public override CancellationToken Token => _context.HttpContext.RequestAborted;
}
and the registration should be like this
services.AddHttpContextAccessor();
services.AddScoped<RequestCancellationBase, RequestCancellation>();
now you can inject wherever you want, RequestCancellationBase
CancellationToken this is because of public static implicit operator CancellationToken(RequestCancellationBase requestCancellation)this solution helped me, hope it is helpful for you also
If there exists an inverse to the transaction (e.g. Send 3 DAO tokens from account A to account B has the inverse of sending 3 tokens from B to A), one can execute the inverse transaction. Note that a contract may implement something or an account holder may do something that is not reversible (e.g., it may burn tokens). Also note that this results in two transactions (the original plus the inverse) which both are recorded permanently in the blockchain. This also means that the transaction fees are incurred for both transactions.
If (and only if) Ethereum is not broken, the private key of the recipient is required to send a reversing transaction from an account. TODO: please add something about sending stuff as a contract (i.e., is there a private key, even if no one knows it, associated with contracts?). In situations where you do not have the private key (such as if you send ether to an exchange and you don't receive an appropriate account balance adjustment), then you must ask the recipient to perform the reversing transaction (and hope they have the private key). If the recipient is a company, you should contact their support staff. Stack exchange members (unless they happen to work at the company in question) cannot help you.
If the transaction has not yet been confirmed in the blockchain and is only in the transaction pool, you can replace the transaction. This is as close as you can get to cancelling a transaction. Note that this still results in a transaction occurring (and gas being paid for).
One way of replacing an unconfirmed transaction is to repost a replacement transaction with the same nonce but a higher gas price; a possible replacement transaction is to post a 0-value balance transfer with yourself as the recipient. It might be a bad idea to set a very low gas limit in case such a transaction is filtered out by a miner. This method can only be used to replace a transaction you have sent. This method works to replace any kind of transaction -- including ones for interacting with contracts such as tokens.
Since the current state of the blockchain is based on the history of the blockchain, one way of reversing a transaction is to rewrite the blockchain history starting from at least the block containing the transaction to be reversed. Forking the blockchain intentionally like this may have negative consequences for the overall Ethereum network.
The accepted current state of the blockchain is the longest chain. One could build a longer chain than the current chain. One way of doing this is to append blocks to the chain faster than people mining the chain containing the transaction to be reversed (the "honest" network). In order to do this (with reasonable statistical success), you need to have more hash power than the honest network. If is the hash rate of the honest miners, your hash rate is r, and r + x is the amount of time expected for the network to have taken to make the number of confirmations on the block with the transaction to be reversed (or, as a first approximation, the amount of time since the block containing the transaction to be reversed was mined), then the expected time to reverse the transaction is t, so if you have 51% of the network and you want to reverse the most recent 120 blocks with an expected block time of 30 seconds (=1 hour of mining), it would take you just over a day to reverse the transaction (rt/x). Possessing (or having access to) this kind of hashing power might shake confidence in transactions on the network.49 * 1 hour / 2
If you can convince people securing the network (currently, this is miners) to change their mining software, you can change the rules of the network so that the transaction is reversed. Forking the network in this manner may be contentious.
If you performed a transaction with someone and are unhappy with the outcome, you can try using the legal system. The legal system may compel the offending party to make good; some countries also can crack the private keys for an Ethereum account. There is nothing in Ethereum itself that allows breaking the rules of Ethereum (obviously?). The closest you can get is to make an amendment to the rules of Ethereum or a one time pardon. This is accomplished via forking (see above).