Пример #1
0
        public void CanUseToISOString()
        {
            var date       = DateTime.UtcNow;
            var dateOffset = DateTime.Now.AddMilliseconds(100);
            var testObject = new CustomType {
                Date = date, DateOffset = dateOffset
            };
            var doc   = RavenJObject.FromObject(testObject);
            var patch = new ScriptedPatchRequest()
            {
                Script = @"
this.DateOutput = new Date(this.Date).toISOString();
this.DateOffsetOutput = new Date(this.DateOffset).toISOString();
"
            };

            using (var scope = new DefaultScriptedJsonPatcherOperationScope())
            {
                var scriptedJsonPatcher = new ScriptedJsonPatcher();
                var result = scriptedJsonPatcher.Apply(scope, doc, patch);

                var dateOutput       = result.Value <string>("DateOutput");
                var dateOffsetOutput = result.Value <string>("DateOffsetOutput");

                // With the custom fixes to Jint, these tests now pass (RavenDB-1536)
                Assert.Equal(date.ToString("yyyy-MM-ddTHH:mm:ss.fffZ"), dateOutput);
                Assert.Equal(dateOffset.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffZ"), dateOffsetOutput);
            }
        }
Пример #2
0
        public void PatcherCanOutputObjectsCorrectly()
        {
            var          doc    = RavenJObject.Parse("{}");
            const string script = @"output(undefined);
                                output(true);
                                output(2);
                                output(2.5);
                                output('string');
                                output(null);
                                output([2, 'c']);
                                output({'a': 'c', 'f': { 'x' : 2}});"
            ;

            var patch = new ScriptedPatchRequest()
            {
                Script = script
            };

            using (var scope = new DefaultScriptedJsonPatcherOperationScope())
            {
                var patcher = new ScriptedJsonPatcher();
                patcher.Apply(scope, doc, patch);
                Assert.Equal(8, patcher.Debug.Count);
                Assert.Equal("undefined", patcher.Debug[0]);
                Assert.Equal("True", patcher.Debug[1]);
                Assert.Equal("2", patcher.Debug[2]);
                Assert.Equal("2.5", patcher.Debug[3]);
                Assert.Equal("string", patcher.Debug[4]);
                Assert.Equal("null", patcher.Debug[5]);
                Assert.Equal("[2,\"c\"]", patcher.Debug[6]);
                Assert.Equal("{\"a\":\"c\",\"f\":{\"x\":2}}", patcher.Debug[7]);
            }
        }
Пример #3
0
        public void CanProcess()
        {
            var document = new RavenJObject
            {
                {
                    "Data", new RavenJObject
                    {
                        { "Title", "Hi" }
                    }
                }
            };

            const string name = @"Raven.Tests.Patching.x2js.js";
            var          manifestResourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(name);
            var          code = new StreamReader(manifestResourceStream).ReadToEnd();

            var jsonPatcher = new ScriptedJsonPatcher();

            using (var scope = new DefaultScriptedJsonPatcherOperationScope())
            {
                scope.CustomFunctions = new JsonDocument
                {
                    DataAsJson = new RavenJObject
                    {
                        { "Functions", code }
                    }
                };

                jsonPatcher.Apply(scope, document, new ScriptedPatchRequest
                {
                    Script = "this.Xml = js2x(this.Data);"
                });
            }
        }
Пример #4
0
        public Tuple <PatchResultData, List <string> > ApplyPatch(string docId, Etag etag,
                                                                  ScriptedPatchRequest patchExisting, ScriptedPatchRequest patchDefault, RavenJObject defaultMetadata,
                                                                  TransactionInformation transactionInformation, bool debugMode = false, IEnumerable <string> participatingIds = null)
        {
            ScriptedJsonPatcher scriptedJsonPatcher        = null;
            DefaultScriptedJsonPatcherOperationScope scope = null;

            try
            {
                var applyPatchInternal = ApplyPatchInternal(docId, etag, transactionInformation,
                                                            jsonDoc =>
                {
                    scope = scope ?? new DefaultScriptedJsonPatcherOperationScope(Database, debugMode);
                    scriptedJsonPatcher = new ScriptedJsonPatcher(Database);
                    return(scriptedJsonPatcher.Apply(scope, jsonDoc.ToJson(), patchExisting, jsonDoc.SerializedSizeOnDisk, jsonDoc.Key));
                },
                                                            () =>
                {
                    if (patchDefault == null)
                    {
                        return(null);
                    }

                    scope = scope ?? new DefaultScriptedJsonPatcherOperationScope(Database, debugMode);

                    scriptedJsonPatcher         = new ScriptedJsonPatcher(Database);
                    var jsonDoc                 = new RavenJObject();
                    jsonDoc[Constants.Metadata] = defaultMetadata.CloneToken() ?? new RavenJObject();
                    return(scriptedJsonPatcher.Apply(scope, jsonDoc, patchDefault, 0, docId));
                },
                                                            () =>
                {
                    if (scope == null)
                    {
                        return(null);
                    }
                    return(scope
                           .GetPutOperations()
                           .ToList());
                },
                                                            () =>
                {
                    if (scope == null)
                    {
                        return(null);
                    }

                    return(scope.DebugActions);
                },
                                                            debugMode, participatingIds: participatingIds);
                return(Tuple.Create(applyPatchInternal, scriptedJsonPatcher == null ? new List <string>() : scriptedJsonPatcher.Debug));
            }
            finally
            {
                if (scope != null)
                {
                    scope.Dispose();
                }
            }
        }
Пример #5
0
        public void CanLoadPutDocumentsMultipleTimesInPatcher()
        {
            using (var store = NewDocumentStore())
            {
                using (var s = store.OpenSession())
                {
                    s.Store(new OpCounter(), "opCounter");
                    s.SaveChanges();
                }

                var patcher = new ScriptedJsonPatcher(store.DocumentDatabase);
                using (var scope = new ScriptedIndexResultsJsonPatcherScope(store.DocumentDatabase, new HashSet <string> {
                    "dogs"
                }))
                {
                    patcher.Apply(scope, new RavenJObject(), new ScriptedPatchRequest
                    {
                        Script =
                            @"var opCounterId = 'opCounter';
	var opCounter = LoadDocument(opCounterId) || {};
	opCounter.Index++;
	PutDocument(opCounterId, opCounter);
	opCounter = LoadDocument(opCounterId)
	opCounter.Deletes++;
	PutDocument(opCounterId, opCounter);
	"
                    });

                    store.DocumentDatabase.TransactionalStorage.Batch(accessor =>
                    {
                        foreach (var operation in scope.GetOperations())
                        {
                            switch (operation.Type)
                            {
                            case ScriptedJsonPatcher.OperationType.Put:
                                store.DocumentDatabase.Documents.Put(operation.Document.Key, operation.Document.Etag, operation.Document.DataAsJson,
                                                                     operation.Document.Metadata, null);
                                break;

                            case ScriptedJsonPatcher.OperationType.Delete:
                                store.DocumentDatabase.Documents.Delete(operation.DocumentKey, null, null);
                                break;

                            default:
                                throw new ArgumentOutOfRangeException("operation.Type");
                            }
                        }
                    });
                }

                using (var s = store.OpenSession())
                {
                    var opCounter = s.Load <OpCounter>("opCounter");
                    Assert.Equal(1, opCounter.Deletes);
                    Assert.Equal(1, opCounter.Index);
                }
            }
        }
Пример #6
0
        public void CreateDocumentShouldThrowIfSpecifiedJsonIsNullOrEmptyString()
        {
            var doc = RavenJObject.FromObject(test);
            var advancedJsonPatcher = new ScriptedJsonPatcher();
            var x = Assert.Throws <InvalidOperationException>(() => advancedJsonPatcher.Apply(doc, new ScriptedPatchRequest
            {
                Script = @"PutDocument('Items/1', null);"
            }));

            Assert.Contains("Created document cannot be null or empty. Document key: 'Items/1'", x.InnerException.Message);

            x = Assert.Throws <InvalidOperationException>(() => advancedJsonPatcher.Apply(doc, new ScriptedPatchRequest
            {
                Script = @"PutDocument('Items/1', null, null);"
            }));

            Assert.Contains("Created document cannot be null or empty. Document key: 'Items/1'", x.InnerException.Message);
        }
Пример #7
0
        public void LongStringRejected()
        {
            var doc = RavenJObject.FromObject(test);
            var advancedJsonPatcher = new ScriptedJsonPatcher();

            Assert.Throws <NotSupportedException>(() => advancedJsonPatcher.Apply(doc, new ScriptedPatchRequest
            {
                Script = new string('a', 8193)
            }));
        }
Пример #8
0
        public void DefiningFunctionForbidden()
        {
            var doc = RavenJObject.FromObject(test);
            var advancedJsonPatcher = new ScriptedJsonPatcher();

            Assert.Throws <NotSupportedException>(() => advancedJsonPatcher.Apply(doc, new ScriptedPatchRequest
            {
                Script = "function a() { a(); }"
            }));
        }
Пример #9
0
        public void CannotUseWhile()
        {
            var doc = RavenJObject.FromObject(test);
            var advancedJsonPatcher = new ScriptedJsonPatcher();

            Assert.Throws <NotSupportedException>(() => advancedJsonPatcher.Apply(doc, new ScriptedPatchRequest
            {
                Script = "while(true) {}"
            }));
        }
Пример #10
0
        public void CannotUseInfiniteLoop()
        {
            var doc = RavenJObject.FromObject(test);
            var advancedJsonPatcher = new ScriptedJsonPatcher();
            var x = Assert.Throws <InvalidOperationException>(() => advancedJsonPatcher.Apply(doc, new ScriptedPatchRequest
            {
                Script = "while(true) {}"
            }));

            Assert.Contains("Too many steps in script", x.Message);
        }
Пример #11
0
        public void CreateDocumentShouldThrowInvalidEtagException()
        {
            var doc = RavenJObject.FromObject(test);
            var advancedJsonPatcher = new ScriptedJsonPatcher();
            var x = Assert.Throws <InvalidOperationException>(() => advancedJsonPatcher.Apply(doc, new ScriptedPatchRequest
            {
                Script = @"PutDocument('Items/1', { Property: 1}, {'@etag': 'invalid-etag' });"
            }));

            Assert.Contains("Invalid ETag value 'invalid-etag' for document 'Items/1'", x.InnerException.Message);
        }
Пример #12
0
        public void CanOutputDebugInformation()
        {
            var doc = RavenJObject.FromObject(test);
            var advancedJsonPatcher = new ScriptedJsonPatcher();

            advancedJsonPatcher.Apply(doc, new ScriptedPatchRequest
            {
                Script = "output(this.Id)"
            });

            Assert.Equal("someId", advancedJsonPatcher.Debug[0]);
        }
Пример #13
0
        public void ShouldWork()
        {
            var scriptedJsonPatcher = new ScriptedJsonPatcher();
            var result = scriptedJsonPatcher.Apply(new RavenJObject {
                { "Val", double.NaN }
            }, new ScriptedPatchRequest
            {
                Script = @"this.Finite = isFinite(this.Val);"
            });

            Assert.False(result.Value <bool>("Finite"));
        }
Пример #14
0
        public void CanRemoveFromCollectionByCondition()
        {
            var doc = RavenJObject.FromObject(test);
            var advancedJsonPatcher = new ScriptedJsonPatcher();
            var resultJson          = advancedJsonPatcher.Apply(doc, new ScriptedPatchRequest
            {
                Script = @"
this.Comments.RemoveWhere(function(el) {return el == 'seven';});
"
            });
            var result = JsonConvert.DeserializeObject <CustomType>(resultJson.ToString());

            Assert.Equal(new[] { "one", "two" }.ToList(), result.Comments);
        }
Пример #15
0
        public void ScriptPatchShouldGenerateNiceException()
        {
            using (var store = NewDocumentStore())
            {
                using (var session = store.OpenSession())
                {
                    session.Store(new SimpleUser {
                        FirstName = "John", LastName = "Smith"
                    });
                    session.SaveChanges();
                }

                store
                .DatabaseCommands
                .Put(
                    Constants.RavenJavascriptFunctions,
                    null,
                    RavenJObject.FromObject(new { Functions =
                                                      @"exports.a = function(value) { return  b(value); };
exports.b = function(v) { return c(v); }
exports.c = function(v) { throw 'oops'; }
" }),
                    new RavenJObject());

                WaitForIndexing(store);

                var patcher = new ScriptedJsonPatcher(store.SystemDatabase);
                using (var scope = new ScriptedIndexResultsJsonPatcherScope(store.SystemDatabase, new HashSet <string>()))
                {
                    var e = Assert.Throws <InvalidOperationException>(() => patcher.Apply(scope, new RavenJObject(), new ScriptedPatchRequest
                    {
                        Script = @"var s = 1234; 
a(s);"
                    }));
                    Assert.Equal(@"Unable to execute JavaScript: 
var s = 1234; 
a(s);

Error: 
oops
Stacktrace:
[email protected]:3
[email protected]:2
[email protected]:1
[email protected]:2
anonymous [email protected]:1", e.Message);
                }
            }
        }
Пример #16
0
        public void CanOutputDebugInformation()
        {
            var doc = RavenJObject.FromObject(test);

            using (var scope = new DefaultScriptedJsonPatcherOperationScope())
            {
                var advancedJsonPatcher = new ScriptedJsonPatcher();
                advancedJsonPatcher.Apply(scope, doc, new ScriptedPatchRequest
                {
                    Script = "output(this.Id)"
                });

                Assert.Equal("someId", advancedJsonPatcher.Debug[0]);
            }
        }
Пример #17
0
        public void CanUseSplit()
        {
            var          doc    = RavenJObject.Parse("{\"Email\":'*****@*****.**'}");
            const string script = @"
this.Parts = this.Email.split('@');";
            var          patch  = new ScriptedPatchRequest()
            {
                Script = script,
            };
            var scriptedJsonPatcher = new ScriptedJsonPatcher();
            var result = scriptedJsonPatcher.Apply(doc, patch);

            Assert.Equal(result["Parts"].Value <RavenJArray>()[0], "somebody");
            Assert.Equal(result["Parts"].Value <RavenJArray>()[1], "somewhere.com");
        }
Пример #18
0
        public void ShouldWork()
        {
            var scriptedJsonPatcher = new ScriptedJsonPatcher();

            using (var scope = new DefaultScriptedJsonPatcherOperationScope())
            {
                var result = scriptedJsonPatcher.Apply(scope, new RavenJObject {
                    { "Val", double.NaN }
                }, new ScriptedPatchRequest
                {
                    Script = @"this.Finite = isFinite(this.Val);"
                });

                Assert.False(result.Value <bool>("Finite"));
            }
        }
Пример #19
0
        public Tuple <PatchResultData, List <string> > ApplyPatch(string docId, Etag etag, ScriptedPatchRequest patch,
                                                                  TransactionInformation transactionInformation, bool debugMode = false)
        {
            ScriptedJsonPatcher scriptedJsonPatcher        = null;
            DefaultScriptedJsonPatcherOperationScope scope = null;

            try
            {
                var applyPatchInternal = ApplyPatchInternal(docId, etag, transactionInformation,
                                                            jsonDoc =>
                {
                    scope = new DefaultScriptedJsonPatcherOperationScope(Database, debugMode);
                    scriptedJsonPatcher = new ScriptedJsonPatcher(Database);
                    return(scriptedJsonPatcher.Apply(scope, jsonDoc.ToJson(), patch, jsonDoc.SerializedSizeOnDisk, jsonDoc.Key));
                },
                                                            () => null,
                                                            () =>
                {
                    if (scope == null)
                    {
                        return(null);
                    }
                    return(scope
                           .GetPutOperations()
                           .ToList());
                },
                                                            () =>
                {
                    if (scope == null)
                    {
                        return(null);
                    }

                    return(scope.DebugActions);
                },
                                                            debugMode);

                return(Tuple.Create(applyPatchInternal, scriptedJsonPatcher == null ? new List <string>() : scriptedJsonPatcher.Debug));
            }
            finally
            {
                if (scope != null)
                {
                    scope.Dispose();
                }
            }
        }
Пример #20
0
        public void ScriptedIndexResultsPatcherShouldNotPatchDocumentsThatAreIndirectlyReferencedByIndexRaw()
        {
            using (var store = NewDocumentStore(activeBundles: "ScriptedIndexResults"))
            {
                new CustomerOrderTotal().Execute(store);

                using (var session = store.OpenSession())
                {
                    session.Store(new Customer {
                        Name = "Customer1", StoredTotal = 100, Id = "customers/1"
                    });
                    session.SaveChanges();

                    session.Store(new Order {
                        Customers = new List <string> {
                            "customers/1"
                        }, OrderItems = 10
                    });
                    session.SaveChanges();
                }

                WaitForIndexing(store);

                var patcher = new ScriptedJsonPatcher(store.SystemDatabase);
                using (var scope = new ScriptedIndexResultsJsonPatcherScope(store.SystemDatabase, new HashSet <string> {
                    "Orders"
                }))
                {
                    var e = Assert.Throws <InvalidOperationException>(() => patcher.Apply(scope, new RavenJObject(), new ScriptedPatchRequest
                    {
                        Script = @"var customer = LoadDocument('customers/1')
if(customer == null) return;
if(customer.StoredTotal != this.TotalOrderItems){
  customer.StoredTotal = this.TotalOrderItems;
  PutDocument('customers/1', customer);
}"
                    }));

                    Assert.Equal("Cannot PUT document 'customers/1' to prevent infinite indexing loop. Avoid modifying documents that could be indirectly referenced by index.", e.InnerException.Message);
                }
            }
        }
Пример #21
0
        public void CannotUseInfiniteLoop()
        {
            var doc = RavenJObject.FromObject(test);
            var advancedJsonPatcher = new ScriptedJsonPatcher();
            var x = Assert.Throws <InvalidOperationException>(() =>
            {
                using (var scope = new DefaultScriptedJsonPatcherOperationScope())
                {
                    advancedJsonPatcher.Apply(scope, doc, new ScriptedPatchRequest {
                        Script = "while(true) {}"
                    });
                }
            });

            Assert.Contains("Unable to execute JavaScript", x.Message);

            var inner = x.InnerException as StatementsCountOverflowException;

            Assert.NotNull(inner);
            Assert.Equal("The maximum number of statements executed have been reached.", inner.Message);
        }
Пример #22
0
            public override void Dispose()
            {
                var patcher = new ScriptedJsonPatcher(database);

                using (var scope = new ScriptedIndexResultsJsonPatcherScope(database, forEntityNames))
                {
                    if (string.IsNullOrEmpty(scriptedIndexResults.DeleteScript) == false)
                    {
                        foreach (var kvp in removed)
                        {
                            foreach (var entry in kvp.Value)
                            {
                                patcher.Apply(scope, entry, new ScriptedPatchRequest
                                {
                                    Script = scriptedIndexResults.DeleteScript,
                                    Values =
                                    {
                                        { "key", kvp.Key }
                                    }
                                });

                                if (Log.IsDebugEnabled && patcher.Debug.Count > 0)
                                {
                                    Log.Debug("Debug output for doc: {0} for index {1} (delete):\r\n.{2}", kvp.Key, scriptedIndexResults.Id, string.Join("\r\n", patcher.Debug));

                                    patcher.Debug.Clear();
                                }
                            }
                        }
                    }

                    if (string.IsNullOrEmpty(scriptedIndexResults.IndexScript) == false)
                    {
                        foreach (var kvp in created)
                        {
                            try
                            {
                                foreach (var entry in kvp.Value)
                                {
                                    patcher.Apply(scope, entry, new ScriptedPatchRequest
                                    {
                                        Script = scriptedIndexResults.IndexScript,
                                        Values =
                                        {
                                            { "key", kvp.Key }
                                        }
                                    });
                                }
                            }
                            catch (Exception e)
                            {
                                Log.Warn("Could not apply index script " + scriptedIndexResults.Id + " to index result with key: " + kvp.Key, e);
                            }
                            finally
                            {
                                if (Log.IsDebugEnabled && patcher.Debug.Count > 0)
                                {
                                    Log.Debug("Debug output for doc: {0} for index {1} (index):\r\n.{2}", kvp.Key, scriptedIndexResults.Id, string.Join("\r\n", patcher.Debug));

                                    patcher.Debug.Clear();
                                }
                            }
                        }
                    }

                    database.TransactionalStorage.Batch(accessor =>
                    {
                        foreach (var operation in scope.GetOperations())
                        {
                            switch (operation.Type)
                            {
                            case ScriptedJsonPatcher.OperationType.Put:
                                database.Documents.Put(operation.Document.Key, operation.Document.Etag, operation.Document.DataAsJson, operation.Document.Metadata, null);
                                break;

                            case ScriptedJsonPatcher.OperationType.Delete:
                                database.Documents.Delete(operation.DocumentKey, null, null);
                                break;

                            default:
                                throw new ArgumentOutOfRangeException("operation.Type");
                            }
                        }
                    });
                }
            }
            public override void Dispose()
            {
                bool   shouldRetry = false;
                int    retries     = 128;
                Random rand        = null;

                do
                {
                    using (shouldRetry ? database.TransactionalStorage.DisableBatchNesting() : null)
                    {
                        var patcher = new ScriptedJsonPatcher(database);
                        using (var scope = new ScriptedIndexResultsJsonPatcherScope(database, forEntityNames))
                        {
                            if (string.IsNullOrEmpty(scriptedIndexResults.DeleteScript) == false)
                            {
                                foreach (var kvp in removed)
                                {
                                    foreach (var entry in kvp.Value)
                                    {
                                        try
                                        {
                                            patcher.Apply(scope, entry, new ScriptedPatchRequest
                                            {
                                                Script = scriptedIndexResults.DeleteScript,
                                                Values =
                                                {
                                                    {
                                                        "key", kvp.Key
                                                    }
                                                }
                                            });
                                        }
                                        catch (Exception e)
                                        {
                                            Log.WarnException("Could not apply delete script " + scriptedIndexResults.Id + " to index result with key: " + kvp.Key, e);
                                        }
                                        finally
                                        {
                                            if (Log.IsDebugEnabled && patcher.Debug.Count > 0)
                                            {
                                                Log.Debug("Debug output for doc: {0} for index {1} (delete):\r\n.{2}", kvp.Key, scriptedIndexResults.Id, string.Join("\r\n", patcher.Debug));

                                                patcher.Debug.Clear();
                                            }
                                        }
                                    }
                                }
                            }

                            if (string.IsNullOrEmpty(scriptedIndexResults.IndexScript) == false)
                            {
                                foreach (var kvp in created)
                                {
                                    try
                                    {
                                        foreach (var entry in kvp.Value)
                                        {
                                            patcher.Apply(scope, entry, new ScriptedPatchRequest
                                            {
                                                Script = scriptedIndexResults.IndexScript,
                                                Values =
                                                {
                                                    {
                                                        "key", kvp.Key
                                                    }
                                                }
                                            });
                                        }
                                    }
                                    catch (Exception e)
                                    {
                                        Log.WarnException("Could not apply index script " + scriptedIndexResults.Id + " to index result with key: " + kvp.Key, e);
                                    }
                                    finally
                                    {
                                        if (Log.IsDebugEnabled && patcher.Debug.Count > 0)
                                        {
                                            Log.Debug("Debug output for doc: {0} for index {1} (index):\r\n.{2}", kvp.Key, scriptedIndexResults.Id, string.Join("\r\n", patcher.Debug));

                                            patcher.Debug.Clear();
                                        }
                                    }
                                }
                            }

                            try
                            {
                                database.TransactionalStorage.Batch(accessor =>
                                {
                                    foreach (var operation in scope.GetOperations())
                                    {
                                        switch (operation.Type)
                                        {
                                        case ScriptedJsonPatcher.OperationType.Put:
                                            if (Log.IsDebugEnabled)
                                            {
                                                Log.Debug("Perform PUT on {0} for scripted index results {1}", operation.Document.Key, scriptedIndexResults.Id);
                                            }

                                            database.Documents.Put(operation.Document.Key, operation.Document.Etag, operation.Document.DataAsJson, operation.Document.Metadata, null);
                                            break;

                                        case ScriptedJsonPatcher.OperationType.Delete:
                                            if (Log.IsDebugEnabled)
                                            {
                                                Log.Debug("Perform DELETE on {0} for scripted index results {1}", operation.DocumentKey, scriptedIndexResults.Id);
                                            }

                                            database.Documents.Delete(operation.DocumentKey, null, null);
                                            break;

                                        default:
                                            throw new ArgumentOutOfRangeException("operation.Type: " + operation.Type);
                                        }
                                    }
                                });

                                shouldRetry = false;
                            }
                            catch (ConcurrencyException ex)
                            {
                                if (scriptedIndexResults.RetryOnConcurrencyExceptions && retries-- > 0)
                                {
                                    shouldRetry = true;
                                    if (rand == null)
                                    {
                                        rand = new Random();
                                    }

                                    if (Log.IsDebugEnabled)
                                    {
                                        Log.DebugException(string.Format("Applying PUT/DELETE for scripted index results {0} failed with concurrency exception. Retrying", scriptedIndexResults.Id), ex);
                                    }

                                    Thread.Sleep(rand.Next(5, Math.Max(retries * 2, 10)));

                                    continue;
                                }

                                if (Log.IsDebugEnabled)
                                {
                                    Log.DebugException(string.Format("Applying PUT/DELETE for scripted index results {0} failed with concurrency exception {1} times.", scriptedIndexResults.Id, 128 - retries + 1), ex);
                                }

                                throw;
                            }
                        }
                    }
                } while (shouldRetry);
            }