/// <summary> /// Sends a patch request for a specific document, ignoring the document's Etag /// </summary> /// <param name="key">Id of the document to patch</param> /// <param name="patch">The patch request to use (using JavaScript)</param> /// <param name="ignoreMissing">true if the patch request should ignore a missing document, false to throw DocumentDoesNotExistException</param> public RavenJObject Patch(string key, ScriptedPatchRequest patch, bool ignoreMissing) { return(asyncServerClient.PatchAsync(key, patch, ignoreMissing).ResultUnwrap()); }
public RavenJObject Patch(string key, ScriptedPatchRequest patchExisting, ScriptedPatchRequest patchDefault, RavenJObject defaultMetadata) { return(AsyncHelpers.RunSync(() => asyncServerClient.PatchAsync(key, patchExisting, patchDefault, defaultMetadata))); }
public virtual RavenJObject Apply(ScriptedJsonPatcherOperationScope scope, RavenJObject document, ScriptedPatchRequest patch, int size = 0, string docId = null) { if (document == null) { return(null); } if (String.IsNullOrEmpty(patch.Script)) { throw new InvalidOperationException("Patch script must be non-null and not empty"); } var resultDocument = ApplySingleScript(document, patch, size, docId, scope); if (resultDocument != null) { document = resultDocument; } return(document); }
public override void Execute(object parameter) { AskUser.ConfirmationAsync("Patch Documents", "Are you sure you want to apply this patch to all matching documents?") .ContinueWhenTrueInTheUIThread(() => { patchModel.ClearQueryError(); var values = patchModel.GetValues(); if (values == null) { return; } var request = new ScriptedPatchRequest { Script = patchModel.Script.CurrentSnapshot.Text, Values = values }; patchModel.InProcess.Value = true; switch (patchModel.PatchOn) { case PatchOnOptions.Document: var commands = new ICommandData[1]; commands[0] = new ScriptedPatchCommandData { Patch = request, Key = patchModel.SelectedItem }; ApplicationModel.Database.Value.AsyncDatabaseCommands.BatchAsync(commands) .ContinueOnUIThread(t => { if (t.IsFaulted) { patchModel.HandlePatchError(t.Exception); } }) .ContinueOnSuccessInTheUIThread( () => ApplicationModel.Database.Value.AsyncDatabaseCommands.GetAsync(patchModel.SelectedItem). ContinueOnSuccessInTheUIThread(doc => { patchModel.OriginalDoc.SetText(doc.ToJson().ToString()); patchModel.NewDoc.SetText(""); patchModel.ShowAfterPrompt = true; })) .Finally(() => patchModel.InProcess.Value = false); break; case PatchOnOptions.Collection: ApplicationModel.Database.Value.AsyncDatabaseCommands.UpdateByIndex(PatchModel.CollectionsIndex, new IndexQuery { Query = "Tag:" + patchModel.SelectedItem }, request) .ContinueOnSuccessInTheUIThread(() => patchModel.UpdateCollectionSource()) .ContinueOnUIThread(t => { if (t.IsFaulted) { patchModel.HandlePatchError(t.Exception); } }) .Finally(() => patchModel.InProcess.Value = false); break; case PatchOnOptions.Index: ApplicationModel.Database.Value.AsyncDatabaseCommands.UpdateByIndex(patchModel.SelectedItem, new IndexQuery { Query = patchModel.QueryDoc.CurrentSnapshot.Text }, request) .ContinueOnSuccessInTheUIThread(() => patchModel.UpdateCollectionSource()) .ContinueOnUIThread(t => { if (t.IsFaulted) { patchModel.HandlePatchError(t.Exception); } }) .Finally(() => patchModel.InProcess.Value = false); break; } }); }
public RavenJObject Patch(string key, ScriptedPatchRequest patch, bool ignoreMissing) { return(AsyncHelpers.RunSync(() => asyncServerClient.PatchAsync(key, patch, ignoreMissing))); }
public IEnumerable <JsonDocument> Handle(IEnumerable <JsonDocument> docs) { if (strategy.SpecifiedCollections == null || strategy.SpecifiedCollections.Count == 0) { return(docs); } return(docs.Select(doc => { var collection = doc.Metadata.Value <string>(Constants.RavenEntityName); string script; if (string.IsNullOrEmpty(collection) || strategy.SpecifiedCollections.TryGetValue(collection, out script) == false) { if (Log.IsDebugEnabled) { Log.Debug(string.Format("Will not replicate document '{0}' to '{1}' because the replication of specified collection is turned on while the document does not belong to any of them", doc.Key, destinationId)); } return null; } if (script == null) { return doc; } var scriptedPatchRequest = new ScriptedPatchRequest { Script = script }; var patcher = new ReplicationScriptedJsonPatcher(database, scriptedPatchRequest); using (var scope = new DefaultScriptedJsonPatcherOperationScope(database)) { try { var transformedDoc = patcher.Apply(scope, doc.ToJson(), scriptedPatchRequest, doc.SerializedSizeOnDisk); if (scope.ActualPatchResult == JsValue.Null) // null means that document should be skip { if (Log.IsDebugEnabled) { Log.Debug(string.Format("Will not replicate document '{0}' to '{1}' because a collection specific script filtered it out", doc.Key, destinationId)); } return null; } doc.Metadata = (RavenJObject)transformedDoc[Constants.Metadata]; transformedDoc.Remove(Constants.Metadata); doc.DataAsJson = transformedDoc; return doc; } catch (ParseException e) { Log.WarnException(string.Format("Could not parse replication transformation script of '{0}' collection on document {1}", collection, doc.Key), e); throw; } catch (Exception e) { Log.WarnException(string.Format("Could not apply replication transformation script of '{0}' collection on document {1}", collection, doc.Key), e); throw; } } }) .Where(x => x != null)); }
public Tuple <PatchResultData, List <string> > ApplyPatch(string docId, Etag etag, ScriptedPatchRequest patchExisting, ScriptedPatchRequest patchDefault, RavenJObject defaultMetadata, TransactionInformation transactionInformation, bool debugMode = false) { ScriptedJsonPatcher scriptedJsonPatcher = null; DefaultScriptedJsonPatcherOperationScope scope = null; try { var applyPatchInternal = ApplyPatchInternal(docId, etag, transactionInformation, jsonDoc => { scope = new DefaultScriptedJsonPatcherOperationScope(Database); scriptedJsonPatcher = new ScriptedJsonPatcher(Database); return(scriptedJsonPatcher.Apply(scope, jsonDoc.ToJson(), patchExisting, jsonDoc.SerializedSizeOnDisk, jsonDoc.Key)); }, () => { if (patchDefault == null) { return(null); } scriptedJsonPatcher = new ScriptedJsonPatcher(Database); var jsonDoc = new RavenJObject(); jsonDoc[Constants.Metadata] = defaultMetadata.CloneToken() ?? new RavenJObject(); return(scriptedJsonPatcher.Apply(scope, new RavenJObject(), patchDefault, 0, docId)); }, () => { if (scope == null) { return(null); } return(scope .GetPutOperations() .ToList()); }, debugMode); return(Tuple.Create(applyPatchInternal, scriptedJsonPatcher == null ? new List <string>() : scriptedJsonPatcher.Debug)); } finally { if (scope != null) { scope.Dispose(); } } }
/// <summary> /// Sends a patch request for a specific document, ignoring the document's Etag /// </summary> /// <param name="key">Id of the document to patch</param> /// <param name="patch">The patch request to use (using JavaScript)</param> public void Patch(string key, ScriptedPatchRequest patch) { Patch(key, patch, null); }
public Operation UpdateByIndex(string indexName, IndexQuery queryToUpdate, ScriptedPatchRequest patch, BulkOperationOptions options = null) { return(asyncServerClient.UpdateByIndexAsync(indexName, queryToUpdate, patch, options).ResultUnwrap()); }
public Task <Operation> UpdateByIndex(string indexName, IndexQuery queryToUpdate, ScriptedPatchRequest patch, bool allowStale) { var updateByIndex = databaseCommands.UpdateByIndex(indexName, queryToUpdate, patch, allowStale); return(new CompletedTask <Operation>(updateByIndex)); }
/// <summary> /// Perform a set based update using the specified index, not allowing the operation /// if the index is stale /// </summary> /// <param name="indexName">Name of the index.</param> /// <param name="queryToUpdate">The query to update.</param> /// <param name="patch">The patch request to use (using JavaScript)</param> public void UpdateByIndex(string indexName, IndexQuery queryToUpdate, ScriptedPatchRequest patch) { UpdateByIndex(indexName, queryToUpdate, patch, false); }
public ScriptedPatchRequestAndCustomFunctionsToken(ScriptedPatchRequest request, RavenJObject customFunctions) { this.request = request; this.customFunctions = customFunctions; }
public Engine CheckoutScript(Func <ScriptedPatchRequest, Engine> createEngine, ScriptedPatchRequest request, RavenJObject customFunctions) { CachedResult value; var patchRequestAndCustomFunctionsTuple = new ScriptedPatchRequestAndCustomFunctionsToken(request, customFunctions); if (cacheDic.TryGetValue(patchRequestAndCustomFunctionsTuple, out value)) { Interlocked.Increment(ref value.Usage); Engine context; if (value.Queue.TryDequeue(out context)) { return(context); } } var result = createEngine(request); RavenJToken functions; if (customFunctions != null && customFunctions.TryGetValue("Functions", out functions)) { result.Execute(string.Format(@"var customFunctions = function() {{ var exports = {{ }}; {0}; return exports; }}(); for(var customFunction in customFunctions) {{ this[customFunction] = customFunctions[customFunction]; }};", functions), new ParserOptions { Source = "customFunctions.js" }); } var cachedResult = new CachedResult { Usage = 1, Queue = new ConcurrentQueue <Engine>(), Timestamp = SystemTime.UtcNow }; cacheDic.AddOrUpdate(patchRequestAndCustomFunctionsTuple, cachedResult, (_, existing) => { Interlocked.Increment(ref existing.Usage); return(existing); }); if (cacheDic.Count > CacheMaxSize) { foreach (var source in cacheDic .Where(x => x.Value != null) .OrderByDescending(x => x.Value.Usage) .ThenBy(x => x.Value.Timestamp) .Skip(CacheMaxSize - CacheMaxSize / 10)) { if (Equals(source.Key, request)) { continue; // we don't want to remove the one we just added } CachedResult ignored; cacheDic.TryRemove(source.Key, out ignored); } foreach (var source in cacheDic.Where(x => x.Value == null)) { CachedResult ignored; cacheDic.TryRemove(source.Key, out ignored); } } return(result); }
private RavenJObject ApplySingleScript(RavenJObject doc, ScriptedPatchRequest patch, int size, string docId, ScriptedJsonPatcherOperationScope scope) { Engine jintEngine; var customFunctions = scope.CustomFunctions != null ? scope.CustomFunctions.DataAsJson : null; try { jintEngine = ScriptsCache.CheckoutScript(CreateEngine, patch, customFunctions); } catch (NotSupportedException e) { throw new ParseException("Could not parse script", e); } catch (JavaScriptException e) { throw new ParseException("Could not parse script", e); } catch (Exception e) { throw new ParseException("Could not parse: " + Environment.NewLine + patch.Script, e); } try { PrepareEngine(patch, docId, size, scope, jintEngine); var jsObject = scope.ToJsObject(jintEngine, doc); jintEngine.Invoke("ExecutePatchScript", jsObject); CleanupEngine(patch, jintEngine, scope); OutputLog(jintEngine); if (scope.DebugMode) { Debug.Add(string.Format("Statements executed: {0}", jintEngine.StatementsCount)); } ScriptsCache.CheckinScript(patch, jintEngine, customFunctions); return(scope.ConvertReturnValue(jsObject)); } catch (ConcurrencyException) { throw; } catch (Exception errorEx) { jintEngine.ResetStatementsCount(); OutputLog(jintEngine); var errorMsg = "Unable to execute JavaScript: " + Environment.NewLine + patch.Script; var error = errorEx as JavaScriptException; if (error != null) { errorMsg += Environment.NewLine + "Error: " + Environment.NewLine + string.Join(Environment.NewLine, error.Error); } if (Debug.Count != 0) { errorMsg += Environment.NewLine + "Debug information: " + Environment.NewLine + string.Join(Environment.NewLine, Debug); } if (error != null) { errorMsg += Environment.NewLine + "Stacktrace:" + Environment.NewLine + error.CallStack; } var targetEx = errorEx as TargetInvocationException; if (targetEx != null && targetEx.InnerException != null) { throw new InvalidOperationException(errorMsg, targetEx.InnerException); } throw new InvalidOperationException(errorMsg, errorEx); } }
/// <summary> /// Sends a patch request for a specific document, ignoring the document's Etag /// </summary> /// <param name="key">Id of the document to patch</param> /// <param name="patch">The patch request to use (using JavaScript)</param> /// <param name="etag">Require specific Etag [null to ignore]</param> public RavenJObject Patch(string key, ScriptedPatchRequest patch, Etag etag) { return(asyncServerClient.PatchAsync(key, patch, etag).ResultUnwrap()); }
public Task <RavenJObject> PatchAsync(string key, ScriptedPatchRequest patch, bool ignoreMissing) { return(new CompletedTask <RavenJObject>(databaseCommands.Patch(key, patch, ignoreMissing))); }
/// <summary> /// Sends a patch request for a specific document which may or may not currently exist /// </summary> /// <param name="key">Id of the document to patch</param> /// <param name="patchExisting">The patch request to use (using JavaScript) to an existing document</param> /// <param name="patchDefault">The patch request to use (using JavaScript) to a default document when the document is missing</param> /// <param name="defaultMetadata">The metadata for the default document when the document is missing</param> public RavenJObject Patch(string key, ScriptedPatchRequest patchExisting, ScriptedPatchRequest patchDefault, RavenJObject defaultMetadata) { return(asyncServerClient.PatchAsync(key, patchExisting, patchDefault, defaultMetadata).ResultUnwrap()); }
public Task <RavenJObject> PatchAsync(string key, ScriptedPatchRequest patch, Etag etag) { return(new CompletedTask <RavenJObject>(databaseCommands.Patch(key, patch, etag))); }
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); 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()); }, debugMode); return(Tuple.Create(applyPatchInternal, scriptedJsonPatcher == null ? new List <string>() : scriptedJsonPatcher.Debug)); } finally { if (scope != null) { scope.Dispose(); } } }
public Task <RavenJObject> PatchAsync(string key, ScriptedPatchRequest patchExisting, ScriptedPatchRequest patchDefault, RavenJObject defaultMetadata) { return(new CompletedTask <RavenJObject>(databaseCommands.Patch(key, patchExisting, patchDefault, defaultMetadata))); }
public override void Execute(object parameter) { patchModel.ClearQueryError(); var values = patchModel.GetValues(); if (values == null) { return; } var request = new ScriptedPatchRequest { Script = patchModel.Script.CurrentSnapshot.Text, Values = values }; var commands = new ICommandData[1]; switch (patchModel.PatchOn) { case PatchOnOptions.Document: ApplicationModel.Database.Value.AsyncDatabaseCommands.GetAsync(patchModel.SelectedItem). ContinueOnSuccessInTheUIThread(doc => patchModel.OriginalDoc.SetText(doc.ToJson().ToString())); commands[0] = new ScriptedPatchCommandData { Patch = request, Key = patchModel.SelectedItem, DebugMode = true }; break; case PatchOnOptions.Collection: case PatchOnOptions.Index: var selectedItem = patchModel.QueryResults.ItemSelection.GetSelectedItems().FirstOrDefault(); if (selectedItem == null || !selectedItem.IsRealized) { return; } patchModel.OriginalDoc.SetText(selectedItem.Item.Document.ToJson().ToString()); var docId = selectedItem.Item.Document.Key; commands[0] = new ScriptedPatchCommandData { Patch = request, Key = docId, DebugMode = true }; break; } patchModel.InProcess.Value = true; ApplicationModel.Database.Value.AsyncDatabaseCommands.BatchAsync(commands) .ContinueOnSuccessInTheUIThread(batch => patchModel.NewDoc.SetText(batch[0].AdditionalData.ToString())) .ContinueOnUIThread(t => { if (t.IsFaulted) { patchModel.HandlePatchError(t.Exception); } }) .Finally(() => patchModel.InProcess.Value = false); patchModel.ShowBeforeAndAfterPrompt = false; patchModel.ShowAfterPrompt = false; }
public Task UpdateByIndex(string indexName, IndexQuery queryToUpdate, ScriptedPatchRequest patch, bool allowStale) { databaseCommands.UpdateByIndex(indexName, queryToUpdate, patch, allowStale); return(new CompletedTask()); }
public Operation UpdateByIndex(string indexName, IndexQuery queryToUpdate, ScriptedPatchRequest patch, BulkOperationOptions options = null) { return(AsyncHelpers.RunSync(() => asyncServerClient.UpdateByIndexAsync(indexName, queryToUpdate, patch, options))); }
public Engine CheckoutScript(Func <ScriptedPatchRequest, Engine> createEngine, ScriptedPatchRequest request) { CachedResult value; if (cacheDic.TryGetValue(request, out value)) { Interlocked.Increment(ref value.Usage); Engine context; if (value.Queue.TryDequeue(out context)) { return(context); } } var result = createEngine(request); var cachedResult = new CachedResult { Usage = 1, Queue = new ConcurrentQueue <Engine>(), Timestamp = SystemTime.UtcNow }; cacheDic.AddOrUpdate(request, cachedResult, (_, existing) => { Interlocked.Increment(ref existing.Usage); return(existing); }); if (cacheDic.Count > CacheMaxSize) { foreach (var source in cacheDic .Where(x => x.Value != null) .OrderByDescending(x => x.Value.Usage) .ThenBy(x => x.Value.Timestamp) .Skip(CacheMaxSize - CacheMaxSize / 10)) { if (Equals(source.Key, request)) { continue; // we don't want to remove the one we just added } CachedResult ignored; cacheDic.TryRemove(source.Key, out ignored); } foreach (var source in cacheDic.Where(x => x.Value == null)) { CachedResult ignored; cacheDic.TryRemove(source.Key, out ignored); } } return(result); }
public RavenJObject Patch(string key, ScriptedPatchRequest patch, Etag etag) { return(AsyncHelpers.RunSync(() => asyncServerClient.PatchAsync(key, patch, etag))); }
/// <summary> /// Perform a set based update using the specified index /// </summary> /// <param name="indexName">Name of the index.</param> /// <param name="queryToUpdate">The query to update.</param> /// <param name="patch">The patch request to use (using JavaScript)</param> /// <param name="allowStale">if set to <c>true</c> allow the operation while the index is stale.</param> public Operation UpdateByIndex(string indexName, IndexQuery queryToUpdate, ScriptedPatchRequest patch, bool allowStale = false) { return(asyncServerClient.UpdateByIndexAsync(indexName, queryToUpdate, patch, allowStale).ResultUnwrap()); }
private RavenJObject ApplySingleScript(RavenJObject doc, ScriptedPatchRequest patch, int size, string docId) { JintEngine jintEngine; try { jintEngine = scriptsCache.CheckoutScript(CreateEngine, patch); } catch (NotSupportedException e) { throw new ParseException("Could not parse script", e); } catch (JintException e) { throw new ParseException("Could not parse script", e); } catch (Exception e) { throw new ParseException("Could not parse: " + Environment.NewLine + patch.Script, e); } loadDocumentStatic = loadDocument; try { CustomizeEngine(jintEngine); jintEngine.SetFunction("PutDocument", ((Action <string, JsObject, JsObject>)(PutDocument))); jintEngine.SetParameter("__document_id", docId); foreach (var kvp in patch.Values) { var token = kvp.Value as RavenJToken; if (token != null) { jintEngine.SetParameter(kvp.Key, ToJsInstance(jintEngine.Global, token)); } else { var rjt = RavenJToken.FromObject(kvp.Value); var jsInstance = ToJsInstance(jintEngine.Global, rjt); jintEngine.SetParameter(kvp.Key, jsInstance); } } var jsObject = ToJsObject(jintEngine.Global, doc); jintEngine.ResetSteps(); if (size != 0) { jintEngine.SetMaxSteps(maxSteps + (size * additionalStepsPerSize)); } jintEngine.CallFunction("ExecutePatchScript", jsObject); foreach (var kvp in patch.Values) { jintEngine.RemoveParameter(kvp.Key); } jintEngine.RemoveParameter("__document_id"); RemoveEngineCustomizations(jintEngine); OutputLog(jintEngine); scriptsCache.CheckinScript(patch, jintEngine); return(ConvertReturnValue(jsObject)); } catch (ConcurrencyException) { throw; } catch (Exception errorEx) { OutputLog(jintEngine); var errorMsg = "Unable to execute JavaScript: " + Environment.NewLine + patch.Script; var error = errorEx as JsException; if (error != null) { errorMsg += Environment.NewLine + "Error: " + Environment.NewLine + string.Join(Environment.NewLine, error.Value); } if (Debug.Count != 0) { errorMsg += Environment.NewLine + "Debug information: " + Environment.NewLine + string.Join(Environment.NewLine, Debug); } throw new InvalidOperationException(errorMsg, errorEx); } finally { loadDocumentStatic = null; } }
private RavenJObject ApplySingleScript(RavenJObject doc, ScriptedPatchRequest patch) { JintEngine jintEngine; try { jintEngine = scriptsCache.CheckoutScript(patch); } catch (NotSupportedException) { throw; } catch (JintException) { throw; } catch (Exception e) { throw new InvalidOperationException("Could not parse: " + Environment.NewLine + patch.Script, e); } loadDocumentStatic = loadDocument; try { foreach (var kvp in patch.Values) { if (kvp.Value is RavenJToken) { jintEngine.SetParameter(kvp.Key, ToJsInstance(jintEngine.Global, (RavenJToken)kvp.Value)); } else { var rjt = RavenJToken.FromObject(kvp.Value); var jsInstance = ToJsInstance(jintEngine.Global, rjt); jintEngine.SetParameter(kvp.Key, jsInstance); } } var jsObject = ToJsObject(jintEngine.Global, doc); jintEngine.ResetSteps(); jintEngine.CallFunction("ExecutePatchScript", jsObject); foreach (var kvp in patch.Values) { jintEngine.RemoveParameter(kvp.Key); } OutputLog(jintEngine); scriptsCache.CheckinScript(patch, jintEngine); return(ToRavenJObject(jsObject)); } catch (Exception errorEx) { OutputLog(jintEngine); var errorMsg = "Unable to execute JavaScript: " + Environment.NewLine + patch.Script; var error = errorEx as JsException; if (error != null) { errorMsg += Environment.NewLine + "Error: " + Environment.NewLine + string.Join(Environment.NewLine, error.Value); } if (Debug.Count != 0) { errorMsg += Environment.NewLine + "Debug information: " + Environment.NewLine + string.Join(Environment.NewLine, Debug); } throw new InvalidOperationException(errorMsg, errorEx); } finally { loadDocumentStatic = null; } }