private void Execute() { this.operation.Status = UpdateCascadeOperationStatus.Executing; operation.StartedDate = DateTime.UtcNow; operationRepository = new Repository <UpdateCascadeOperation>(db); var completedReferencingEntityNames = this.operation.CollectionOperations .Where(x => x.IsCompleted) .Select(x => x.ReferencingEntityName) .ToHashSet(); var notCompletedReferencingCollections = this.setting.ReferencingCollections.Values .Where(rc => !completedReferencingEntityNames.Contains(rc.ReferencingEntityName)); try { log.Trace("Update cascade operation {0} started", operation.Id); foreach (var referencingCollectionSetting in notCompletedReferencingCollections) { var collectionOperation = this.operation.CollectionOperations.FirstOrDefault(co => co.ReferencingEntityName == referencingCollectionSetting.ReferencingEntityName); if (collectionOperation == null) { collectionOperation = new ReferencingCollectionOperation { ReferencingEntityName = referencingCollectionSetting.ReferencingEntityName }; this.operation.CollectionOperations.Add(collectionOperation); } UpdateCascadeReferencingCollection(referencingCollectionSetting, collectionOperation); } operation.Status = operation.CollectionOperations.Any(co => co.Status == UpdateCascadeOperationStatus.Failed) ? UpdateCascadeOperationStatus.Failed : UpdateCascadeOperationStatus.CompletedSuccessfully; log.Trace("Update cascade operation {0} completed with status {1}", operation.Status); } catch (OperationCanceledException) { operation.Status = UpdateCascadeOperationStatus.Canceled; log.Trace("Update cascade operation {0} has been canceled", this.operation.Id); throw; } catch (Exception) { operation.Status = UpdateCascadeOperationStatus.Failed; throw; } finally { operation.CompletedDate = DateTime.UtcNow; if (!(services.IsShutDownInProgress && operation.Status == UpdateCascadeOperationStatus.Canceled)) { SaveOperationSilentlyIgnoringError(); } operationRepository = null; } }
private void Execute() { this.operation.Status = UpdateCascadeOperationStatus.Executing; operation.StartedDate = DateTime.UtcNow; operationRepository = new Repository<UpdateCascadeOperation>(db); var completedReferencingEntityNames = this.operation.CollectionOperations .Where( x => x.IsCompleted) .Select( x => x.ReferencingEntityName) .ToHashSet(); var notCompletedReferencingCollections = this.setting.ReferencingCollections.Values .Where( rc => ! completedReferencingEntityNames.Contains( rc.ReferencingEntityName)); try { log.Trace("Update cascade operation {0} started", operation.Id); foreach (var referencingCollectionSetting in notCompletedReferencingCollections) { var collectionOperation = this.operation.CollectionOperations.FirstOrDefault(co => co.ReferencingEntityName == referencingCollectionSetting.ReferencingEntityName); if (collectionOperation == null) { collectionOperation = new ReferencingCollectionOperation { ReferencingEntityName = referencingCollectionSetting.ReferencingEntityName }; this.operation.CollectionOperations.Add(collectionOperation); } UpdateCascadeReferencingCollection(referencingCollectionSetting, collectionOperation); } operation.Status = operation.CollectionOperations.Any(co => co.Status == UpdateCascadeOperationStatus.Failed) ? UpdateCascadeOperationStatus.Failed : UpdateCascadeOperationStatus.CompletedSuccessfully; log.Trace("Update cascade operation {0} completed with status {1}", operation.Status); } catch (OperationCanceledException) { operation.Status = UpdateCascadeOperationStatus.Canceled; log.Trace("Update cascade operation {0} has been canceled", this.operation.Id); throw; } catch (Exception) { operation.Status = UpdateCascadeOperationStatus.Failed; throw; } finally { operation.CompletedDate = DateTime.UtcNow; if (! (services.IsShutDownInProgress && operation.Status == UpdateCascadeOperationStatus.Canceled)) { SaveOperationSilentlyIgnoringError(); } operationRepository = null; } }
private bool UpdateDocumentWithProgressReport(JsonDocument referencingDocument, ReferencingCollectionOperation collectionOperation) { if (UpdateDocument(referencingDocument)) { collectionOperation.UpdatedDocumentCount++; if (collectionOperation.UpdatedDocumentCount % 200 == 0) { log.Trace("Updating progress for operation {0}. {1} {2} documents have been updated so far", operation.Id, collectionOperation.UpdatedDocumentCount, collectionOperation.ReferencingEntityName); SaveOperationSilentlyIgnoringError(); // updating progress is not so important } return true; } else { return false; } }
private void UpdateCascadeReferencingCollection(ReferencingCollectionSetting rc, ReferencingCollectionOperation co) { co.StartedDate = DateTime.UtcNow; co.Status = UpdateCascadeOperationStatus.Executing; co.UpdatedDocumentCount = 0; SaveOperationSilentlyIgnoringError(); // we can continue anyway log.Trace("Update cascade {0} referencing document collection for update cascade operation {1} started", rc.ReferencingEntityName, operation.Id); try { int updatedByIndex = 0; Guid lastEtag; do { lastEtag = db.GetLastEtag(); var query = new IndexQuery { CutoffEtag = lastEtag, Query = string.Format("{0}:{1} AND {2}:{3}NULL TO {4}{5}", rc.ReferencedIdPropertyNameInIndex, RavenQuery.Escape(referencedDoc.Key), rc.ReferencedEtagPropertyNameInIndex, "{", RavenQuery.Escape(Convert.ToString(referencedDoc.Etag, CultureInfo.InvariantCulture)), "}") }; updatedByIndex = db.UpdateByIndex(rc.IndexName, query, doc => UpdateDocumentWithProgressReport(doc, co), TimeSpan.FromHours(8), cancellationToken, null); } while (updatedByIndex > 0); db.UpdateDocumentsAfter(lastEtag, UpdateDocument, cancellationToken, null); co.Status = UpdateCascadeOperationStatus.CompletedSuccessfully; log.Trace("Update cascade {0} documents for operation {1} completed successfully. {2} documents have been updated in {3}", rc.ReferencingEntityName, operation.Id, co.UpdatedDocumentCount, co.ElapsedTime); } catch (OperationCanceledException) // save the operation and rethrow { co.Status = UpdateCascadeOperationStatus.Canceled; throw; } catch (Exception ex) // Log the error, save the operation, and move to the next. { co.ErrorMessage = ex.Message; co.Status = UpdateCascadeOperationStatus.Failed; log.ErrorException(string.Format("Update cascade {0} documents for operation {1} failed miserably. Moving on the next one ...", rc.ReferencingEntityName, operation.Id), ex); } finally { co.CompletedDate = DateTime.UtcNow; if (!(services.IsShutDownInProgress && co.Status == UpdateCascadeOperationStatus.Canceled)) SaveOperationSilentlyIgnoringError(); // we want to preserve OperationCanceledException. } }
private bool UpdateDocumentWithProgressReport(JsonDocument referencingDocument, ReferencingCollectionOperation collectionOperation) { if (UpdateDocument(referencingDocument)) { collectionOperation.UpdatedDocumentCount++; if (collectionOperation.UpdatedDocumentCount % 200 == 0) { log.Trace("Updating progress for operation {0}. {1} {2} documents have been updated so far", operation.Id, collectionOperation.UpdatedDocumentCount, collectionOperation.ReferencingEntityName); SaveOperationSilentlyIgnoringError(); // updating progress is not so important } return(true); } else { return(false); } }
private void UpdateCascadeReferencingCollection(ReferencingCollectionSetting rc, ReferencingCollectionOperation co) { co.StartedDate = DateTime.UtcNow; co.Status = UpdateCascadeOperationStatus.Executing; co.UpdatedDocumentCount = 0; SaveOperationSilentlyIgnoringError(); // we can continue anyway log.Trace("Update cascade {0} referencing document collection for update cascade operation {1} started", rc.ReferencingEntityName, operation.Id); try { int updatedByIndex = 0; Guid lastEtag; do { lastEtag = db.GetLastEtag(); var query = new IndexQuery { CutoffEtag = lastEtag, Query = string.Format("{0}:{1} AND {2}:{3}NULL TO {4}{5}", rc.ReferencedIdPropertyNameInIndex, RavenQuery.Escape(referencedDoc.Key), rc.ReferencedEtagPropertyNameInIndex, "{", RavenQuery.Escape(Convert.ToString(referencedDoc.Etag, CultureInfo.InvariantCulture)), "}") }; updatedByIndex = db.UpdateByIndex(rc.IndexName, query, doc => UpdateDocumentWithProgressReport(doc, co), TimeSpan.FromHours(8), cancellationToken, null); } while (updatedByIndex > 0); db.UpdateDocumentsAfter(lastEtag, UpdateDocument, cancellationToken, null); co.Status = UpdateCascadeOperationStatus.CompletedSuccessfully; log.Trace("Update cascade {0} documents for operation {1} completed successfully. {2} documents have been updated in {3}", rc.ReferencingEntityName, operation.Id, co.UpdatedDocumentCount, co.ElapsedTime); } catch (OperationCanceledException) // save the operation and rethrow { co.Status = UpdateCascadeOperationStatus.Canceled; throw; } catch (Exception ex) // Log the error, save the operation, and move to the next. { co.ErrorMessage = ex.Message; co.Status = UpdateCascadeOperationStatus.Failed; log.ErrorException(string.Format("Update cascade {0} documents for operation {1} failed miserably. Moving on the next one ...", rc.ReferencingEntityName, operation.Id), ex); } finally { co.CompletedDate = DateTime.UtcNow; if (!(services.IsShutDownInProgress && co.Status == UpdateCascadeOperationStatus.Canceled)) { SaveOperationSilentlyIgnoringError(); // we want to preserve OperationCanceledException. } } }