IRavenQueryable<T>.ToListAsync() treats 304 Not Modified as an error?

484 views
Skip to first unread message

Joel

unread,
Feb 22, 2012, 8:29:44 PM2/22/12
to rav...@googlegroups.com
Server: 616
Client: 616

When I use IDocumentSession and session.Query<Foo>().ToList(), everything works great.

When I use IAsyncDocumentSession and session.Query<Foo>().ToListAsync(), it works perfectly the first time after I restart the application, and throws an error like the following every time I execute the same query after that.

I can see on the server console that 304 Not Modified is being returned in both cases, it's just that the sync version treats that as an opportunity to return the value from the cache, and the asyc version blows up. Am I doing something wrong?

System.AggregateException: One or more errors occurred. ---> System.Net.WebException: The remote server returned an error: (304) Not Modified.
   at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
   at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise)
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
   at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
   at System.Threading.Tasks.Task`1.get_Result()
   at Raven.Client.Connection.HttpJsonRequest.<>c__DisplayClass9.<InternalReadResponseStringAsync>b__6() in c:\Builds\raven\Raven.Client.Lightweight\Connection\HttpJsonRequest.cs:line 125
   at Raven.Client.Connection.HttpJsonRequest.ReadStringInternal(Func`1 getResponse) in c:\Builds\raven\Raven.Client.Lightweight\Connection\HttpJsonRequest.cs:line 272
   at Raven.Client.Connection.HttpJsonRequest.<InternalReadResponseStringAsync>b__5(Task`1 task) in c:\Builds\raven\Raven.Client.Lightweight\Connection\HttpJsonRequest.cs:line 125
   at System.Threading.Tasks.ContinuationResultTaskFromResultTask`2.InnerInvoke()
   at System.Threading.Tasks.Task.Execute()



Joel

unread,
Feb 23, 2012, 2:17:39 PM2/23/12
to rav...@googlegroups.com
Here's a failing test. I'd love to know what I'm doing wrong here...

using System.Linq;
using Raven.Client;
using Raven.Client.Document;
using Raven.Client.Linq;
using Xunit;

namespace RavenAsyncTest
{
    public class Dummy
    {
        public string Id { get; set; }
        public string Name { get; set; }
    }

    public class AsyncTest
    {
        private static IDocumentStore store = null;

        static AsyncTest()
        {
            store = new DocumentStore { Url = "http://localhost:8080/" };
            store.Initialize();
        }

        [Fact]
        public void SyncQuery()
        {
            using (var session = store.OpenSession())
            {
                var results = session.Query<Dummy>().ToList();
                Assert.Equal(0, results.Count);
            }
        }

        [Fact]
        public void AsyncQuery()
        {
            using (var session = store.OpenAsyncSession())
            {
                var results = session.Query<Dummy>().ToListAsync();
                results.Wait();
                var results2 = session.Query<Dummy>().ToListAsync();
                results2.Wait();
                Assert.Equal(0, results2.Result.Count);
            }
        }
    }
}


RavenAsyncTest.AsyncTest.AsyncQuery : System.AggregateException : One or more errors occurred.
---- System.AggregateException : One or more errors occurred.
-------- System.AggregateException : One or more errors occurred.
------------ System.AggregateException : One or more errors occurred.
---------------- System.AggregateException : One or more errors occurred.
-------------------- System.AggregateException : One or more errors occurred.
------------------------ System.AggregateException : One or more errors occurred.
---------------------------- System.Net.WebException : The remote server returned an error: (304) Not Modified.
Stack Trace:
   at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
   at Raven.Client.Linq.LinqExtensions.<ToListAsync>b__5[T](Task`1 task) in c:\Builds\raven\Raven.Client.Lightweight\Linq\LinqExtensions.cs:line 186
   at System.Threading.Tasks.ContinuationResultTaskFromResultTask`2.InnerInvoke()
   at System.Threading.Tasks.Task.Execute()
----- Inner Stack Trace -----
   at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
   at Raven.Client.Document.AbstractDocumentQuery`2.<ToListAsync>b__25(Task`1 t) in c:\Builds\raven\Raven.Client.Lightweight\Document\AbstractDocumentQuery.cs:line 1535
   at System.Threading.Tasks.ContinuationResultTaskFromResultTask`2.InnerInvoke()
   at System.Threading.Tasks.Task.Execute()
----- Inner Stack Trace -----
   at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
   at Raven.Client.Document.AbstractDocumentQuery`2.ProcessEnumerator(Task`1 task) in c:\Builds\raven\Raven.Client.Lightweight\Document\AbstractDocumentQuery.cs:line 583
   at Raven.Client.Document.AbstractDocumentQuery`2.<ToListAsync>b__26(Task`1 t) in c:\Builds\raven\Raven.Client.Lightweight\Document\AbstractDocumentQuery.cs:line 1533
   at System.Threading.Tasks.ContinuationResultTaskFromResultTask`2.InnerInvoke()
   at System.Threading.Tasks.Task.Execute()
----- Inner Stack Trace -----
   at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
   at Raven.Client.Document.AbstractDocumentQuery`2.<ExecuteActualQueryAsync>b__1d(Task`1 task) in c:\Builds\raven\Raven.Client.Lightweight\Document\AbstractDocumentQuery.cs:line 1367
   at System.Threading.Tasks.ContinuationResultTaskFromResultTask`2.InnerInvoke()
   at System.Threading.Tasks.Task.Execute()
----- Inner Stack Trace -----
   at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
   at Raven.Client.Connection.Async.AsyncServerClient.<>c__DisplayClass32.<QueryAsync>b__30(Task`1 task) in c:\Builds\raven\Raven.Client.Lightweight\Connection\Async\AsyncServerClient.cs:line 522
   at System.Threading.Tasks.ContinuationResultTaskFromResultTask`2.InnerInvoke()
   at System.Threading.Tasks.Task.Execute()
----- Inner Stack Trace -----
   at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
   at Raven.Client.Connection.HttpJsonRequest.<ReadResponseJsonAsync>b__0(Task`1 x) in c:\Builds\raven\Raven.Client.Lightweight\Connection\HttpJsonRequest.cs:line 84
   at System.Threading.Tasks.ContinuationResultTaskFromResultTask`2.InnerInvoke()
   at System.Threading.Tasks.Task.Execute()
----- Inner Stack Trace -----
   at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
   at Raven.Client.Connection.HttpJsonRequest.<>c__DisplayClass9.<InternalReadResponseStringAsync>b__6() in c:\Builds\raven\Raven.Client.Lightweight\Connection\HttpJsonRequest.cs:line 125
   at Raven.Client.Connection.HttpJsonRequest.ReadStringInternal(Func`1 getResponse) in c:\Builds\raven\Raven.Client.Lightweight\Connection\HttpJsonRequest.cs:line 272
   at Raven.Client.Connection.HttpJsonRequest.<InternalReadResponseStringAsync>b__5(Task`1 task) in c:\Builds\raven\Raven.Client.Lightweight\Connection\HttpJsonRequest.cs:line 125
   at System.Threading.Tasks.ContinuationResultTaskFromResultTask`2.InnerInvoke()
   at System.Threading.Tasks.Task.Execute()
----- Inner Stack Trace -----

Itamar Syn-Hershko

unread,
Feb 23, 2012, 8:27:21 PM2/23/12
to rav...@googlegroups.com
You shouldn't be reusing the session for 2 async operations

I added a failing test, to see if we can make this error any better

Joel

unread,
Feb 23, 2012, 8:33:53 PM2/23/12
to rav...@googlegroups.com
That's good to know, if bizarre, but it doesn't actually make a difference. I get the same error whether or not I do two async operations with the same AsyncSession or two different AsyncSession instances minutes apart.

Joel

unread,
Feb 24, 2012, 1:56:20 PM2/24/12
to rav...@googlegroups.com
Here's my failing test, updated to use two different async sessions, with a 1000ms delay between them. It gets the exact same error.

Incidentally, do you really mean to say that I'm not supposed to be able to do a LoadAsync and a SaveChangesAsync with the same session? What is the point of an async session that can only do a single operation in its lifetime? Why would it matter, as long as I don't try to do two async operations simultaneously?

using System.Linq;
using Raven.Client;
using Raven.Client.Document;
using Raven.Client.Linq;
using Xunit;

namespace RavenAsyncTest
{
    public class Dummy
    {
        public string Id { get; set; }
        public string Name { get; set; }
    }

    public class AsyncTest
    {
        private static IDocumentStore store = null;

        static AsyncTest()
        {
            store = new DocumentStore { Url = "http://localhost:8080/" };
            store.Initialize();
        }

        [Fact]
        public void AsyncQuery()
        {
            using (var session = store.OpenAsyncSession())
            {
                var results = session.Query<Dummy>().ToListAsync();
                results.Wait();
            }
            System.Threading.Thread.Sleep(1000);
            using (var session = store.OpenAsyncSession())
            {
                var results2 = session.Query<Dummy>().ToListAsync();
                results2.Wait();
                Assert.Equal(0, results2.Result.Count);
            }
        }
    }
}


Oren Eini (Ayende Rahien)

unread,
Feb 26, 2012, 3:20:45 AM2/26/12
to rav...@googlegroups.com
Reproduced and fixed, will be in the next build.

Joel

unread,
Feb 26, 2012, 2:07:28 PM2/26/12
to rav...@googlegroups.com

Thanks!

Joel

unread,
Mar 2, 2012, 9:25:47 PM3/2/12
to rav...@googlegroups.com
When should I expect to see this fix? I'm still getting exceptions thrown for 304 Not Modified on async operations in build 701...

Oren Eini (Ayende Rahien)

unread,
Mar 3, 2012, 8:11:57 AM3/3/12
to rav...@googlegroups.com
What?!
Did you update your client?

Joel

unread,
Mar 3, 2012, 9:38:35 AM3/3/12
to rav...@googlegroups.com

I'm pretty sure I did, but I will double check and make some stand alone unit tests in a day or two. In addition, I believe I saw an exception thrown from a 404 when I did a LoadAsync with a non-existant id, instead of returning null. But I'll double check that too.

Joel

unread,
Mar 6, 2012, 1:02:33 AM3/6/12
to rav...@googlegroups.com
I did update my client, and it turns out that ToListAsync() works perfectly in build 701.

The real problem is that IAsyncDocumentSession.LoadAsync seems to have the same problem that ToListAsync used to have. That is to say, loading the same document twice (same session or not) results in an exception thrown from a 304 Not Modified, while loading a bogus ID with LoadAsync throws an exception from 404 Not Found.

I can work around it by using LINQ for everything, but I don't imagine that's as efficient as using LoadAsync when I only want a single document.

Thanks,

Joel

Oren Eini (Ayende Rahien)

unread,
Mar 6, 2012, 6:23:57 AM3/6/12
to rav...@googlegroups.com
Are you sure? I have a passing test for that:

[Fact]
public void AsyncLoad()
{
using (GetNewServer())
using (var store = new DocumentStore
{
}.Initialize())
{
using (var session = store.OpenAsyncSession())
{
session.Store(new Dummy() );

session.SaveChangesAsync().Wait();
}
using (var session = store.OpenAsyncSession())
{
session.LoadAsync<Dummy>("dummies/1").Wait();
Assert.Equal(0, store.JsonRequestFactory.NumberOfCachedRequests);
}
using (var session = store.OpenAsyncSession())
{
session.LoadAsync<Dummy>("dummies/1").Wait();
Assert.Equal(1, store.JsonRequestFactory.NumberOfCachedRequests);

Joel

unread,
Mar 7, 2012, 4:06:44 PM3/7/12
to rav...@googlegroups.com
With build 705 I'm not seeing any 304 exceptions from async loads or async queries. However, here's a test that fails on an exception thrown by a 404 when I try to LoadAsync with a non-existant ID. The synchronous version of the same test passes.

        [Fact]
        public void AsyncLoadNonExistant()
        {
            // load a non-existant entity
            using (var session = store.OpenAsyncSession())
            {
                var loaded = session.LoadAsync<Dummy>("dummies/-1337");
                loaded.Wait();
                Assert.Null(loaded.Result);

Oren Eini (Ayende Rahien)

unread,
Mar 8, 2012, 5:09:50 AM3/8/12
to rav...@googlegroups.com
Thanks, we had an issue with AggregateException vs WebException.
Fixed now.
Reply all
Reply to author
Forward
0 new messages