I was told that if I want to use predis-async, then I will use some kind of async web framework (probably built using https://github.com/reactphp/react). I am currently using Yii.
I was also told that
$client->getEventLoop()->run();
That line will start event loop which won't return after all connections to Redis are terminated and all callbacks are invoked. So that means that this line will be blocking for your code. Try to run following code (the simplest code illustrating Predis Async usage):
$client = new Predis\Async\Client('tcp://127.0.0.1:6379');
$client->set('test', 'value');
$client->getEventLoop()->run();
echo 'END';
END won't be probably displayed for a long time or maybe never, but for sure it will take more than the same operation using non-Async
Predis.
However, my own understanding is that existing PHP system should be able to use Predis Async right out of the box, as a lib. Which means existing PHP system does not need to be on ReactPHP. My idea of using predis async is similar to using mongodb asynchronous
commit. When PHP calls mongodb lib to commit a write operation, it is
asynchronous. Mongodb immediately returns the call rather than waiting for
the write happens first. In this case, mongodb doesn't requires
asynchronous php framework too.
Is it true that
END won't be probably displayed for a long time or maybe never, but
for sure it will take more than the same operation using non-Async
Predis.
Related
Is there any way to tell in ASP.NET Core if any given middleware will contain a Run() call which will stop the pipeline? It seems that UseMvc() is one big one, but I am not even certain about that, I just keep reading that it needs to go at the end, I assume it is because it contains a call to Run().
Perhaps there is a way to generate a visualisation of the pipeline for all middleware currently in use, showing which one contains the Run() call?
There is no sure way to tell, beyond reading documentation on each specific piece of middleware.
quoting itminus in the comments on my question:
Not only Run(), but also MapWhen() will terminate the process. Also, anyone could create a custom middleware that doesn't invoke the next delegate and then cause to a terminate.
It's the duty of middleware to determine whether there's a need to to call next. There's no built-in way to visualize the pipeline except you read the document/source code. That's because all the middlewares will be built into a single final delegate at startup time. When there's an incoming message, the final delegate will be used to process requests. As a programmer, we know what will be done by the middlewares, we know the time when it branches, and we know the time it terminates that's because we write the code. But the program won't know it until it actually runs just because the final delegate is built at startup time.
Currently, we are using StackExchange.Redis and, as it does not provides "blocking pops", we are doing as suggested on the documentation:
db.ListLeftPush(key, newWork, flags: CommandFlags.FireAndForget);
sub.Publish(channel, "");
What is the difference from this to the following?
db.ListLeftPushAsync(key, newWork);
sub.Publish(channel, "");
We know the purpose of the commands, what we would like to know is if it has any difference internally or any risk of behaving differently? (Execution order etc.)
There's a main difference comparing fire and forget vs calling an async operation and not awaiting it.
Fire and forget means that not only you're not waiting for the result but you don't care if it works or not, while an async operation may throw an exception once it has ended if something goes wrong.
In the other hand, when you issue a fire and forget command, StackExchange.Redis doesn't try to retrieve the command result internally, which is better if you just want the so-called fire and forget behavior when issuing commands.
You may check this difference if you open ConnectionMultiplexer source code and you see how ExecuteAsyncImpl / ExecuteSyncImpl methods are implemented:
// For example, ExecuteAsyncImpl...
if (message.IsFireAndForget)
{
TryPushMessageToBridge(message, processor, null, ref server);
return CompletedTask<T>.Default(null); // F+F explicitly does not get async-state
}
else
{
var tcs = TaskSource.CreateDenyExecSync<T>(state);
var source = ResultBox<T>.Get(tcs);
if (!TryPushMessageToBridge(message, processor, source, ref server))
{
ThrowFailed(tcs, ExceptionFactory.NoConnectionAvailable(IncludeDetailInExceptions, message.Command, message, server));
}
return tcs.Task;
}
Answer to some OP comment
Hi. Thanks for your answer. We know the purpose of the commands, what
we would like to know is if it has any differrence internally or any
risk of behaving differently (execution order etc.)
Since the async operation won't be finished when you publish the message on the Redis channel, it can happen that you publish the message and the operation gets executed never. You lose a lot of control.
When you send a fire and forget command, it mightn't be executed too, but you know that the try was done before you publish the channel's message. Therefore, you shouldn't use async operations to implement fire and forget pattern when using StackExchange.Redis.
You may check this other related Q&A: Stackexchange.redis does fire and forget guarantees delivery?
My store.sync() can return success:false, and if it does, I would like to use something similar to Ext's failure callback to react to the error appropriately, but I did not find a possibility to use any builtin ST functions for this. sync has neither callback nor success nor failure option available in ST.
What did I overlook?
PS: I did find a workaround for success callback at Why is there no sync callback in Sencha Touch? but I need failure callback.
store.sync() is not where you need to look. Take a look at the proxy. Most likely you are using an Ajax request and that in turn will deliver a detailed success and failure.
I am now calling Ext.data.Model.save() on all Ext.data.Model instances that are dirty. This won't batch everything neatly together, but in 90% of the cases, only one item is edited anyways. The best is that this allows to check for failure on each and every item, and not only on the whole batch.
I am trying to write a control panel to
Inform about certain KPIS
Enable the user to init certain requests / jobs by pressing a button that then runs a stored proc on the DB or sets a specific setting etc
So far, so good, except I would like to run some bigger jobs where the length of time that the job is running for is unknown and could run over both the script timeout period AND the time the user is willing to wait for a response.
What I want is a "fire and forget" process so the user hits the button and even if they kill the page or turn off their phone they know the job has been initiated and WILL complete.
I was looking into C# BeginExecuteNonQuery which is an async call to the query so the proc is fired but the control doesn't have to wait for a response from it to carry on. However I don't know what happens when the page/app that fired it is shut.
Also I was thinking of some sort of Ajax command that fires the code in a page behind the scenes so the user doesn't know about it running but then again I believe if the user shuts the page down the script will die and the command will die on the server as well.
The only way for certain I know of is a "queue" table where jobs are inserted into this table then an MS Agent job comes along every minute or two checking for new inserts and then runs the code if there is any. That way it is all on the DB and only a DB crash will destroy it. It won't help with multiple jobs waiting to be run concurrently that both take a long time but it's the only thing I can be sure of that will ensure the code is run at all.
Any ideas?
Any language is okay.
Since web browsers are unconnected, requests from them always take the full amount of time. The governing factor isn't what the browser does, but how long the web site itself will allow an action to continue.
IIS (and in general, web servers) have a timeout period for requests, where if the work being done takes simply too long, the request is terminated. This would involve abruptly stopping whatever is taking so long, such as a database call, running code, and so on.
Simply making your long-running actions asynchronous may seem like a good idea, however I would recommend against that. The reason is that in ASP and ASP.Net, asynchronously-called code still consumes a thread in a way that blocks other legitimate request from getting through (in some cases you can end up consuming two threads!). This could have performance implications in non-obvious ways. It's better to just increase the timeout and allow the synchronously blocking task to complete. There's nothing special you have to do to make such a request complete fully, it will occur even if the sender closes his browser or turns off his phone immediately after (presuming the entire request was received).
If you're still concerned about making certain work finish, no matter what is going on with the web request, then it's probably better to create an out-of-process server/service that does the work and to which such tasks can be handed off. Your web site then invokes a method that, inside the service, starts its own async thread to do the work and then immediately returns. Perhaps it also returns a request ID, so that the web page can check on the status of the requested work later through other methods.
You may use asynchronous method and call the query from this method.
Your simple method can be changed in to a asynch method in the following manner.
Consider that you have a Test method to be called asynchronously -
Class AsynchDemo
{
public string TestMethod(out int threadId)
{
//call your query here
}
//create a asynch handler delegate:
public delegate string AsyncMethodCaller(out int threadId);
}
In your main program /or where you have to call the Test Method:
public static void Main()
{
// The asynchronous method puts the thread id here.
int threadId;
// Create an instance of the test class.
AsyncDemo ad = new AsyncDemo();
// Create the delegate.
AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod);
// Initiate the asychronous call.
IAsyncResult result = caller.BeginInvoke(
out threadId, null, null);
// Call EndInvoke to wait for the asynchronous call to complete,
// and to retrieve the results.
string returnValue = caller.EndInvoke(out threadId, result);
Console.WriteLine("The call executed on thread {0}, with return value \"{1}\".",
threadId, returnValue);
}
From my experience a Classic ASP or ASP.NET page will run until complete, even if the client disconnects, unless you have something in place for checking that the client is still connected and do something if they are not, or a timeout is reached.
However, it would probably be better practice to run these sorts of jobs as scheduled tasks.
On submitting your web page could record in a database that the task needs to be run and then when the scheduled task runs it checks for this and starts the job.
Many web hosts and/or web control panels allow you to create scheduled tasks that call a URL on schedule.
Alternately if you have direct access to the web server you could create a scheduled task on the server to call a URL on schedule.
Or, if ASP.NET, you can put some code in global.asax to run on a schedule. Be aware though, if your website is set to stop after a certain period of inactivity then this will not work unlesss there is frequent continuous activity.
I would like my node.js tests to ensure that, once the test is over and test.finish() or similar is called, that there is no more code waiting to be run. No more I/O waiting to finish, no more timers waiting to fire, etc. etc.
Is this possible in node.js?
When using nodeunit each test function keeps running until test.done() has been called. Every test function needs to call this. This way you can make sure your callbacks have been executed. I also like to use async module to clean up my code(callbacks) a bit.
Are you using test.expect() at the beginning of each test and test.done() at the end of each one? Think of them like begin and end braces.
I wrote my own, which essentially spins up a node instance for each test. If your test leaves a callback dangling, node just won't exit, and the whole test suite hangs instead of exiting early with success (which would be bad!)