PageRenderTime 48ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/Raven.Database/Server/Controllers/DocumentsBatchController.cs

https://github.com/nwendel/ravendb
C# | 150 lines | 124 code | 23 blank | 3 comment | 5 complexity | 9b5428b261ddbc59f50b6b2b31b6d938 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, BSD-3-Clause, CC-BY-SA-3.0
  1. using System;
  2. using System.Diagnostics;
  3. using System.Linq;
  4. using System.Net;
  5. using System.Net.Http;
  6. using System.Text;
  7. using System.Threading;
  8. using System.Threading.Tasks;
  9. using System.Web.Http;
  10. using Raven.Abstractions;
  11. using Raven.Abstractions.Data;
  12. using Raven.Abstractions.Exceptions;
  13. using Raven.Abstractions.Logging;
  14. using Raven.Database.Actions;
  15. using Raven.Database.Data;
  16. using Raven.Database.Extensions;
  17. using Raven.Database.Impl;
  18. using Raven.Database.Server.WebApi.Attributes;
  19. using Raven.Json.Linq;
  20. namespace Raven.Database.Server.Controllers
  21. {
  22. public class DocumentsBatchController : RavenDbApiController
  23. {
  24. [HttpPost]
  25. [Route("bulk_docs")]
  26. [Route("databases/{databaseName}/bulk_docs")]
  27. public async Task<HttpResponseMessage> BulkPost()
  28. {
  29. using (var cts = new CancellationTokenSource())
  30. using (cts.TimeoutAfter(DatabasesLandlord.SystemConfiguration.DatabaseOperationTimeout))
  31. {
  32. var jsonCommandArray = await ReadJsonArrayAsync();
  33. cts.Token.ThrowIfCancellationRequested();
  34. var transactionInformation = GetRequestTransaction();
  35. var commands =
  36. (from RavenJObject jsonCommand in jsonCommandArray select CommandDataFactory.CreateCommand(jsonCommand, transactionInformation)).ToArray();
  37. Log.Debug(
  38. () =>
  39. {
  40. if (commands.Length > 15) // this is probably an import method, we will input minimal information, to avoid filling up the log
  41. {
  42. return "\tExecuted "
  43. + string.Join(
  44. ", ", commands.GroupBy(x => x.Method).Select(x => string.Format("{0:#,#;;0} {1} operations", x.Count(), x.Key)));
  45. }
  46. var sb = new StringBuilder();
  47. foreach (var commandData in commands)
  48. {
  49. sb.AppendFormat("\t{0} {1}{2}", commandData.Method, commandData.Key, Environment.NewLine);
  50. }
  51. return sb.ToString();
  52. });
  53. var batchResult = Database.Batch(commands, cts.Token);
  54. return GetMessageWithObject(batchResult);
  55. }
  56. }
  57. [HttpDelete]
  58. [Route("bulk_docs/{*id}")]
  59. [Route("databases/{databaseName}/bulk_docs/{*id}")]
  60. public HttpResponseMessage BulkDelete(string id)
  61. {
  62. // we don't use using because execution is async
  63. var cts = new CancellationTokenSource();
  64. var timeout = cts.TimeoutAfter(DatabasesLandlord.SystemConfiguration.DatabaseOperationTimeout);
  65. var indexDefinition = Database.IndexDefinitionStorage.GetIndexDefinition(id);
  66. if (indexDefinition == null)
  67. throw new IndexDoesNotExistsException(string.Format("Index '{0}' does not exist.", id));
  68. if (indexDefinition.IsMapReduce)
  69. throw new InvalidOperationException("Cannot execute DeleteByIndex operation on Map-Reduce indexes.");
  70. var databaseBulkOperations = new DatabaseBulkOperations(Database, GetRequestTransaction(), cts, timeout);
  71. return OnBulkOperation(databaseBulkOperations.DeleteByIndex, id, cts, timeout);
  72. }
  73. [HttpPatch]
  74. [Route("bulk_docs/{*id}")]
  75. [Route("databases/{databaseName}/bulk_docs/{*id}")]
  76. public async Task<HttpResponseMessage> BulkPatch(string id)
  77. {
  78. // we don't use using because execution is async
  79. var cts = new CancellationTokenSource();
  80. var timeout = cts.TimeoutAfter(DatabasesLandlord.SystemConfiguration.DatabaseOperationTimeout);
  81. var databaseBulkOperations = new DatabaseBulkOperations(Database, GetRequestTransaction(), cts, timeout);
  82. var patchRequestJson = await ReadJsonArrayAsync();
  83. var patchRequests = patchRequestJson.Cast<RavenJObject>().Select(PatchRequest.FromJson).ToArray();
  84. return OnBulkOperation((index, query, allowStale) => databaseBulkOperations.UpdateByIndex(index, query, patchRequests, allowStale), id, cts, timeout);
  85. }
  86. [HttpEval]
  87. [Route("bulk_docs/{*id}")]
  88. [Route("databases/{databaseName}/bulk_docs/{*id}")]
  89. public async Task<HttpResponseMessage> BulkEval(string id)
  90. {
  91. // we don't use using because execution is async
  92. var cts = new CancellationTokenSource();
  93. var timeout = cts.TimeoutAfter(DatabasesLandlord.SystemConfiguration.DatabaseOperationTimeout);
  94. var databaseBulkOperations = new DatabaseBulkOperations(Database, GetRequestTransaction(), cts, timeout);
  95. var advPatchRequestJson = await ReadJsonObjectAsync<RavenJObject>();
  96. var advPatch = ScriptedPatchRequest.FromJson(advPatchRequestJson);
  97. return OnBulkOperation((index, query, allowStale) => databaseBulkOperations.UpdateByIndex(index, query, advPatch, allowStale), id, cts, timeout);
  98. }
  99. private HttpResponseMessage OnBulkOperation(Func<string, IndexQuery, bool, RavenJArray> batchOperation, string index, CancellationTokenSource cts, CancellationTimeout timeout)
  100. {
  101. if (string.IsNullOrEmpty(index))
  102. return GetEmptyMessage(HttpStatusCode.BadRequest);
  103. var allowStale = GetAllowStale();
  104. var indexQuery = GetIndexQuery(maxPageSize: int.MaxValue);
  105. var status = new BulkOperationStatus();
  106. long id;
  107. var task = Task.Factory.StartNew(() =>
  108. {
  109. var array = batchOperation(index, indexQuery, allowStale);
  110. status.State = array;
  111. status.Completed = true;
  112. });
  113. Database.Tasks.AddTask(task, status, new TaskActions.PendingTaskDescription
  114. {
  115. StartTime = SystemTime.UtcNow,
  116. TaskType = TaskActions.PendingTaskType.IndexBulkOperation,
  117. Payload = index
  118. }, out id, cts);
  119. return GetMessageWithObject(new { OperationId = id });
  120. }
  121. public class BulkOperationStatus
  122. {
  123. public RavenJArray State { get; set; }
  124. public bool Completed { get; set; }
  125. }
  126. }
  127. }