In our django-channels async consumer, i'm trying to retrieve a group result. This result may or may not be complete, and therefor i would like to add a callback to pipe results as they become ready. The problem is, the websocket is async, the callback must be sync, and self.send method must to async. Initially i assumed being able to just wrap the async send in async_to_sync, though it gives the error You cannot use AsyncToSync in the same thread as an async event loop - just await the async function directly., and therefor it seems that going async->sync->async isn't allowed.
class ImageConsumer(AsyncWebsocketConsumer):
async def celery_retrieve_group_result(self, batch_id):
group = group = celery.GroupResult().restore(batch_id)
res = group.get(callback=self.sync_callback)
def sync_callback(self, task_id, value):
async_to_sync(self.send_group_result)(task_id, value)
async def send_group_result(self, task_id , value):
await self.send(json.dumps({"type": "result.redraw_border", "result": value}))
I have tried different combinations, though my limiting factor is that the callback must be sync, and everything else is Async.
Does anyone have experience mixing celery with async django in this manner?
Any help would be appreciated!
Decided to go with a different approach of iterating over the enclosed AsyncResults.
class ImageConsumer(AsyncWebsocketConsumer):
name = "Image Consumer"
timeout = 20
sleep_duration = 5e-2
async def celery_retrieve_group_result(self, batch_id):
group = celery.GroupResult().restore(batch_id)
if group is not None:
ordered_list_of_async_results = group.results
for result in ordered_list_of_async_results:
start = time.time()
try:
while not result.ready():
await asyncio.sleep(self.sleep_duration)
if self.timeout and time.time() - start > self.timeout:
logger.exception(str(TimeoutError))
raise TimeoutError
value = result.get()
await self.send(json.dumps({'type': 'result.processing', 'result': value}))
except:
await self.send(json.dumps({'type': 'result.processing', 'error': str(TimeoutError)}))
group.forget()
else:
await self.send(json.dumps({'type': 'response.nonexistant_group', 'error': 'No result batch exists. re-upload'}))
This is working really well. The timeout is because Celery 4.3 currently has an issue with Redis backends, which if removed will cause a gridlock. So until that is fixed, this is working perfectly.
Related
Why is the res variable always false even though the parameters are correct?
fun isValidUser(_studentEmail: String, _password: String): Boolean {
var res = false
userList.get().addOnSuccessListener { result ->
for (document in result) {
val studentEmail = document.data["studentEmail"] as String
val password = document.data["password"] as String
if (_studentEmail == studentEmail && _password == password) {
res = true
}
}
}
return res
}
This doesn't behave like you think it does.
The userList.get() launches an asynchronous task, which means the program will continue its execution without waiting for the task to be done.
addOnSuccessListener only registers a listener - a piece of code to run when the query successfully completes, but that piece of code will only be run in the future, not right away, because the query takes some time.
When the program reaches the return res, the query still hasn't completed and the listener hasn't been executed yet.
If you want to reason more sequentially about this stuff, you can use Kotlin coroutine extensions to await() the result instead of registering a listener. Check out kotlinx-coroutines-play-services for instance. However, if you have trouble understanding asynchronous behaviour, you should probably read up more about this before diving into coroutines.
I want to run a computation that might take too long. If it doesn't finish in a specific time, abort the computation and return a different value. For this problem I found Future.timeout, it would almost do the same thing that I want, except it doesn't work for this code.
Future<String> timeoutTest() async
{
return await longComputation().timeout(
Duration(milliseconds: 10),
onTimeout: () => "Took too long"
);
}
Future<String> longComputation() async
{
int startTime = DateTime.now().millisecondsSinceEpoch;
Rational n = Rational.one;
for(int i = 1; i < 2000; i++)
{
n *= Rational.fromInt(i);
}
String result = n.toDecimalString();
print("Time took: ${DateTime.now().millisecondsSinceEpoch - startTime} ms");
return result;
}
When I call print(await timeoutTest()) I either expect a string of digits that took maximum 10ms to calculate OR the "Took too long" string if it took more than 10ms. But I get the string of digits, and the message in the console: "Time took: 877 ms". So the timeout didn't work.
If I fake the computation with Future.delay, the timeout works as expected. It returns a different value, because the longComputation took at least 100ms. (I still get the message in the console: "Time took: 103ms", but this is not the main problem.)
Future<String> longComputation() async
{
int startTime = DateTime.now().millisecondsSinceEpoch;
String result = await Future.delayed(
Duration(milliseconds: 100),
() => "Fake computation result"
);
print("Time took: ${DateTime.now().millisecondsSinceEpoch - startTime} ms");
return result;
}
I'm assuming I messed up something in the longComputation, but what? There were no un-awaited Futures.
This behavior can be confusing but it is important to remember that your Dart code are only executed in a single thread (unless you are using isolates).
The problem is that the logic behind .timeout needs to run in the same single thread and Dart can't just stop the execution of your own code. So if you are running a CPU intensive calculation without any pauses you are stopping the Dart VM from running any other events on the event queue.
What the implementation of .timeout actually does, is creating an internal Timer which are going to be triggered in the future unless you get a result before the timeout value. This Timer event are going on top on the event queue like any other event in the Dart VM.
But in your first example, we are actually never going to execute any other event on the event queue before you are giving the result. So from the Future's point of view, you are returning a result before the deadline.
This is going to look like .timeout is kind of pointless but what it really are for is when you are making some IO operations like API requests where the Dart VM are actually waiting for some answer.
If you are going to use it for heavy calculations, you can either spawn an Isolate so your main isolate instance can wait on the other isolate. Alternative, you can insert some pauses in your calculation which makes space for the Dart VM to execute other events on the event queue. An example could be inserting await Future<void>(() => null); which are going to spawn a new event on top of the event queue. When we wait for all events on the queue to be executed before our own empty calculation.
It would then also make sense to add some logic so your own code can see if the timeout value has been reached so you can stop the calculation if that is the case.
You can't actually cancel Futures. At best you could have your .timeout callback set a flag that longComputation periodically checks to become a no-op as soon as possible.
Also see Future.timeout documention is misleading.
I'm still struggeling with the async/await pattern so I'm here to ask you some precisions.
I saw this page explaining the async/await pattern pretty well. I'm posting here the example that bother me :
import 'dart:async';
Future<String> firstAsync() async {
await Future<String>.delayed(const Duration(seconds: 2));
return "First!";
}
Future<String> secondAsync() async {
await Future<String>.delayed(const Duration(seconds: 2));
return "Second!";
}
Future<String> thirdAsync() async {
await Future<String>.delayed(const Duration(seconds: 2));
return "Third!";
}
void main() async {
var f = await firstAsync();
print(f);
var s = await secondAsync();
print(s);
var t = await thirdAsync();
print(t);
print('done');
}
In this example, each async method is called one after another, so the execution time for the main function is 6 seconds (3 x 2 seconds). However, I don't understand what's the point of asynchronous function if they are executed one after another.
Are async functions not supposed to execute in the background ? Is it not the point of multiple async functions to fastens the process with parrallel execution ?
I think I'm missing something about asynchronous functions and async/await pattern in flutter so if you could explain me that, it would be very appreciated.
Best
Waiting on multiple Futures to complete using Future.wait()
If the order of execution of the functions is not important, you can use Future.wait().
The functions get triggered in quick succession; when all of them complete with a value, Future.wait() returns a new Future. This Future completes with a list containing the values produced by each function.
Future
.wait([firstAsync(), secondAsync(), thirdAsyncC()])
.then((List responses) => chooseBestResponse(responses))
.catchError((e) => handleError(e));
or with async/await
try {
List responses = await Future.wait([firstAsync(), secondAsync(), thirdAsyncC()]);
} catch (e) {
handleError(e)
}
If any of the invoked functions completes with an error, the Future returned by Future.wait() also completes with an error. Use catchError() to handle the error.
Resource:https://v1-dartlang-org.firebaseapp.com/tutorials/language/futures#waiting-on-multiple-futures-to-complete-using-futurewait
The example is designed to show how you can wait for a long-running process without actually blocking the thread. In practice, if you have several of those that you want to run in parallel (for example: independent network calls), you could optimize things.
Calling await stops the execution of the method until the future completes, so the call to secondAsync will not happen until firstAsync finishes, and so on. If you do this instead:
void main() async {
var f = firstAsync();
var s = secondAsync();
var t = thirdAsync();
print(await f);
print(await s);
print(await t);
print('done');
}
then all three futures are started right away, and then you wait for them to finish in a specific order.
It is worth highlighting that now f, s, and t have type Future<String>. You can experiment with different durations for each future, or changing the order of the statements.
If anyone new in this problem use the async . Dart has a function called FutureGroup. You can use it to run futures in parallel.
Sample:
final futureGroup = FutureGroup();//instantiate it
void runAllFutures() {
/// add all the futures , this is not the best way u can create an extension method to add all at the same time
futureGroup.add(hello());
futureGroup.add(checkLocalAuth());
futureGroup.add(hello1());
futureGroup.add(hello2());
futureGroup.add(hello3());
// call the `.close` of the group to fire all the futures,
// once u call `.close` this group cant be used again
futureGroup.close();
// await for future group to finish (all futures inside it to finish)
await futureGroup.future;
}
This futureGroup has some useful methods which can help you ie. .future etc.. check the documentation to get more info.
Here's a sample usage Example One using await/async and Example Two using Future.then.
you can always use them in a single future
final results = await Future.wait([
firstAsync();
secondAsync();
thirdAsync();
]);
results will be an array of you return type. in this case array of strings.
cheers.
Try this resolve.
final List<Future<dynamic>> featureList = <Future<dynamic>>[];
for (final Partner partner in partnerList) {
featureList.add(repository.fetchAvatar(partner.uid));
}
await Future.wait<dynamic>(featureList);
If want parallel execution you should switch to multi thread concept called Isolates
mix this with async/await concepts . You can also check this website for more
https://buildflutter.com/flutter-threading-isolates-future-async-and-await/
Using async / await like that is useful when you need a resource before executing the next task.
In your example you don't do really useful things, but imagine you call firstAsync, that gives you a stored authorization token in your phone, then you call secondAsync giving this token get asynchronously and execute an HTTP request and then checking the result of this request.
In this case you don't block the UI thread (user can interact with your app) and other tasks (get token, HTTP request...) are done in background.
i think you miss understood how flutter works first flutter is not multi threaded.....!
second if it isn't multi threaded how can it executes parallel tasks, which doesnt happen....! here is some links that will help you understand more https://webdev.dartlang.org/articles/performance/event-loop
https://www.dartlang.org/tutorials/language/futures
flutter doesn't put futures on another thread but what happens that they are added to a queue the links that i added are for event loop and how future works. hope you get it , feel free to ask me :)
In the kotlinx.coroutines library you can start new coroutine using either launch (with join) or async (with await). What is the difference between them?
launch is used to fire and forget coroutine. It is like starting a new thread. If the code inside the launch terminates with exception, then it is treated like uncaught exception in a thread -- usually printed to stderr in backend JVM applications and crashes Android applications. join is used to wait for completion of the launched coroutine and it does not propagate its exception. However, a crashed child coroutine cancels its parent with the corresponding exception, too.
async is used to start a coroutine that computes some result. The result is represented by an instance of Deferred and you must use await on it. An uncaught exception inside the async code is stored inside the resulting Deferred and is not delivered anywhere else, it will get silently dropped unless processed. You MUST NOT forget about the coroutine you’ve started with async.
I find this guide to be useful. I will quote the essential parts.
🦄 Coroutines
Essentially, coroutines are light-weight threads.
So you can think of a coroutine as something that manages thread in a very efficient way.
🐤 launch
fun main(args: Array<String>) {
launch { // launch new coroutine in background and continue
delay(1000L) // non-blocking delay for 1 second (default time unit is ms)
println("World!") // print after delay
}
println("Hello,") // main thread continues while coroutine is delayed
Thread.sleep(2000L) // block main thread for 2 seconds to keep JVM alive
}
So launch starts a coroutine, does something, and returns a token immediately as Job. You can call join on this Job to block until this launch coroutine completes.
fun main(args: Array<String>) = runBlocking<Unit> {
val job = launch { // launch new coroutine and keep a reference to its Job
delay(1000L)
println("World!")
}
println("Hello,")
job.join() // wait until child coroutine completes
}
🦆 async
Conceptually, async is just like launch. It starts a separate coroutine which is a light-weight thread that works concurrently with all the other coroutines. The difference is that launch returns a Job and does not carry any resulting value, while async returns a Deferred -- a light-weight non-blocking future that represents a promise to provide a result later.
So async starts a background thread, does something, and returns a token immediately as Deferred.
fun main(args: Array<String>) = runBlocking<Unit> {
val time = measureTimeMillis {
val one = async { doSomethingUsefulOne() }
val two = async { doSomethingUsefulTwo() }
println("The answer is ${one.await() + two.await()}")
}
println("Completed in $time ms")
}
You can use .await() on a deferred value to get its eventual result, but Deferred is also a Job, so you can cancel it if needed.
So Deferred is actually a Job. Read this for more details.
interface Deferred<out T> : Job (source)
🦋 async is eager by default
There is a laziness option to async using an optional start parameter with a value of CoroutineStart.LAZY. It starts coroutine only when its result is needed by some await or if a start function is invoked.
launch and async are used to start new coroutines. But, they execute them in different manner.
I would like to show very basic example which will help you understand difference very easily
launch
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
btnCount.setOnClickListener {
pgBar.visibility = View.VISIBLE
CoroutineScope(Dispatchers.Main).launch {
val currentMillis = System.currentTimeMillis()
val retVal1 = downloadTask1()
val retVal2 = downloadTask2()
val retVal3 = downloadTask3()
Toast.makeText(applicationContext, "All tasks downloaded! ${retVal1}, ${retVal2}, ${retVal3} in ${(System.currentTimeMillis() - currentMillis)/1000} seconds", Toast.LENGTH_LONG).show();
pgBar.visibility = View.GONE
}
}
// Task 1 will take 5 seconds to complete download
private suspend fun downloadTask1() : String {
kotlinx.coroutines.delay(5000);
return "Complete";
}
// Task 1 will take 8 seconds to complete download
private suspend fun downloadTask2() : Int {
kotlinx.coroutines.delay(8000);
return 100;
}
// Task 1 will take 5 seconds to complete download
private suspend fun downloadTask3() : Float {
kotlinx.coroutines.delay(5000);
return 4.0f;
}
}
In this example, my code is downloading 3 data on click of btnCount button and showing pgBar progress bar until all download gets completed. There are 3 suspend functions downloadTask1(), downloadTask2() and downloadTask3() which downloads data. To simulate it, I've used delay() in these functions. These functions waits for 5 seconds, 8 seconds and 5 seconds respectively.
As we've used launch for starting these suspend functions, launch will execute them sequentially (one-by-one). This means that, downloadTask2() would start after downloadTask1() gets completed and downloadTask3() would start only after downloadTask2() gets completed.
As in output screenshot Toast, total execution time to complete all 3 downloads would lead to 5 seconds + 8 seconds + 5 seconds = 18 seconds with launch
async
As we saw that launch makes execution sequentially for all 3 tasks. The time to complete all tasks was 18 seconds.
If those tasks are independent and if they do not need other task's computation result, we can make them run concurrently. They would start at same time and run concurrently in background. This can be done with async.
async returns an instance of Deffered<T> type, where T is type of data our suspend function returns. For example,
downloadTask1() would return Deferred<String> as String is return type of function
downloadTask2() would return Deferred<Int> as Int is return type of function
downloadTask3() would return Deferred<Float> as Float is return type of function
We can use the return object from async of type Deferred<T> to get the returned value in T type. That can be done with await() call. Check below code for example
btnCount.setOnClickListener {
pgBar.visibility = View.VISIBLE
CoroutineScope(Dispatchers.Main).launch {
val currentMillis = System.currentTimeMillis()
val retVal1 = async(Dispatchers.IO) { downloadTask1() }
val retVal2 = async(Dispatchers.IO) { downloadTask2() }
val retVal3 = async(Dispatchers.IO) { downloadTask3() }
Toast.makeText(applicationContext, "All tasks downloaded! ${retVal1.await()}, ${retVal2.await()}, ${retVal3.await()} in ${(System.currentTimeMillis() - currentMillis)/1000} seconds", Toast.LENGTH_LONG).show();
pgBar.visibility = View.GONE
}
This way, we've launched all 3 tasks concurrently. So, my total execution time to complete would be only 8 seconds which is time for downloadTask2() as it is largest of all of 3 tasks. You can see this in following screenshot in Toast message
both coroutine builders namely launch and async are basically lambdas with receiver of type CoroutineScope which means their inner block is compiled as a suspend function, hence they both run in an asynchronous mode AND they both will execute their block sequentially.
The difference between launch and async is that they enable two different possibilities. The launch builder returns a Job however the async function will return a Deferred object. You can use launch to execute a block that you don't expect any returned value from it i.e writing to a database or saving a file or processing something basically just called for its side effect. On the other hand async which return a Deferred as I stated previously returns a useful value from the execution of its block, an object that wraps your data, so you can use it for mainly its result but possibly for its side effect as well. N.B: you can strip the deferred and get its value using the function await, which will block the execution of your statements until a value is returned or an exceptions is thrown! You could achieve the same thing with launch by using the function join()
both coroutine builder (launch and async) are cancelable.
anything more?: yep with launch if an exception is thrown within its block, the coroutine is automatically canceled and the exceptions is delivered. On the other hand, if that happens with async the exception is not propagated further and should be caught/handled within the returned Deferred object.
more on coroutines https://kotlinlang.org/docs/tutorials/coroutines/coroutines-basic-jvm.html
https://www.codementor.io/blog/kotlin-coroutines-6n53p8cbn1
Async and Launch, both are used to create coroutines that run in the background. In almost every situation one can use either of them.
tl;dr version:
When you dont care about the task's return value, and just want to run it, you may use Launch. If you need the return type from the task/coroutine you should use async.
Alternate:
However, I feel the above difference/approach is a consequence of thinking in terms of Java/one thread per request model. Coroutines are so inexpensive, that if you want to do something from the return value of some task/coroutine(lets say a service call) you are better off creating a new coroutine from that one. If you want a coroutine to wait for another coroutine to transfer some data, I would recommend using channels and not the return value from Deferred object. Using channels and creating as much number of coroutines as required, is the better way IMO
Detailed answer:
The only difference is in the return type and what functionality it provides.
Launch returns Job while Async returns Deferred. Interestingly enough, Deferred extends Job. Which implies it must be providing additional functionality on top of Job. Deferred is type parameterised over where T is the return type. Thus, Deferred object can return some response from the block of code executed by async method.
p.s. I only wrote this answer because I saw some factually incorrect answers on this question and wanted to clarify the concept for everyone. Also, while working on a pet project myself I faced similar problem because of previous Java background.
launch returns a job
async returns a result (deferred job)
launch with join is used to wait until the job gets finished. It simply suspends the coroutine calling join(), leaving the current thread free to do other work (like executing another coroutine) in the meantime.
async is used to compute some results. It creates a coroutine and returns its future result as an implementation of Deferred. The running coroutine is cancelled when the resulting deferred is cancelled.
Consider an async method that returns a string value. If the async method is used without await it will return a Deferred string but if await is used you will get a string as the result
The key difference between async and launch:
Deferred returns a particular value of type T after your Coroutine finishes executing, whereas Job doesn’t.
launch / async no result
Use when don't need the result,
Don't block the code where is called,
Run in sequential
async for result
When you need to wait for the result and can run in parallel for
efficiency,
Block the code where is called,
Run in concurrent
Alongside the other great answers, for the people familiar with Rx and getting into coroutines, async returns a Deferred which is akin to Single while launch returns a Job that is more akin to Completable. You can .await() to block and get the value of the first one, and .join() to block until the Job is completed.
As far as I know, when runtime comes across the statement below it wraps the rest of the function as a callback to the method which is invoked asynchronously (someCall() in this example). In this case anotherCall() will be executed as a callback to someCall():
await someCall();
await anotherCall();
I wonder if it is possible to make runtime perform like this: call someCall() in async fashion and return immediately to the calling thread, then invoke anotherCall() similarly (without waiting someCall to complete). Because I need these two methods to run asynchronously and suppose these calls are just fire and forget calls.
Is it possible to implement this scenario using just async and await (not using old begin/end mechanism)?
The async/await includes a few operators to help with parallel composition, such as WhenAll and WhenAny.
var taskA = someCall(); // Note: no await
var taskB = anotherCall(); // Note: no await
// Wait for both tasks to complete.
await Task.WhenAll(taskA, taskB);
// Retrieve the results.
var resultA = taskA.Result;
var resultB = taskB.Result;
The simplest way is probably to do this:
var taskA = someCall();
var taskB = someOtherCall();
await taskA;
await taskB;
This is especially nice if you want the result values:
var result = await taskA + await taskB;
so you don't need to do taskA.Result.
TaskEx.WhenAll might be faster than two awaits after each other. i don't know since I haven't done performance investigation on that, but unless you see a problem I think the two consecutive awaits reads better, especially if you ewant the result values.
The Async CTP is no longer needed provided you're using .NET 4.5. Note that the async functionality is implemented by the compiler so .NET 4 apps can use it but VS2012 is required to compile it.
TaskEx is not needed anymore. The CTP couldn't modify the existing framework so it used extensions to accomplish things that the language would handle in 5.0. Just use Task directly.
So herewith, I have re-written the code(answered by Stephen Cleary) by replacing TaskEx with Task.
var taskA = someCall(); // Note: no await
var taskB = anotherCall(); // Note: no await
// Wait for both tasks to complete.
await Task.WhenAll(taskA, taskB);
// Retrieve the results.
var resultA = taskA.Result;
var resultB = taskB.Result;