In ASP.NET, why does DbSet.LastAsync() not exist? - asp.net

I've make some codes implementing some web API.
This API method returns last record of Foo Table.
public class FooController : ApiController
{
private FooContext db = new FooContext();
// GET: api/Foo
[ResponseType(typeof(Foo))]
public async Task<IHttpActionResult> GetLastFoo()
{
Foo foo = await db.Foo.Last();
if (foo == null)
{
return NotFound();
}
return Ok(foo);
}
}
I want make this API asynchronous, but there is no LastAsync() method.
Why and how can I solve it?
Thanks in advance.

You should not use Task.Run in ASP.NET:
Async and await on ASP.NET are all about I/O. They really excel at
reading and writing files, database records, and REST APIs. However,
they’re not good for CPU-bound tasks. You can kick off some background
work by awaiting Task.Run, but there’s no point in doing so. In fact,
that will actually hurt your scalability by interfering with the
ASP.NET thread pool heuristics. If you have CPU-bound work to do on
ASP.NET, your best bet is to just execute it directly on the request
thread. As a general rule, don’t queue work to the thread pool on
ASP.NET.
From Async Programming : Introduction to Async/Await on ASP.NET
Still it does not mean you can't use async and await in ASP.NET for I/O (and that's what you want) just use real async methods and not a fake async wrappers over synchronous methods (that will just push the work into other ThreadPool thread and you will not gain any performance benfit from it).
Since you don't have LastAsync method in EF I suggest you to use OrderBy to order your collection as you want and to use FirstAsync method (or FirstAsync overload that supports lambda predicate) instead of using Last method, FirstAsync is a true async I/O method that is supported in EF.
More info about when it's appropriate to use Task.Run can be found in Task.Run Etiquette Examples: Don't Use Task.Run in the Implementation article in Stephen Cleary's blog.
Your question why there is no LastAsync method in the first place should be directed to the team at Microsoft that desiged EF api, but my guess is that they didn't bother implementing it since it is so easy to achieve the same functionally with FirstAsync method as I suggested.

A working version of that code would look like this:
public class FooController : ApiController
{
private FooContext db = new FooContext();
// GET: api/Foo
[ResponseType(typeof(Foo))]
public async Task<IHttpActionResult> GetLastFoo()
{
Foo foo = await db.Foo.OrderByDesc(x=> x.Timestamp).FirstOrDefaultAsync();
if (foo == null)
{
return NotFound();
}
return Ok(foo);
}
}
Last etc don't work against an EF IQueryable because SQL doesn't have an equivalent command

about how to solve it
you can use
await Task.Run(()=>db.Foo.Last());

Related

Convert async to sync for HttpClient.SendAsync

I want to use a REST-call like this:
private async Task<HttpResponseMessage> SendRequestHelperAsync(HttpRequestMessage message, CancellationToken ct)
{
var response = await HttpClient.SendAsync(message, ct).ConfigureAwait(false);
return response;
}
from a non-async method. When I use it like this:
var response = SendRequestHelperAsync(message, ct).Result;
it gets stuck. When I use it directly, it gets stuck as well:
HttpResponseMessage response = HttpClient.SendAsync(message, ct).Result;
When I was looking for some solution, I came across using a task like this:
var task = Task.Run(async () => { await SendRequestHelperAsync(message, ct); });
but then how do I get the result back?
(I am using it from .Net Framework 4.8, WinForms Application.)
I want to use [async code] from a non-async method.
The best answer is "don't". Instead, go async all the way.
You could use Task.Run as a workaround; this is the thread pool hack, which will work in this specific case (warning: it does not work in every case, specifically, if the code in the Task.Run delegate accesses UI elements, then this hack will not work). The thread pool hack supports return types, as such:
var response = Task.Run(async () => await SendRequestHelperAsync(message, ct))
.GetAwaiter().GetResult();
However, the best answer is still "don't". The fact that you're deadlocking (as explained in detail on my blog) implies that this code is being run on the UI thread, and the solution is attempting to block the UI thread on a network request. Blocking the UI thread is a poor user experience.
Instead, the best solution is to redesign the UI so that no blocking is necessary. This is usually done by adding some kind of spinner or "loading..." UI element, and then updating the UI when the asynchronous operation completes.

masstransit access Activity from service bus message

I am using Masstransit to send Request/Response via servicebus between two services(dont ask why).
I would like to set-up custom application insights telemetry. I know that ServiceBus Messages add Diagnostic metadata so consumer can extract it and use it to add correlation between services. However I can't access it in MassTransit, or at least I dont know how.
Any tips?
Couple of months passed and solution i implemented proves to be a good one.
I created class that implements IReceiveObserver. On PreReceive I am able to access (ServiceBusReceiveContext)context and start Telemetry operation that has correct parent id. so it looks like this:
public Task PreReceive(ReceiveContext context)
{
var serviceBusContext = (ServiceBusReceiveContext)context;
var requestActivity = new Activity("Process");
requestActivity.SetParentId(serviceBusContext.Properties["Diagnostic-Id"].ToString());
IOperationHolder<RequestTelemetry> operation = _telemetryClient.StartOperation<RequestTelemetry>(requestActivity);
operation.Telemetry.Success = true;
serviceBusContext.Properties.Add(TelemetryOperationKey, operation);
return Task.CompletedTask;
}
On PostReceive I am able to stop operation:
public Task PostReceive(ReceiveContext context)
{
var serviceBusContext = (ServiceBusReceiveContext)context;
var operation = (IOperationHolder<RequestTelemetry>)serviceBusContext.Properties[TelemetryOperationKey];
operation.Dispose();
return Task.CompletedTask;
}
I also do some magic when exception happens:
public Task ReceiveFault(ReceiveContext context, Exception exception)
{
_telemetryClient.TrackException(exception);
var serviceBusContext = (ServiceBusReceiveContext)context;
var operation = (IOperationHolder<RequestTelemetry>)serviceBusContext.Properties[TelemetryOperationKey];
operation.Telemetry.ResponseCode = "Fail";
operation.Telemetry.Success = false;
operation.Dispose();
return Task.CompletedTask;
}
It was difficult to find this solution by reading MassTransit documentation. I would say that MassTransit is a fantastic tool for some situations there is no alternatives. However documentation is pretty poor.
You can use Application Insights with MassTransit, there is a package available that writes metrics directly.
The documentation is available here:
https://masstransit-project.com/advanced/monitoring/applications-insights.html
Also, you can access Activity.Current from anyway, I think, based on my experience with DiagnosticSource. It might be different with AppInsights though.

How to rewrite synchronous controller to be asynchronous in Play?

I'm using Play framework 2.2 for one of my upcoming web application. I have implemented my controllers in synchronous pattern, with several blocking calls (mainly, database).
For example,
Synchronous version:
public static Result index(){
User user = db.getUser(email); // blocking
User anotherUser = db.getUser(emailTwo); // blocking
...
user.sendEmail(); // call to a webservice, blocking.
return ok();
}
So, while optimising the code, decided to make use of Asynchronous programming support of Play. Gone through the documentation, but the idea is still vague to me, as I'm confused about how to properly convert the above synchronous block of code to Async.
So, I came up with below code:
Asynchronous version:
public static Promise<Result> index(){
return Promise.promise(
new Function0<Result>(){
public Result apply(){
User user = db.getUser(email); // blocking
User anotherUser = db.getUser(emailTwo); // blocking
...
user.sendEmail(); // call to a webservice, blocking.
return ok();
}
}
);
}
So, I just wrapped the entire control logic inside a promise block.
Is my approach correct?
Should I convert each and every blocking request inside the controller, as Asynchronous, or wrapping several blocking calls inside single Async block is enough?
The play framework is asynchronous by nature and it allows the creation of fully non-blocking code. But in order to be non-blocking - with all its benefits - you can't just wrap your blocking code and expect magic to happen...
In an ideal scenario, your complete application is written in a non-blocking manner. If this is not possible (for whatever reason), you might want to abstract your blocking code in Akka actors or behind async interfaces which return scala.concurrent.Future's. This way you can execute your blocking code (simultaneously) in a dedicated Execution Context, without impacting other actions. After all, having all your actions share the same ExecutionContext means they share the same Thread pool. So an Action that blocks Threads might drastically impact other Actions doing pure CPU while having CPU not fully utilized!
In your case, you probably want to start at the lowest level. It looks like the database calls are blocking so start by refactoring these first. You either need to find an asynchronous driver for whatever database you are using or if there is only a blocking driver available, you should wrap them in a future to execute using a DB-specific execution context (with a ThreadPool that's the same size as the DB ConnectionPool).
Another advantage of abstracting the DB calls behind an async interface is that, if at some point in the future, you switch to a non-blocking driver, you can just change the implementation of your interface without having to change your controllers!
In your re-active controller, you can then handle these futures and work with them (when they complete). You can find more about working with Futures here
Here's a simplified example of your controller method doing non-blocking calls, and then combining the results in your view, while sending an email asynchronous:
public static Promise<Result> index(){
scala.concurrent.Future<User> user = db.getUser(email); // non-blocking
scala.concurrent.Future<User> anotherUser = db.getUser(emailTwo); // non-blocking
List<scala.concurrent.Future<User>> listOfUserFutures = new ArrayList<>();
listOfUserFutures.add(user);
listOfUserFutures.add(anotherUser);
final ExecutionContext dbExecutionContext = Akka.system().dispatchers().lookup("dbExecutionContext");
scala.concurrent.Future<Iterable<User>> futureListOfUsers = akka.dispatch.Futures.sequence(listOfUserFutures, dbExecutionContext);
final ExecutionContext mailExecutionContext = Akka.system().dispatchers().lookup("mailExecutionContext");
user.andThen(new OnComplete<User>() {
public void onComplete(Throwable failure, User user) {
user.sendEmail(); // call to a webservice, non-blocking.
}
}, mailExecutionContext);
return Promise.wrap(futureListOfUsers.flatMap(new Mapper<Iterable<User>, Future<Result>>() {
public Future<Result> apply(final Iterable<User> users) {
return Futures.future(new Callable<Result>() {
public Result call() {
return ok(...);
}
}, Akka.system().dispatcher());
}
}, ec));
}
It you don't have anything to not block on then there may not be a reason to make your controller async. Here is a good blog about this from one of the creators of Play: http://sadache.tumblr.com/post/42351000773/async-reactive-nonblocking-threads-futures-executioncont

Task.ContinueWith confusion

With ASP.NET 4.5 I'm trying to play with the new async/await toys. I have a IDataReader-implementing class that wraps a vendor-specific reader (like SqlDatareader). I have a simple ExecuteSql() method that operates synchronously like so:
public IDataReader ReaderForSql(string sql)
{
var cmd = NewCommand(sql, CommandType.Text);
return DBReader.ReaderFactory(cmd.ExecuteReader());
}
What I want is an Async version of this. Here's my first try:
public Task<IDataReader> ReaderForSqlAsync(string sql, CancellationToken ct)
{
var cmd = NewCommand(sql, CommandType.Text);
return cmd.ExecuteReaderAsync(ct)
.ContinueWith(t => DBReader.ReaderFactory(t.Result));
}
and I use it:
using (var r = await connection.ReaderForSqlAsync("SELECT ...", cancellationToken))
{
...
}
This works great in my limited testing so far. But after watching this Cloud9 video a few times: http://channel9.msdn.com/Events/aspConf/aspConf/Async-in-ASP-NET I got worreid about warnings they gave regarding:
ContinueWith consuming extra threadpool resources - Readerfactory is very light!
Task.Result blocking
and since I am passing a ContinuationToken to ExecuteReaderAsync() it seems cancellation is just yet another reason ExecuteReaderAsync() could fail (it's SQL after all!)
What will be the state of the task when I try to ContinueWith it? Will t.Result block? throw? do the wrong thing?
ContinueWith will use the current task scheduler (a thread pool thread) by default, but you can change that by passing TaskContinuationOptions.ExecuteSynchronously and an explicit TaskScheduler.
That said, I would make this as a first effort:
public async Task<IDataReader> ReaderForSqlAsync(string sql, CancellationToken ct)
{
var cmd = NewCommand(sql, CommandType.Text);
var readerResult = await cmd.ExecuteReaderAsync(ct).ConfigureAwait(false);
return DBReader.ReaderFactory(readerResult);
}
async and await handle all the ContinueWith delicacies and edge conditions in a consistent manner for you. It may be possible to complicate this code to be faster if performance testing indicates it's a serious problem.
Result blocks if the task has not completed. But in the continuation handler it already has. So it does not block. You are doing the right thing.
When you invoke Result on a faulted task (and you say this might happen) the exception is rethrown. This causes your continuation to fault with the same exception which causes the final task returned from ReaderForSqlAsync to also be faulted. This is a good thing: The entire chain of tasks faulted and all exceptions have been observed (on contrast to being swallowed). So this is best-practice, too.
Using a thread for compute-bound work is always ok. So again, you are doing the right thing using ContinueWith. You have to compute the IDataReader somewhere after all. You cannot not compute it.

Suggestions for simple ways to do Asynchronous processing in Grails

Let's say I have a simple controller like this:
class FooController {
def index = {
someVeryLongCompution() //e.g crawl a set of web pages
render "Long computation was launched."
}
}
When the index action is invoked, I want the method to return immediately to the user while running the long computation asynchronously.
I understand the most robust way to do this would be to use a message broker in the architecture, but I was wondering if there is a simpler way to do it.
I tried the Executor plugin but that blocks the http request from returning until the long computation is done.
I tried the Quartz plugin, but that seems to be good for periodic tasks (unless there is a way to run a job just once?)
How are you guys handling such requests in Grails?
Where do you want to process veryLongComputation(), on the same Grails server, or a different server?
If the same server, you don't need JMS, another option is to just create a new thread and process the computation asynchronously.
def index = {
def asyncProcess = new Thread({
someVeryLongComputation()
} as Runnable )
asyncProcess.start()
render "Long computation was launched."
}
If you use a simple trigger in Grails Quartz and set the repeatCount to 0, the job will only run once. It runs separate from user requests, however, so you'd need to figure out some way to communicate to user when it completed.
I know this is a very old question, just wanted to give an updated answer.
Since grails 2.3, the framework supports async calls using Servlet 3.0 async request handling (of course, a servlet 3.0 container must be used and the servlet version should be 3.0 in the configuration, which it is per default)
It is documented here : http://grails.org/doc/latest/guide/async.html
In general, there are two ways achieving what you asked for:
import static grails.async.Promises.*
def index() {
tasks books: Book.async.list(),
totalBooks: Book.async.count(),
otherValue: {
// do hard work
}
}
or the Servlet Async way:
def index() {
def ctx = startAsync()
ctx.start {
new Book(title:"The Stand").save()
render template:"books", model:[books:Book.list()]
ctx.complete()
}
}
Small note - The grails method is using promises, which is a major (async) leap forward. Any Promise can be chained to further promised, have a callback on success and fail etc'
Have you tried Grails Promisses API? It should be as simple as
import static grails.async.Promise
import static grails.async.Promises
class FooController {
def index = {
Promise p = Promises.task {
someVeryLongCompution() //e.g crawl a set of web pages
}
render "Long computation was launched."
}
}
Try Spring events plugin - It supports asynchronous event listeners.
If you'd like to use the Quartz plugin (as we always do), you can do it like this. It works well for us:
DEFINE A JOB (with no timed triggers)
static triggers = {
simple name:'simpleTrigger', startDelay:0, repeatInterval: 0, repeatCount: 0
}
CALL <job>.triggerNow() to manually execute the job in asynchronous mode.
MyJob.triggerNow([key1:value1, key2: value2]);
Pro Tip #1
To get the named parameters out the other side...
def execute(context) {
def value1 = context.mergedJobDataMap.get('key1');
def value2 = context.mergedJobDataMap.get('key2');
...
if (value1 && value2) {
// This was called by triggerNow(). We know this because we received the parameters.
} else {
// This was called when the application started up. There are no parameters.
}
}
Pro Tip #2
The execute method always gets called just as the application starts up, but the named parameters come through as null.
Documentation: http://grails.org/version/Quartz%20plugin/24#Dynamic%20Jobs%20Scheduling
The best solution for this kind of problem is to use JMS, via the JMS plugin.
For a simpler implementation, that doesn't requires an externel server/service, you can try the Spring Events plugin.
Grails 2.2.1 Solution I had an additional requirement that said the report had to auto pop a window when it was complete. So I chose the servlet way from above with a twist. I replaced the render a view with a json formatted string return it looked like this.
Additionally my client side is not a gsp view, it is ExtJS 4.1.1 (a HTML5 product)
enter code here
def index() {
def ctx = startAsync()
ctx.start ({
Map retVar = [reportId: reportId, success: success];
String jsonString = retVar as JSON;
log.info("generateTwoDateParamReport before the render out String is: " + jsonString);
ctx.getOriginalWebRequest().getCurrentResponse().setContentType("text/html");
ctx.getOriginalWebRequest().getCurrentResponse().setCharacterEncoding("UTF-8");
log.info("current contentType is: "ctx.getOriginalWebRequest().getCurrentResponse().contentType);
try {
ctx.getOriginalWebRequest().getCurrentResponse().getWriter().write(jsonString);
ctx.getOriginalWebRequest().getCurrentResponse().getWriter().flush();
ctx.getOriginalWebRequest().getCurrentResponse().setStatus(HttpServletResponse.SC_OK);
}
catch (IOException ioe)
{
log.error("generateTwoDateParamReport flush data to client failed.");
}
ctx.complete();
log.info("generateNoUserParamsReport after complete");
});
}

Resources