What is new in RavenDB 3.0Client side
While most of the time, when a user is working with RavenDB, they do so via the browser, developers spend most of their time in code, and when working with RavenDB, that means working with the RavenDB Client API. We have spent quite a bit of time on that as well, as you can imagine. Here are a few of the highlights.
Fully async, all the way through. Communication with RavenDB is done to a remote server, which means that a lot of time is spent just doing I/O. Recognizing this, we are now taking full advantage of the async API available to us and the entirety of RavenDB 3.0 Client API is async. Previously, we had an async and sync version of the stack, which cause compatibility issues, some stuff worked for sync and not for async, or vice versa. With 3.0, we now has a single code path, and it is all async. For the sync API, we are just wrapping the async API. That gives us a single code path, and a fully async I/O throughout, unless you chose to use the sync API, at which point we’ll wait, per your request.
Lazy async is fully supported now. As part of the fully async part, we now have support for lazy operations on the full async session.
Lazy timings. As long as we are speaking lazily, a frequent request was to be able to get the actual time that the lazy request spent on the server side. That was actually interesting, because when we first implemented this feature, we thought we had a bug. The total time for the request was lower than the time for each individual request. Then I realized that we are actually running the requests in parallel inside the server, so that made sense.
Embedded / remote clients unity. Similar to the previous issue, embedded clients had a totally different code path than remote clients. That caused issues because sometimes you had something that would work in embedded but not in remote. And that sucked. We changes things so now everything works through the same (async!) pipeline. That means that you can do async calls on embedded databases, and that as far as RavenDB is concerned, there really is no difference if you are calling me from the same process or remotely.
Admin operation split was done so we won’t have a developer accidently try to use an operation that requires admin privileges. Now all of the privilege actions are under the cmds.Admin or cmds.GlobalAdmin properties. That gives you a good indication about the permission levels that you need for an operation. Either you just need access to the database (obvious), or you are a database admin (able to do things such as take backups, start / stop indexing, etc) or you are a server admin, and can create or delete databases, change permissions, etc.
Bulk insert errors are now handled much better, previously we had to wait until the operation would be completed, which could be quite a while. Now we can detect and error on them immediately.
Bulk insert change detection. Users often use bulk insert to manage ETL processes. It is very common to have a nightly process that run over the data and write large portions of it. With 3.0, we have the ability to specify that the data might actually be the same, so the bulk insert process will check, and if the stored value and the new value is the same, the server will skip writing to this document. In this way, we won’t have to re-index this document, re-replicate it, etc.
Reduced client side allocations. RavenDB users often run their software for months at a time, that means that anything that we can do to help reduce resource consumption is good. We have changed how we work internally to reduce the number of allocations that we are doing, and in particular to reduce the number of large object heap allocations. This tend to reduce the overall resource cost significantly over time.
What changes? In RavenDB, you could ask the session if there has been any changes (ie, if a call to SaveChanges() will go to the server), or if a particular entity had changes. Honestly, we added that feature strictly for our own testing, we didn’t think it would actually be used. Overtime, we saw that users often had questions in the form of: “I loaded the document, made no changes, but it is still saying that it changed!” The answer for those questions ranged from: “You have a computed Age field that uses the current time to calculate itself” to “you added/remove a property, and now it needs to be saved.” Sometimes it was our change detection code that had a false positive, as well, but any time this happened, that required a support call to resolve. Now, you can call session.Advanced.WhatChanged(), which will give you a dictionary with full details on all the changes that happened in the session.
Missing properties retention. This one is probably the first feature that we developed strictly for 3.0. The issue is what happens when you load a document from the database, but it has extra properties. What do I mean by that? Imagine that we changed our code to remove the FullName property. However, all our documents retain that property. In 2.5, loading and saving the document would overwrite the existing document with the new one, without the property. We got feedback from customers that this wasn’t a desirable behavior. Now, even though the FullName property isn’t accessible from your model, it will be retained (even if you have made changes to other properties).
Formatted indexes. In 2.5, you usually define indexes using the linq query format, but when you look at them on the server side, they can be… quite ugly. We are now using the same index format technique we have server side to prettify the indexes and make sure that they look very similar to the way you define them in code.
There are other stuff that went into the client, better Linq query support, you can now do includes on the results of MoreLikeThis query, and a lot of other stuff that I just done have the time (and you the patience) to go over them all. Those are the highlights, the things that really stand out.
More posts in "What is new in RavenDB 3.0" series:
- (24 Sep 2014) Meta discussion
- (23 Sep 2014) Operations–Optimizations
- (22 Sep 2014) Operations–the nitty gritty details
- (22 Sep 2014) Operations–production view
- (19 Sep 2014) Operations–the pretty pictures tour
- (19 Sep 2014) SQL Replication
- (18 Sep 2014) Queries improvements
- (17 Sep 2014) Query diagnostics
- (17 Sep 2014) Indexing enhancements
- (16 Sep 2014) Indexing backend
- (15 Sep 2014) Simplicity
- (15 Sep 2014) JVM Client API
- (12 Sep 2014) Client side
- (11 Sep 2014) The studio
- (11 Sep 2014) RavenFS
- (10 Sep 2014) Voron
@Oren: there is a part missing in the 3rd bullet point. You say "That was actually interesting, because when we first implemented this feature," and then abruptly stop.
FYI: There is an infinite loop in the "next" links at the top of the article. http://ayende.com/blog/168420/ravendb-unrecoverable-database-and-data-loss says the next article is http://ayende.com/blog/168386/what-is-new-in-ravendb-3-0-client-side, which says the next article is http://ayende.com/blog/168420/ravendb-unrecoverable-database-and-data-loss. Racoon bug?
Njy, thanks, fixed.
Daniel, Fixed, and yes, that is a bug in how we handle this inside Raccoon.
I was reviewing this today to remind myself of what's coming up and noticed the comments on: 'Missing properties retention'. The current behaviour of it removing the missing properties is exactly what we want to happen 99% of the time because it's a great way of clearing up old stuff that is not needed any more. We have a big clean up coming soon for unneeded properties (spread everywhere) and don't want to delay upgrading to 3.0 because of this change. Is this optional behaviour so we can retain the way it currently works? Although I'm sure you have optimised this, I wouldn't want to have the overhead of merging the documents either which surely must have some cost on every save?
Hi Ian, Yes, you can do that by setting Conventions.PreserveDocumentPropertiesNotFoundOnModel = false.
Good news, thanks...