Cancel currently running function/goroutine - go

I'm using gin-gonic as HTTP handler. I want to prerender some graphical resources after my users make POST request. For this, I put a middleware that assign a function (with a timer inside) to a map[string]func() and call this function directly after assignation.
The problem is, when the user make two subsequent request, the function is called twice.
Is there any way to clear function ref and/or his currently running call like a clearInterval or clearTimeout in Javascript ?
Thanks

No; whatever function you've scheduled to run as a goroutine needs to either return or call runtime.Goexit.
If you're looking for a way to build cancellation into your worker, Go provides a primitive to handle that, which is already part of any HTTP request - contexts. Check out these articles from the Go blog:
Concurrency Patterns: Context
Pipelines and cancellation

I suppose your rendering function is calling into a library, so you don't have control over the code where the bulk of the time is spent. If you do have such control, just pass a channel into the goroutine, periodically check if the channel is closed, and just return from the goroutine if that happens.
But actually I would recommend a different, and simpler, solution: keep track (in a map) of the file names (or hashes) of the files that are currently being processed, and check that map before launching a second one.

Related

How to test for infinite loop/recursion with ginkgo/gomega?

I have a golang function which recursively steps through a json string and replaces custom references with the json document they are referencing. I just noticed that I forgot to handle cyclic references, whose occurrence will lead to endless recursion.
Before I fix this, I'd like to write a test for this case (using ginkgo/gomega), so I can verify that my solution works and I will notice if I ever break it and run into this problem again.
But how do I do something like if this function call does not return within <timeout>, abort it and fail the test?
Gomega's Eventually has a timeout, but it doesn't abort the function if it is already running, so it will block forever in this case.
I found this example for how to check for a timeout using select and channels, but from what I understood, it is not possible to terminate a goroutine from outside - so my function will continue to run in the background, eating up resources?
What is the best way to check for infinite recursion?
You can't abort a running function. The function has to support abortion, idiomatically through a context.Context or a channel. If you want to support timeout or abortion, you have to change / refactor your function. And the function itself has to support this, e.g. it has to monitor the context.Context and return early if cancellation was requested. For details and example, see Terminating function execution if a context is cancelled
See related:
cancel a blocking operation in Go
Cancelling user specific goroutines

When (how quickly) is a golang child function cancelled when cancelFunc() is called?

I want to access Redis and do a GET on two machines simultaneously. I'll use the first result I get and cancel the other call.
What I'm wondering is whether cancelFunc() breaks a go function immediately or whether it will wait for a specific event to happen before it notices the signal. The documentation just says:
Calling the CancelFunc cancels the child and its children, removes the parent's reference to the child, and stops any associated timers.
That doesn't say whether it happens immediately or whether a special cancellation point needs to be reached.
Any documentation I missed about that particular point?
Canceling a context simply closes its Done channel, it doesn't "kill" a goroutine or anything like that. Code that executes under the context has to do a select to notice the closure of the Done channel and abandon whatever work it's doing.
However in many cases this work is already done for you. If the redis client method you're using to make requests accepts a context, then it's safe to assume that if that context is canceled, the client will handle the cancellation and the method will immediately return an error of context.Canceled — all you need to do is handle that error by quitting what you're doing.

NSUrlConnection synchronous request without accepting redirects

I am currently implementing code that uses macOS API for HTTP/HTTPs requests in a Delphi/Lazarus program.
The code runs in its own thread (i.e. not main/ui thread) and is part of a larger threading based crawler across Windows/Mac and Delphi/Lazarus. I try to implement the actual HTTP/S request part using the OS API - but handle e.g. processing and taking action upon HTTP headers myself.
This means I would like to keep using synchronous mode if possible.
I want the request to simply return to me what the server returns.
I do not want it to follow redirects.
I currently use sendSynchroniousRequest_returningResponse_error
I have tried searching Google, but it seems there is no way when using synchronous requests? That just seems a bit odd.
No, NSURLConnection's synchronous functionality is very limited, and was never expanded because it is so strongly discouraged. That said, it is technically possible to implement what you're trying to do.
My recollection, from having replaced that method with an NSURLSession equivalent once (to swizzle in a less leaky replacement for that method in a binary-only library), is that you need to basically write a method that uses a shared dictionary to store a semaphore for each NSURLSessionDataTask (using the data task as a key). Then, you set the semaphore's count to zero so that it will block immediately when you wait on it, asynchronously start an asynchronous request on the main thread, and then wait on the semaphore (in the current thread). In the asynchronous data task's completion handler block, you increment the semaphore, thus unblocking the calling thread.
The trick is to ensure that the session runs its callbacks on a thread OTHER than the current one (which is blocked waiting for the semaphore). So you'll need to dispatch_async into the main thread when you actually start the data task.
Ostensibly, if you supported converting the task into a download task or stream task in the relevant delegate method, you would also need to take appropriate action to update the shared dictionary as well, but I'm assuming you won't use that feature. :-)

Why MvxCachingFragmentCompatActivity call ExecutePendingTransactions manually?

Use mvvmcross for Xamarin.Android. Why MvxCachingFragmentCompatActivity call ExecutePendingTransactions in ShowFragment method manually? What actions done with this call? As I see, it can takes about second for several devices while navigation.
Thanks
It is basically necessary, if the next actions rely on the handling of the commit() before doing any other action.
For MVVMCross especially:
OnFragmentChanging(fragInfo, ft);
ft.Commit();
SupportFragmentManager.ExecutePendingTransactions();
OnFragmentChanged(fragInfo);
The OnFragmentChanged-Event should obviously only be called if the changes got applied. Just to take one of the code snippets out of MvxCachingFragmentCompatActivity.
From the API documentation.
After a FragmentTransaction is committed with
FragmentTransaction.commit(), it is scheduled to be executed
asynchronously on the process's main thread. If you want to
immediately executing any such pending operations, you can call this
function (only from the main thread) to do so. Note that all callbacks
and other related behavior will be done from within this call, so be
careful about where this is called from.

Flux Dispatch.dispatch(...): Cannot dispatch in the middle of a dispatch

My code
https://gist.github.com/ButuzGOL/707d1605f63eef55e4af
So when I get sign-in success callback I want to make redirect,
redirect works through dispatcher too.
And I am getting Dispatch.dispatch(...): Cannot dispatch in the middle of a dispatch.
Is there any hack to call action in the middle ?
I don't see where in the gist that you posted you are doing the redirect. I only see the AUTH_SIGNIN and AUTH_SIGNIN_SUCCESS actions, and they look pretty straightforward.
But no, there is no hack to create an action in the middle of a dispatch, and this is by design. Actions are not supposed to be things that cause a change. They are supposed to be like a newspaper that informs the application of a change in the outside world, and then the application responds to that news. The stores cause changes in themselves. Actions just inform them.
If you have this error, then you need to back up and look at how you're handling the original action. Most often, you can set up your application to respond to the original action, accomplish everything you need to do, and avoid trying to create a second action.
You can make it work by "scheduling" the next action instead of calling it directly, here is an example code:
// instead of doing this
Dispatcher.dispatch(...);
// go like this
setTimeout(function() {
Dispatcher.dispatch(...);
}, 1);
This will cause your next dispatch to be called later out of the current dispatch process, and no error will happen.
If your dispatch code is on a callback any kind of other async operation that will work as well (for example in a response for an Ajax request).
I'm using this style to make some forms respond to generic data here and I'm facing no issue, at least the way I'm using it.
you can user the "defer" option in the dispatcher.
In your case it would be like:
Dispatcher.dispatch.defer(...);
You can check if the dispatcher is dispatching, such as:
if(!MyDispatcher.isDispatching()) {
MyDispatcher.dispatch({...});
}

Resources