private OngoingTaskReplication GetExternalReplicationInfo(DatabaseTopology dbTopology, ClusterTopology clusterTopology, ExternalReplication watcher) { NodeId responsibale = null; var tag = dbTopology.WhoseTaskIsIt(watcher, ServerStore.Engine.CurrentState); if (tag != null) { responsibale = new NodeId { NodeTag = tag, NodeUrl = clusterTopology.GetUrlFromTag(tag) }; } (string Url, OngoingTaskConnectionStatus Status)res = (null, OngoingTaskConnectionStatus.None); if (tag == ServerStore.NodeTag) { res = Database.ReplicationLoader.GetExternalReplicationDestination(watcher.TaskId); } else { res.Status = OngoingTaskConnectionStatus.NotOnThisNode; } var taskInfo = new OngoingTaskReplication { TaskId = watcher.TaskId, TaskName = watcher.Name, ResponsibleNode = responsibale, DestinationDatabase = watcher.Database, TaskState = watcher.Disabled ? OngoingTaskState.Disabled : OngoingTaskState.Enabled, DestinationUrl = res.Url, TaskConnectionStatus = res.Status, }; return(taskInfo); }
public Task GetOngoingTaskInfo() { if (ResourceNameValidator.IsValidResourceName(Database.Name, ServerStore.Configuration.Core.DataDirectory.FullPath, out string errorMessage) == false) { throw new BadRequestException(errorMessage); } var key = GetLongQueryString("key"); var typeStr = GetQueryStringValueAndAssertIfSingleAndNotEmpty("type"); using (ServerStore.ContextPool.AllocateOperationContext(out TransactionOperationContext context)) { using (context.OpenReadTransaction()) { var clusterTopology = ServerStore.GetClusterTopology(context); var record = ServerStore.Cluster.ReadDatabase(context, Database.Name); var dbTopology = record?.Topology; if (Enum.TryParse <OngoingTaskType>(typeStr, true, out var type) == false) { throw new ArgumentException($"Unknown task type: {type}", "type"); } string tag; switch (type) { case OngoingTaskType.Replication: var watcher = record?.ExternalReplication.Find(x => x.TaskId == key); if (watcher == null) { HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound; break; } tag = dbTopology?.WhoseTaskIsIt(watcher, ServerStore.IsPassive()); var replicationTaskInfo = new OngoingTaskReplication { TaskId = watcher.TaskId, TaskName = watcher.Name, ResponsibleNode = new NodeId { NodeTag = tag, NodeUrl = clusterTopology.GetUrlFromTag(tag) }, DestinationDatabase = watcher.Database, TaskState = watcher.Disabled ? OngoingTaskState.Disabled : OngoingTaskState.Enabled, DestinationUrl = watcher.Url }; WriteResult(context, replicationTaskInfo); break; case OngoingTaskType.Backup: var backupConfiguration = record?.PeriodicBackups?.Find(x => x.TaskId == key); if (backupConfiguration == null) { HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound; break; } tag = dbTopology?.WhoseTaskIsIt(backupConfiguration, ServerStore.IsPassive()); var backupDestinations = GetBackupDestinations(backupConfiguration); var backupStatus = Database.PeriodicBackupRunner.GetBackupStatus(key); var nextBackup = Database.PeriodicBackupRunner.GetNextBackupDetails(record, backupConfiguration, backupStatus); var backupTaskInfo = new OngoingTaskBackup { TaskId = backupConfiguration.TaskId, BackupType = backupConfiguration.BackupType, TaskName = backupConfiguration.Name, TaskState = backupConfiguration.Disabled ? OngoingTaskState.Disabled : OngoingTaskState.Enabled, ResponsibleNode = new NodeId { NodeTag = tag, NodeUrl = clusterTopology.GetUrlFromTag(tag) }, BackupDestinations = backupDestinations, LastFullBackup = backupStatus.LastFullBackup, LastIncrementalBackup = backupStatus.LastIncrementalBackup, NextBackup = nextBackup }; WriteResult(context, backupTaskInfo); break; case OngoingTaskType.SqlEtl: var sqlEtl = record?.SqlEtls?.Find(x => x.TaskId == key); if (sqlEtl == null) { HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound; break; } WriteResult(context, new OngoingTaskSqlEtl { TaskId = sqlEtl.TaskId, TaskName = sqlEtl.Name, Configuration = sqlEtl }); break; case OngoingTaskType.RavenEtl: var ravenEtl = record?.RavenEtls?.Find(x => x.TaskId == key); if (ravenEtl == null) { HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound; break; } WriteResult(context, new OngoingTaskRavenEtl { TaskId = ravenEtl.TaskId, TaskName = ravenEtl.Name, Configuration = ravenEtl }); break; case OngoingTaskType.Subscription: var nameKey = GetQueryStringValueAndAssertIfSingleAndNotEmpty("taskName"); var itemKey = SubscriptionState.GenerateSubscriptionItemKeyName(record.DatabaseName, nameKey); var doc = ServerStore.Cluster.Read(context, itemKey); if (doc == null) { HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound; break; } var subscriptionState = JsonDeserializationClient.SubscriptionState(doc); tag = dbTopology?.WhoseTaskIsIt(subscriptionState, ServerStore.IsPassive()); var subscriptionStateInfo = new SubscriptionStateWithNodeDetails { Query = subscriptionState.Query, ChangeVectorForNextBatchStartingPoint = subscriptionState.ChangeVectorForNextBatchStartingPoint, SubscriptionId = subscriptionState.SubscriptionId, SubscriptionName = subscriptionState.SubscriptionName, LastTimeServerMadeProgressWithDocuments = subscriptionState.LastTimeServerMadeProgressWithDocuments, Disabled = subscriptionState.Disabled, LastClientConnectionTime = subscriptionState.LastClientConnectionTime, ResponsibleNode = new NodeId { NodeTag = tag, NodeUrl = clusterTopology.GetUrlFromTag(tag) } }; // Todo: here we'll need to talk with the running node? TaskConnectionStatus = subscriptionState.Disabled ? OngoingTaskConnectionStatus.NotActive : OngoingTaskConnectionStatus.Active, WriteResult(context, subscriptionStateInfo.ToJson()); break; default: HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound; break; } } } return(Task.CompletedTask); }