private RavenConnectionStringOptions GetConnectionOptionsSafe(TimeSeriesReplicationDestination destination, out string lastError) { try { var connectionStringOptions = new RavenConnectionStringOptions { Url = destination.ServerUrl, ApiKey = destination.ApiKey, }; if (string.IsNullOrEmpty(destination.Username) == false) { connectionStringOptions.Credentials = string.IsNullOrEmpty(destination.Domain) ? new NetworkCredential(destination.Username, destination.Password) : new NetworkCredential(destination.Username, destination.Password, destination.Domain); } lastError = string.Empty; return(connectionStringOptions); } catch (Exception e) { lastError = e.Message; Log.ErrorException(string.Format("Ignoring bad replication config!{0}Could not figure out connection options for [Url: {1}]", Environment.NewLine, destination.ServerUrl), e); return(null); } }
private ReplicationResult TryReplicate(TimeSeriesReplicationDestination destination, out long lastEtagSent, out string lastError) { long etag; lastEtagSent = 0; var connectionStringOptions = GetConnectionOptionsSafe(destination, out lastError); if (connectionStringOptions == null || !GetLastReplicatedEtagFrom(connectionStringOptions, destination.TimeSeriesUrl, out etag, out lastError)) { return(ReplicationResult.Failure); } var replicationData = GetTimeSeriesDataSinceEtag(etag, out lastEtagSent); storage.MetricsTimeSeries.GetReplicationBatchSizeMetric(destination.TimeSeriesUrl).Mark(replicationData.Logs.Count); storage.MetricsTimeSeries.GetReplicationBatchSizeHistogram(destination.TimeSeriesUrl).Update(replicationData.Logs.Count); if (replicationData.Logs.Count > 0) { return(PerformReplicationToServer(connectionStringOptions, destination.TimeSeriesUrl, replicationData, out lastError) ? ReplicationResult.Success : ReplicationResult.Failure); } return(ReplicationResult.NotReplicated); }
private bool ReplicateTo(TimeSeriesReplicationDestination destination) { var replicationStopwatch = Stopwatch.StartNew(); //todo: here, build url according to :destination.Url + '/ts/' + destination. try { string lastError; long lastEtag; bool result = false; switch (TryReplicate(destination, out lastEtag, out lastError)) { case ReplicationResult.Success: DateTime replicationTime = SystemTime.UtcNow; RecordSuccess(destination.TimeSeriesUrl, lastReplicatedEtag: lastEtag, lastReplicatedLastModified: replicationTime); storage.MetricsTimeSeries.OutgoingReplications.Mark(); result = true; break; case ReplicationResult.NotReplicated: //TODO: Record not replicated RecordSuccess(destination.TimeSeriesUrl, SystemTime.UtcNow); break; default: RecordFailure(destination.TimeSeriesUrl, lastError); storage.MetricsTimeSeries.OutgoingReplications.Mark(); break; } return(result); } catch (Exception ex) { Log.ErrorException("Error occured replicating to: " + destination.TimeSeriesUrl, ex); RecordFailure(destination.TimeSeriesUrl, ex.Message); return(false); } finally { replicationStopwatch.Stop(); var elapsedMicroseconds = (long)(replicationStopwatch.Elapsed.TotalMilliseconds * SystemTime.MicroSecPerTick); storage.MetricsTimeSeries.GetReplicationDurationHistogram(destination.TimeSeriesUrl).Update(elapsedMicroseconds); var holder = activeReplicationTasks.GetOrAdd(destination.TimeSeriesUrl, s => new SemaphoreSlim(0, 1)); holder.Release(); } }
private void ReplicateToDestination(TimeSeriesReplicationDestination destination) { var dest = destination.TimeSeriesUrl; var holder = activeReplicationTasks.GetOrAdd(dest, s => new SemaphoreSlim(1)); if (holder.Wait(0) == false) { return; } var replicationTask = Task.Factory.StartNew( () => { //using (LogContext.WithDatabase(storage.Name)) //TODO: log with time series context //{ try { if (ReplicateTo(destination)) { SignalUpdate(); } } catch (Exception e) { Log.ErrorException("Could not replicate to " + dest, e); } //} }); activeTasks.Enqueue(replicationTask); replicationTask.ContinueWith( _ => { // here we purge all the completed tasks at the head of the queue Task task; while (activeTasks.TryPeek(out task)) { if (!task.IsCompleted && !task.IsCanceled && !task.IsFaulted) { break; } activeTasks.TryDequeue(out task); // remove it from end } }); }