filipw / Strathweb.CacheOutput

ASP.NET Web API CacheOutput - library to allow you to cache the output of ApiControllers
Other
882 stars 253 forks source link

HttpResponseMessage not returning on first "cached" request #85

Closed Zettersten closed 9 years ago

Zettersten commented 10 years ago
[CacheOutput(ClientTimeSpan = 100, ServerTimeSpan = 100)]
public async Task<HttpResponseMessage> Get(string imageId)
{
  if (string.IsNullOrEmpty(imageId))
  {
    return Request.CreateResponse(HttpStatusCode.BadRequest);
  }

  var images = await _repository.Get(imageId);

  if (images == null)
  {
    return Request.CreateResponse(HttpStatusCode.BadRequest);
  }

  if (IsImageRequest)
  {

    if (!File.Exists(images.Path))
    {
      return Request.CreateResponse(HttpStatusCode.Gone);
    }

    HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK);
    response.Content = new StreamContent(File.OpenRead(images.Path));
    response.Content.Headers.ContentType = new MediaTypeHeaderValue("image/png");
    response.Headers.Location = new Uri(images.Href);

    return response;

  }

  return Request.CreateResponse(HttpStatusCode.OK, images);
}

Model from repository contains path to image on hard disk.

Works fine without cache. Fails to resolve/respond after cache is set.

capture

but when i refresh again, and then subsequently continue refreshing... all is good!

Is this a bug?

capture_good

polyzois commented 10 years ago

It is a bug, I have the exact same thing. I will try and describe it in a little while... Just need to come up with a solution.

This is the offending line of code. It will deadlock sometimes https://github.com/filipw/AspNetWebApi-OutputCache/blob/master/src/WebApi.OutputCache.V2/CacheOutputAttribute.cs#L196

as explained for instance here http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html

jfritchman commented 10 years ago

I just updated to the latest version (0.60) that was pushed to Nuget and I am still having this problem. Is anyone else still having the problem?

polyzois commented 10 years ago

Yes I still do. I thought that it was solved but there are still issues. Issues that dont arise if I remove the call to ReadAsByteArrayAsync. I am using async actions and I guess you do as well?

I also tried rewriting the CacheOutputAttibute overriding the new async filter hooks but it still dedalocks/hangs on this...

jfritchman commented 10 years ago

You are correct, I am using async actions. I am fairly new to API development but please let me know if you need some possible assistance. I really like this library and I would hate to have to remove it from my project but we are about to enter load testing soon and I need to find a caching solution.

polyzois commented 10 years ago

The strange thing is that it always the first request that gets stuck. Subsequent calls work just fine. I have tried deadlock detection but I cant find anything. The Debug Diagnostic tool from Microsoft tells me there is a lock in native code but I don't know what the problem is really. I might add that I use IIS 7.5 .net 4.5 and Web Api 2.1.

jfritchman commented 10 years ago

The odd part for me is that it doesn't happen for every controller, actually it only seems to be one. I can reproduce the problem using IIS Express, .Net 4.5.1 and Web API 2.2 and also with IIS 8.0 on Sever 2012.

polyzois commented 10 years ago

I get the feeling it is the first call to an async api method that fails, all subsequent calls go through. But this first call is hung. As I happen to know which call is the first made I changed that single action from async to "ordinary". Also I tried changing the cache to not look at the response stream but rather the response object but that fails the same way.

var objectContent = actionExecutedContext.Response.Content as ObjectContent;

BTW my async code is a call to a WCF using the Asynchronous Programming Model (APM) Begin/End wrapped by Task.Factory.FromAsync

pepopowitz commented 9 years ago

I was on the verge of ripping out my CacheOutput attributes and using server-side data caching instead, when I found this open issue. I am having the exact same problem - async actions that are cached on the server, deadlocking on only the second request to the endpoint. Did anyone ever find a workaround or solution for this issue?

I wish I had more info to add, but the above comments pretty much cover my findings.

dmarlow commented 9 years ago

Same here, I ended up removing CacheOutput on the async API endpoints. It was very hard to track down.

sbezludny commented 9 years ago

I encountered a similar problem in my application. Issue was in interaction between OuputCache and Compression Delegating Handler. Thing is that call of ReadAsByteArrayAsync (that is used underhood of OutputCache) caused calculation of content-length after that Compression Delegating Handler used incorrect value of content-length instead to omit that header. Hope this help.

Zettersten commented 9 years ago

@sbezludny possible pull-request? Help us out brotha!

yoyos commented 9 years ago

I'm using the last version https://www.nuget.org/packages/Strathweb.CacheOutput.WebApi2/0.9.0 and still have this deadlock on first request.

I'm using .NET 4.5 Ninject Async actions .. Am I the only one ?

pafanasiev commented 8 years ago

Same here, with the latest version of nuget - this still reproduces for me but only for some controllers? Has anyone figured out why is this happening?

yoyos commented 8 years ago

As I remember, I fixed the problem by disabling all modules in web.config and enabling one by one. It was coming from another package (a module of https://www.nuget.org/packages/ImageResizer/) that needed an upgrade (pre version) from Sync to Async. You should try the same