Why does RemoteDatabsaeChanges has DisposeAsync, and other pro dev tips
The following piece of code is taken from the RavenDB’s RemoteDatabaseChanges class, which implements the client side behavior for the RavenDB Changes API:
As you can see, we are doing something really strange here, DisposeAsync().
The reason it is there is that we need to send a command to the server to tell it to disconnect the connection from its end. Sure, we can just abort the request from our end (in fact, we are doing that), but only after we have tried to get the server to do this.
Why are we doing this?
The answer is quite simple. We want good Fiddler support.
By sending the disconnect command, we ensure that the connection will be properly closed, and Fiddler can then show the content, like so:
Being able to look at those (even if only after the connection has been closed) is invaluable when doing diagnostics, debugging or just wanting to take a peek.
On the hand, if we weren’t doing this, we would get 502 or 504 errors from Fiddler, which is annoying and opaque. And that isn’t a good way to create a good feel for people trying out your products.
Comments
DDD - Debug Driven Design
Wouldn't the application throw an exception if this runs when the app is closing down?
Chadbr, We are handling this.
I really like the "making live services more debuggable" series you are running.
a couple of things though: 1. why new CompletedTask all the time? since all CompletedTasks are essentially the same you could be able to have a CompletedTask.Instance or something of sorts, if you're doing that a lot. 2. are you 100% sure that keyValuePair.Value will never be null there? connections might leak in that (perhaps remote) case
Ken,
1) The cost of new object() is minimal.
2) No, the value is never null.
Without looking at your code, I'd guess that CompletedTask will generate a TaskCompletionSource and set its value. A new TaskCompletionSource() is hardly equivalent to new object(). A Task Completion Source etc is hardly a simple object(). who knows what it is doing internally during the construction of the tcs.
e.g. Brad Wilson on http://bradwilson.typepad.com/blog/2012/04/tpl-and-servers-pt4.html
talks about the cost for TCS creations, and advocates re-using cached versions for Completed (and Cancelled) tasks
as for 2) are you absolutely certain that no-when in the future you'll be null-ing a value in that dictionary for some reason, causing a failure here that no test will catch? Dispose calls should be as safe as possible, especially in a highly concurrent server env.
Ken, This code: var sw = Stopwatch.StartNew(); for (int i = 0; i < 1000 * 1000; i++) { var tcs = new TaskCompletionSource<object>(); tcs.SetResult(null); } Console.WriteLine(sw.ElapsedMilliseconds);
Completes in less than 150 ms, so I think that we are good on that regard.
As for anyhow anywhen for the error, no. But I am pretty sure that there is a test that will catch it if it will happen.
Comment preview