/src/Raven.Server/Documents/Patch/PatchConflict.cs

https://github.com/fitzchak/ravendb · C# · 69 lines · 62 code · 4 blank · 3 comment · 6 complexity · 6b9600a651f5a5844949a7c366e8ef8d MD5 · raw file

  1. using System;
  2. using System.Collections.Generic;
  3. using Jint.Native;
  4. using Raven.Client;
  5. using Raven.Server.ServerWide.Context;
  6. using Sparrow.Json;
  7. using Sparrow.Logging;
  8. namespace Raven.Server.Documents.Patch
  9. {
  10. public class PatchConflict
  11. {
  12. private readonly DocumentDatabase _database;
  13. private readonly List<object> _docs = new List<object>();
  14. private readonly DocumentConflict _fstDocumentConflict;
  15. private readonly bool _hasTombstone;
  16. private static readonly string TombstoneResolverValue = Guid.NewGuid().ToString();
  17. private readonly Logger _logger;
  18. public PatchConflict(DocumentDatabase database, IReadOnlyList<DocumentConflict> docs)
  19. {
  20. _logger = LoggingSource.Instance.GetLogger<PatchConflict>(database.Name);
  21. _database = database;
  22. foreach (var doc in docs)
  23. {
  24. if (doc.Doc != null)
  25. {
  26. _docs.Add(doc);
  27. }
  28. else
  29. {
  30. _hasTombstone = true;
  31. }
  32. }
  33. _fstDocumentConflict = docs[0];
  34. }
  35. public bool TryResolveConflict(DocumentsOperationContext context, PatchRequest patch, out BlittableJsonReaderObject resolved)
  36. {
  37. using (_database.Scripts.GetScriptRunner(patch, false, out var run))
  38. using (var result = run.Run(context, context, "resolve", new object[] { _docs, _hasTombstone, TombstoneResolverValue }))
  39. {
  40. if (result.IsNull)
  41. {
  42. resolved = null;
  43. if (_logger.IsInfoEnabled)
  44. {
  45. _logger.Info(
  46. $"Conflict resolution script for {_fstDocumentConflict.Collection} collection declined to resolve the conflict for {_fstDocumentConflict.LowerId}");
  47. }
  48. return false;
  49. }
  50. if (result.StringValue == TombstoneResolverValue)
  51. {
  52. resolved = null;
  53. return true;
  54. }
  55. var instance = result.GetOrCreate(Constants.Documents.Metadata.Key);
  56. // if user didn't specify it, we'll take it from the first doc
  57. // we cannot change collections here anyway, anything else, the
  58. // user need to merge on their own
  59. instance.Put(Constants.Documents.Metadata.Collection, new JsValue(_fstDocumentConflict.Collection), false);
  60. resolved = result.TranslateToObject(context, usageMode: BlittableJsonDocumentBuilder.UsageMode.ToDisk);
  61. return true;
  62. }
  63. }
  64. }
  65. }