private void RunMaintenanceTaskForRepos(UserAndSession registeredUser) { EventMetadata metadata = new EventMetadata(); metadata.Add(nameof(this.task), MaintenanceTasks.GetVerbTaskName(this.task)); metadata.Add(nameof(registeredUser.UserId), registeredUser.UserId); metadata.Add(nameof(registeredUser.SessionId), registeredUser.SessionId); int reposSkipped = 0; int reposSuccessfullyRemoved = 0; int repoRemovalFailures = 0; int reposMaintained = 0; int reposInRegistryForUser = 0; bool maintenancePaused = false; string rootPath; string errorMessage; string traceMessage = null; IEnumerable <ScalarRepoRegistration> reposForUser = this.repoRegistry.GetRegisteredRepos().Where( x => x.UserId.Equals(registeredUser.UserId, StringComparison.InvariantCultureIgnoreCase)); foreach (ScalarRepoRegistration repoRegistration in reposForUser) { ++reposInRegistryForUser; if (maintenancePaused || this.IsMaintenancePaused(out traceMessage)) { metadata[nameof(traceMessage)] = traceMessage; maintenancePaused = true; ++reposSkipped; continue; } rootPath = Path.GetPathRoot(repoRegistration.NormalizedRepoRoot); metadata[nameof(repoRegistration.NormalizedRepoRoot)] = repoRegistration.NormalizedRepoRoot; metadata[nameof(rootPath)] = rootPath; metadata.Remove(nameof(errorMessage)); if (!string.IsNullOrWhiteSpace(rootPath) && !this.fileSystem.DirectoryExists(rootPath)) { ++reposSkipped; // If the volume does not exist we'll assume the drive was removed or is encrypted, // and we'll leave the repo in the registry (but we won't run maintenance on it). this.tracer.RelatedEvent( EventLevel.Informational, $"{nameof(this.RunMaintenanceTaskForRepos)}_SkippedRepoWithMissingVolume", metadata); continue; } if (!this.fileSystem.DirectoryExists(repoRegistration.NormalizedRepoRoot)) { // The repo is no longer on disk (but its volume is present) // Unregister the repo if (this.repoRegistry.TryUnregisterRepo(repoRegistration.NormalizedRepoRoot, out errorMessage)) { ++reposSuccessfullyRemoved; this.tracer.RelatedEvent( EventLevel.Informational, $"{nameof(this.RunMaintenanceTaskForRepos)}_RemovedMissingRepo", metadata); } else { ++repoRemovalFailures; metadata[nameof(errorMessage)] = errorMessage; this.tracer.RelatedEvent( EventLevel.Warning, $"{nameof(this.RunMaintenanceTaskForRepos)}_FailedToRemoveRepo", metadata); } continue; } ++reposMaintained; this.tracer.RelatedEvent( EventLevel.Informational, $"{nameof(this.RunMaintenanceTaskForRepos)}_CallingMaintenance", metadata); this.scalarVerb.CallMaintenance(this.task, repoRegistration.NormalizedRepoRoot, registeredUser.SessionId); } metadata.Add(nameof(reposInRegistryForUser), reposInRegistryForUser); metadata.Add(nameof(reposSkipped), reposSkipped); metadata.Add(nameof(reposSuccessfullyRemoved), reposSuccessfullyRemoved); metadata.Add(nameof(repoRemovalFailures), repoRemovalFailures); metadata.Add(nameof(reposMaintained), reposMaintained); metadata.Add(nameof(maintenancePaused), maintenancePaused); this.tracer.RelatedEvent( EventLevel.Informational, $"{nameof(this.RunMaintenanceTaskForRepos)}_MaintenanceSummary", metadata); }