private Task<RangeValue> GetNextMaxAsyncInner(IAsyncDatabaseCommands databaseCommands)
{
var minNextMax = Range.Max;
return GetDocumentAsync(databaseCommands)
.ContinueWith(task =>
{
try
{
JsonDocument document;
try
{
document = task.Result;
}
catch (ConflictException e)
{
// resolving the conflict by selecting the highest number
var highestMax = e.ConflictedVersionIds
.Select(conflictedVersionId => databaseCommands.GetAsync(conflictedVersionId)
.ContinueWith(t => GetMaxFromDocument(t.Result, minNextMax)))
.AggregateAsync(Enumerable.Max);
return highestMax
.ContinueWith(t => PutDocumentAsync(databaseCommands, new JsonDocument
{
Etag = e.Etag,
Metadata = new RavenJObject(),
DataAsJson = RavenJObject.FromObject(new {Max = t.Result}),
Key = HiLoDocumentKey
}))
.Unwrap()
.ContinueWithTask(() => GetNextRangeAsync(databaseCommands));
}
long min, max;
if (document == null)
{
min = minNextMax + 1;
max = minNextMax + capacity;
document = new JsonDocument
{
Etag = Etag.Empty,
// sending empty etag means - ensure the that the document does NOT exists
Metadata = new RavenJObject(),
DataAsJson = RavenJObject.FromObject(new {Max = max}),
Key = HiLoDocumentKey
};
}
else
{
var oldMax = GetMaxFromDocument(document, minNextMax);
min = oldMax + 1;
max = oldMax + capacity;
document.DataAsJson["Max"] = max;
}
return PutDocumentAsync(databaseCommands, document).WithResult(new RangeValue(min, max));
}
catch (ConcurrencyException)
{
return GetNextMaxAsyncInner(databaseCommands);
}
}).Unwrap();
}