Example #1
0
        private PatchResultData ApplyPatchInternal(string docId, Etag etag,
                                       TransactionInformation transactionInformation,
                                       Func<JsonDocument, RavenJObject> patcher,
                                       Func<RavenJObject> patcherIfMissing,
                                       Func<IList<JsonDocument>> getDocsCreatedInPatch,
                                       bool debugMode)
        {
            if (docId == null) throw new ArgumentNullException("docId");
            docId = docId.Trim();
            var result = new PatchResultData
            {
                PatchResult = PatchResult.Patched
            };

            bool shouldRetry = false;
            int retries = 128;
            Random rand = null;
            do
            {
                var doc = Database.Documents.Get(docId, transactionInformation);
                Log.Debug(() => string.Format("Preparing to apply patch on ({0}). Document found?: {1}.", docId, doc != null));

                if (etag != null && doc != null && doc.Etag != etag)
                {
                    Debug.Assert(doc.Etag != null);
                    Log.Debug(() => string.Format("Got concurrent exception while tried to patch the following document ID: {0}", docId));
                    throw new ConcurrencyException("Could not patch document '" + docId + "' because non current etag was used")
                    {
                        ActualETag = doc.Etag,
                        ExpectedETag = etag,
                    };
                }

                var jsonDoc = (doc != null ? patcher(doc) : patcherIfMissing());
                if (jsonDoc == null)
                {
                    Log.Debug(() => string.Format("Preparing to apply patch on ({0}). DocumentDoesNotExists.", docId));
                    result.PatchResult = PatchResult.DocumentDoesNotExists;
                }
                else
                {
                    if (debugMode)
                    {
                        result.Document = jsonDoc;
                        result.PatchResult = PatchResult.Tested;
                    }
                    else
                    {
                        try
                        {
                            Database.Documents.Put(doc == null ? docId : doc.Key, (doc == null ? null : doc.Etag), jsonDoc, jsonDoc.Value<RavenJObject>(Constants.Metadata), transactionInformation);

                            var docsCreatedInPatch = getDocsCreatedInPatch();
                            if (docsCreatedInPatch != null && docsCreatedInPatch.Count > 0)
                            {
                                foreach (var docFromPatch in docsCreatedInPatch)
                                {
                                    Database.Documents.Put(docFromPatch.Key, docFromPatch.Etag, docFromPatch.DataAsJson,
                                        docFromPatch.Metadata, transactionInformation);
                                }
                            }
                            shouldRetry = false;
                            result.PatchResult = PatchResult.Patched;
                        }
                        catch (ConcurrencyException)
                        {
                            if (TransactionalStorage.IsAlreadyInBatch)
                                throw;
                            if (retries-- > 0)
                            {
                                shouldRetry = true;
                                if (rand == null)
                                    rand = new Random();
                                Thread.Sleep(rand.Next(5, Math.Max(retries * 2, 10)));
                                continue;
                            }

                            throw;
                        }
                    }
                }

                if (shouldRetry == false)
                    WorkContext.ShouldNotifyAboutWork(() => "PATCH " + docId);

            } while (shouldRetry);

            return result;
        }
Example #2
0
		private PatchResultData ApplyPatchInternal(string docId, Etag etag,
												TransactionInformation transactionInformation,
												Func<RavenJObject, int, RavenJObject> patcher, bool debugMode)
		{
			if (docId == null) throw new ArgumentNullException("docId");
			docId = docId.Trim();
			var result = new PatchResultData
			{
				PatchResult = PatchResult.Patched
			};

			bool shouldRetry = false;
			int[] retries = { 128 };
			do
			{
				TransactionalStorage.Batch(actions =>
				{
					var doc = actions.Documents.DocumentByKey(docId, transactionInformation);
					if (doc == null)
					{
						result.PatchResult = PatchResult.DocumentDoesNotExists;
					}
					else if (etag != null && doc.Etag != etag)
					{
						Debug.Assert(doc.Etag != null);
						throw new ConcurrencyException("Could not patch document '" + docId + "' because non current etag was used")
						{
							ActualETag = doc.Etag,
							ExpectedETag = etag,
						};
					}
					else
					{
						var jsonDoc = patcher(doc.ToJson(), doc.SerializedSizeOnDisk);
						if (debugMode)
						{
							result.Document = jsonDoc;
							result.PatchResult = PatchResult.Tested;
						}
						else
						{
							try
							{
								Put(doc.Key, doc.Etag, jsonDoc, jsonDoc.Value<RavenJObject>("@metadata"), transactionInformation);
							}
							catch (ConcurrencyException)
							{
								if (retries[0]-- > 0)
								{
									shouldRetry = true;
									return;
								}
								throw;
							}
							result.PatchResult = PatchResult.Patched;
						}
					}
					if (shouldRetry == false)
						workContext.ShouldNotifyAboutWork(() => "PATCH " + docId);
				});

			} while (shouldRetry);
			return result;
		}
Example #3
0
		private PatchResultData ApplyPatchInternal(string docId, Etag etag,
												   TransactionInformation transactionInformation,
												   Func<RavenJObject, int, RavenJObject> patcher,
												   Func<RavenJObject> patcherIfMissing,
												   Func<IList<JsonDocument>> getDocsCreatedInPatch,
												   bool debugMode)
		{
			if (docId == null) throw new ArgumentNullException("docId");
			docId = docId.Trim();
            var result = new PatchResultData
            {
                PatchResult = PatchResult.Patched
            };

            bool shouldRetry = false;
            int[] retries = { 128 };
			Random rand = null;
            do
            {
                TransactionalStorage.Batch(actions =>
				{
					var doc = actions.Documents.DocumentByKey(docId, transactionInformation);
					if (etag != null && doc != null && doc.Etag != etag)
					{
						Debug.Assert(doc.Etag != null);
						throw new ConcurrencyException("Could not patch document '" + docId + "' because non current etag was used")
						{
							ActualETag = doc.Etag,
							ExpectedETag = etag,
						};
					}

					var jsonDoc = (doc != null ? patcher(doc.ToJson(), doc.SerializedSizeOnDisk) : patcherIfMissing());
					if (jsonDoc == null)
					{
						result.PatchResult = PatchResult.DocumentDoesNotExists;
					}
					else
					{
						if (debugMode)
						{
							result.Document = jsonDoc;
							result.PatchResult = PatchResult.Tested;
						}
						else
						{
							try
							{
								Put(doc == null ? docId : doc.Key, (doc == null ? null : doc.Etag), jsonDoc, jsonDoc.Value<RavenJObject>(Constants.Metadata), transactionInformation);

								var docsCreatedInPatch = getDocsCreatedInPatch();
								if (docsCreatedInPatch != null && docsCreatedInPatch.Count > 0)
								{
									foreach (var docFromPatch in docsCreatedInPatch)
									{
										Put(docFromPatch.Key, docFromPatch.Etag, docFromPatch.DataAsJson,
											docFromPatch.Metadata, transactionInformation);
									}
								}
							}
							catch (ConcurrencyException)
							{
								if (actions.IsNested)
									throw;
								if (retries[0]-- > 0)
								{
									shouldRetry = true;
									if (rand == null)
										rand = new Random();
                                    Thread.Sleep(rand.Next(5, Math.Max(retries[0] * 2, 10)));
									return;
								}
								throw;
							}
							result.PatchResult = PatchResult.Patched;
						}
					}
					if (shouldRetry == false)
						workContext.ShouldNotifyAboutWork(() => "PATCH " + docId);
				});

            } while (shouldRetry);
            return result;
        }