Ejemplo n.º 1
0
        public async Task <bool> TryLockAsync(
            LockToken token,
            int tries = 16, // this is NOT retry - it is try
            int retryTimeoutMilliseconds = 15000,
            int timeoutMilliseconds      = 15000)
        {
            if (tries < 1)
            {
                tries = 1;
            }

            var blob = await GetBlobAsync(token.ResourceId);

            for (int i = 0; i < tries; i++)
            {
                try
                {
                    await blob.AcquireLeaseAsync(
                        TimeSpan.FromMilliseconds(timeoutMilliseconds),
                        token.TokenId.ToString("N"));

                    return(true);
                }
                catch (Exception e)
                {
                    TheTrace.TraceInformation("Lock attempt - already locked: {0}", e);
                    // ignore
                }
                await Task.Delay(TimeSpan.FromMilliseconds(retryTimeoutMilliseconds / tries));
            }

            return(false);
        }
Ejemplo n.º 2
0
        private static Func <Task> SendCommand(int run)
        {
            return(async() =>
            {
                var r = new Random();
                while (_run == run)
                {
                    try
                    {
                        for (int i = 0; i < r.Next(1, 10); i++)
                        {
                            var payload = BitConverter.GetBytes(r.Next(0, 100000)).Concat(BitConverter.GetBytes(r.Next(0, 100000))).ToArray();
                            await _cluster.ApplyCommandAsync(new StateMachineCommandRequest()
                            {
                                Command = payload
                            });
                        }

                        TheTrace.TraceInformation("Sent commands");
                    }
                    catch (Exception e)
                    {
                        TheTrace.TraceError(e.ToString());
                    }

                    await Task.Delay(r.Next(0, 50));
                }
            });
        }
Ejemplo n.º 3
0
        public async Task <IEnumerable <Event> > ProcessAsync(Event evnt)
        {
            var shardKeyArrived = evnt.GetBody <ShardKeyArrived>();

            _telemetryProvider.WriteTelemetry(
                "ShardKey receive message delay duration",
                (long)(DateTime.UtcNow - evnt.Timestamp).TotalMilliseconds,
                shardKeyArrived.Source.TypeName);

            await _durationInstrumentor.InstrumentAsync(async() =>
            {
                TheTrace.TraceInformation("Got {0} from {1}", shardKeyArrived.ShardKey,
                                          shardKeyArrived.Source.TypeName);

                var shardKeyQuerier = (string)shardKeyArrived.Source.GetDynamicProperty(ConveyorBeltConstants.ShardKeyQuery);
                var query           = FactoryHelper.Create <IShardKeyQuery>(shardKeyQuerier, typeof(TableStorageShardKeyQuery));
                var entities        = await query.QueryAsync(shardKeyArrived);

                var shardKeyTime = shardKeyArrived.GetDateTimeOffset().ToString("yyyyMMddHHmm");

                await _pusher.PushAll(PreprocessEntities(entities, shardKeyArrived, shardKeyTime), shardKeyArrived.Source).ConfigureAwait(false);
            }).ConfigureAwait(false);

            return(Enumerable.Empty <Event>());
        }
Ejemplo n.º 4
0
        private IEnumerable <DynamicTableEntity> PreprocessEntities(IEnumerable <DynamicTableEntity> entities, ShardKeyArrived shardKeyArrived, string shardKeyTime)
        {
            var minDateTime = DateTimeOffset.MaxValue;
            var n           = 0;

            foreach (var entity in entities)
            {
                var eventDateTimeOffset = entity.GetEventDateTimeOffset();
                var delayInSeconds      = entity.Timestamp.Subtract(eventDateTimeOffset).TotalSeconds;
                if (delayInSeconds >= _shardKeyDelayWarning)
                {
                    TheTrace.TraceWarning(
                        "SHARD_KEY_ACTOR_DELAY_DETECTED => Delay of {0} seconds for {1} in shardKey {2} and time {3}",
                        delayInSeconds, shardKeyArrived.Source.TypeName, shardKeyArrived.ShardKey, shardKeyTime);
                }

                entity.Timestamp = eventDateTimeOffset;
                yield return(entity);

                minDateTime = minDateTime > entity.Timestamp ? entity.Timestamp : minDateTime;
                n++;
            }

            TheTrace.TraceInformation("Gathered {0} records for {1} and ShardKey {2} => {1}_{2} {1}_{3}", n,
                                      shardKeyArrived.Source.TypeName, shardKeyArrived.ShardKey, shardKeyTime);

            if (n > 0)
            {
                _telemetryProvider.WriteTelemetry(
                    "ShardKeyArrivedActor log delay duration",
                    (long)(DateTimeOffset.UtcNow - minDateTime).TotalMilliseconds,
                    shardKeyArrived.Source.TypeName);
            }
        }
        public async Task <bool> UpdateMappingAsync(string baseUrl, string indexName, string typeName, string mapping)
        {
            TheTrace.TraceInformation("Adding {0} type to {1} index.", typeName, indexName);

            baseUrl = baseUrl.TrimEnd('/');
            var url      = string.Format(MappingFormat, baseUrl, indexName, typeName);
            var response = await _httpClient.PutAsync(url,
                                                      new StringContent(mapping, Encoding.UTF8, "application/json"));

            var text = await response.Content.ReadAsStringAsync();

            var mappings = _existingIndices[indexName];

            if (response.IsSuccessStatusCode)
            {
                mappings.TryAdd(typeName, null);
                return(true);
            }
            else
            {
                throw new ApplicationException(string.Format("Error {0}: {1}",
                                                             response.StatusCode,
                                                             text));
            }
        }
Ejemplo n.º 6
0
        private async Task DoScheduleAsync(PeckSource source)
        {
            var oldTimestamp = source.Timestamp;

            try
            {
                await _eventQueueOperator.PushAsync(new Event(new PeckSourceScheduled()
                {
                    Source = source
                })
                {
                    QueueName = QueueName.FromTopicName("PeckSourceScheduled").ToString()
                });

                source.LastOffset = DateTimeOffset.UtcNow;
                await _table.ExecuteAsync(TableOperation.InsertOrMerge(source));
            }
            catch (Exception e)
            {
                source.LastOffset = oldTimestamp;
                TheTrace.TraceError("Error scheduling source {0} : {1}", source.Name, e);
                try
                {
                    _table.Execute(TableOperation.InsertOrMerge(source));
                }
                catch (Exception ex)
                {
                    TheTrace.TraceError("Error saving error (!) in table. Source {0} : {1}", source.Name, ex);
                }
            }
        }
Ejemplo n.º 7
0
        public async Task <IEnumerable <Event> > ProcessAsync(Event evnt)
        {
            var shardKeyArrived = evnt.GetBody <ShardKeyArrived>();

            TheTrace.TraceInformation("Got {0} from {1}", shardKeyArrived.ShardKey,
                                      shardKeyArrived.Source.TypeName);

            var shardKeyQuerier = (string)shardKeyArrived.Source.GetDynamicProperty(ConveyorBeltConstants.ShardKeyQuery);
            var query           = FactoryHelper.Create <IShardKeyQuery>(shardKeyQuerier, typeof(TableStorageShardKeyQuery));
            var entities        = await query.QueryAsync(shardKeyArrived);

            bool hasAnything = false;

            foreach (var entity in entities)
            {
                await _pusher.PushAsync(entity, shardKeyArrived.Source);

                hasAnything = true;
            }

            if (hasAnything)
            {
                await _pusher.FlushAsync();
            }

            return(Enumerable.Empty <Event>());
        }
Ejemplo n.º 8
0
        public void CanAdd2And2EvenIfItFails()
        {
            var maths = new Worker("maths");
            var ran   = false;
            var timesForExceptions = 4;
            var job = new Job <int>(c =>
            {
                if (timesForExceptions-- > 0)
                {
                    throw new ApplicationException();
                }
                ran = true;
                return(Task.FromResult(2 + 2));
            },
                                    TheTrace.LogPolicy("this").RetryForeverAsync()
                                    );

            maths.Start();
            maths.Enqueue(job);
            while (!job.IsFinished)
            {
                Thread.Sleep(100);
            }
            Assert.True(ran);
        }
        private async Task PushbatchAsync()
        {
            if (_stringBuilder.Length == 0)
            {
                return;
            }

            try
            {
                var responseMessage = await _httpClient.PostAsync(_esUrl + "_bulk",
                                                                  new StringContent(_stringBuilder.ToString(),
                                                                                    Encoding.UTF8, "application/json"));

                _stringBuilder.Clear();
                _numberOfRecords = 0;
                responseMessage.EnsureSuccessStatusCode();

                TheTrace.TraceInformation("ConveyorBelt_Pusher: Pushing to {0}", _esUrl);
            }
            catch (Exception e)
            {
                TheTrace.TraceError(e.ToString());
                throw;
            }
        }
Ejemplo n.º 10
0
        public async Task <Tuple <IEnumerable <Event>, bool> > TryScheduleAsync(DiagnosticsSource source)
        {
            // if Stop offset has been reached
            if (!string.IsNullOrEmpty(source.StopOffsetPoint) && source.LastOffsetPoint != null && source.LastOffsetPoint.CompareTo(source.StopOffsetPoint) >= 0)
            {
                return(new Tuple <IEnumerable <Event>, bool>(Enumerable.Empty <Event>(), false));
            }

            var lockToken = new LockToken(source.ToTypeKey());
            int seconds   =
                Convert.ToInt32(_configurationValueProvider.GetValue(ConfigurationKeys.ClusterLockDurationSeconds));

            if (!(await _lockStore.TryLockAsync(lockToken, 2, 1000, seconds * 1000)))
            {
                TheTrace.TraceInformation("I could NOT be master for {0}", source.ToTypeKey());
                return(new Tuple <IEnumerable <Event>, bool>(Enumerable.Empty <Event>(), false));
            }
            try
            {
                var events = await DoSchedule(source);

                return(new Tuple <IEnumerable <Event>, bool>(events, true));
            }
            finally
            {
                Task.Run(() => _lockStore.ReleaseLockAsync(lockToken)).Wait();
            }
        }
Ejemplo n.º 11
0
        public async Task PushAsync(DynamicTableEntity entity, DiagnosticsSourceSummary source)
        {
            if (source.Filter == null)
            {
                source.Filter = string.Empty;
            }

            if (!_filters.ContainsKey(source.Filter))
            {
                _filters.Add(source.Filter, new SimpleFilter(source.Filter));
            }

            if (!_filters[source.Filter].Satisfies(entity))
            {
                return;
            }

            var op = new
            {
                index = new
                {
                    _index = source.IndexName ?? _indexNamer.BuildName(entity.Timestamp, source.DynamicProperties["MappingName"].ToString().ToLowerInvariant()),
                    _type  = source.DynamicProperties["MappingName"].ToString(),
                    _id    = entity.PartitionKey + entity.RowKey
                }
            };

            var doc = new JObject();

            doc.Add("@timestamp", entity.Timestamp);
            doc.Add("PartitionKey", entity.PartitionKey);
            doc.Add("RowKey", entity.RowKey);
            doc.Add("cb_type", source.TypeName);

            foreach (var property in entity.Properties)
            {
                if (property.Key != DiagnosticsSource.CustomAttributesFieldName)
                {
                    doc[property.Key] = JToken.FromObject(property.Value.PropertyAsObject);
                }
            }
            if (entity.Properties.ContainsKey(DiagnosticsSource.CustomAttributesFieldName))
            {
                foreach (var keyValue in GetNameValues(entity.Properties[DiagnosticsSource.CustomAttributesFieldName].StringValue))
                {
                    doc[keyValue.Key] = keyValue.Value;
                }
            }

            _batch.AddDoc(JsonConvert.SerializeObject(op).Replace("\r\n", " "), doc.ToString().Replace("\r\n", " "));

            if (_batch.Count >= _batchSize)
            {
                await PushbatchAsync();

                TheTrace.TraceInformation("ConveyorBelt_Pusher: Pushed records to ElasticSearch for {0}-{1}",
                                          source.PartitionKey,
                                          source.RowKey);
            }
        }
Ejemplo n.º 12
0
        private void LoadState(Guid?seedId = null)
        {
            using (var tx = _env.BeginReadOnlyTransaction())
            {
                LoadLastTermAndIndex(tx);

                // snapshot
                Snapshot ss;
                if (TryGetLastSnapshot(out ss))
                {
                    LogOffset = ss.LastIncludedIndex + 1;
                }

                // state
                _state = new PersistentState(seedId);
                Bufferable val;
                if (tx.TryGet(_stateDb, StateDbKeys.Id, out val))
                {
                    _state.Id = val;

                    if (tx.TryGet(_stateDb, StateDbKeys.CurrentTerm, out val)) // this should be always TRUE
                    {
                        _state.CurrentTerm = val;
                    }

                    if (tx.TryGet(_stateDb, StateDbKeys.LastVotedFor, out val))
                    {
                        Guid g = val;
                        _state.LastVotedForId = g == Guid.Empty ? (Guid?)null : g;
                    }
                }
            }

            TheTrace.TraceInformation($"Seed Id was {seedId} and now {_state.Id}");
        }
Ejemplo n.º 13
0
        public async Task <IEnumerable <Event> > ProcessAsync(Event evnt)
        {
            var shardKeyArrived = evnt.GetBody <ShardRangeArrived>();

            TheTrace.TraceInformation("Got {0}->{1} from {2}", shardKeyArrived.InclusiveStartKey,
                                      shardKeyArrived.InclusiveEndKey, shardKeyArrived.Source.TypeName);

            var account = CloudStorageAccount.Parse(shardKeyArrived.Source.ConnectionString);
            var client  = account.CreateCloudTableClient();
            var table   = client.GetTableReference(shardKeyArrived.Source.DynamicProperties["TableName"].ToString());

            var entities = table.ExecuteQuery(new TableQuery().Where(
                                                  TableQuery.CombineFilters(
                                                      TableQuery.GenerateFilterCondition("PartitionKey", "ge", shardKeyArrived.InclusiveStartKey),
                                                      TableOperators.And,
                                                      TableQuery.GenerateFilterCondition("PartitionKey", "le", shardKeyArrived.InclusiveEndKey))));

            bool hasAnything = false;

            foreach (var entity in entities)
            {
                await _pusher.PushAsync(entity, shardKeyArrived.Source);

                hasAnything = true;
            }

            if (hasAnything)
            {
                await _pusher.FlushAsync();
            }

            return(Enumerable.Empty <Event>());
        }
Ejemplo n.º 14
0
        public async Task KeepFeedingAFollowerAndNeverDreamsOfPower()
        {
            var t        = new CancellationTokenSource();
            var leaderId = Guid.NewGuid();

            _server = new DefaultRaftServer(_sister, _sister, _sister, _maqina.Object, _manijer.Object, _settings);
            _server.Start();

            // to set the term to 1
            await _server.AppendEntriesAsync(new AppendEntriesRequest()
            {
                CurrentTerm       = 1,
                Entries           = new byte[0][],
                LeaderCommitIndex = 20,
                LeaderId          = leaderId,
                PreviousLogIndex  = -1,
                PreviousLogTerm   = 0
            });

            _server.LastHeartBeat     = new AlwaysRecentTimestamp();
            _server.LastHeartBeatSent = new AlwaysRecentTimestamp();

            TheTrace.TraceInformation("OK, now this is before wait...");
            Thread.Sleep(1000);
            TheTrace.TraceInformation("Wait finished.");
            Assert.Equal(1, _server.State.CurrentTerm);
            TheTrace.TraceInformation("Checked Term.");
            Assert.Equal(Role.Follower, _server.Role);
            TheTrace.TraceInformation("Checked Role.");
            t.Cancel();
        }
Ejemplo n.º 15
0
        public async Task KeepExtendingLeaseAsync(Event message, TimeSpan howLong, CancellationToken cancellationToken)
        {
            await Task.Delay(new TimeSpan(2 * howLong.Ticks / 3), cancellationToken);

            while (true)
            {
                try
                {
                    if (cancellationToken.IsCancellationRequested)
                    {
                        break;
                    }

                    var underlyingMessage = (BrokeredMessage)message.UnderlyingMessage;
                    await underlyingMessage.RenewLockAsync();

                    await Task.Delay(new TimeSpan(2 * howLong.Ticks / 3), cancellationToken);
                }
                catch (Exception exception)
                {
                    TheTrace.TraceError(exception.ToString());
                    break;
                }
            }
        }
Ejemplo n.º 16
0
        public async Task <PollerResult <Event> > NextAsync(QueueName name)
        {
            try
            {
                BrokeredMessage message = null;
                if (name.IsSimpleQueue)
                {
                    var client = _clientProvider.GetQueueClient(name);
                    message = await client.ReceiveAsync(_longPollingTimeout);
                }
                else
                {
                    var client = _clientProvider.GetSubscriptionClient(name);
                    message = await client.ReceiveAsync(_longPollingTimeout);
                }

                return(new PollerResult <Event>(message != null,
                                                message == null
                            ? null
                            : message.ToEvent(name)
                                                ));
            }
            catch (Exception e)
            {
                TheTrace.TraceWarning(e.ToString());
                return(new PollerResult <Event>(false, null));
            }
        }
Ejemplo n.º 17
0
        /// <summary>
        /// Note: RunAsync and Start ping-pong between each other.
        /// </summary>
        /// <returns></returns>

        private async Task RunAsync()
        {
            bool result = false;

            try
            {
                _cancellationTokenSource = new CancellationTokenSource();
                result = await _work(_cancellationTokenSource.Token);
            }
            catch (Exception exception)
            {
                TheTrace.TraceWarning(exception.ToString());
            }

            if (result)
            {
                _interval.Reset();
            }
            else
            {
                await Task.Delay(_interval.Next());
            }

            if (_isWorking)
            {
                Start();
            }
        }
Ejemplo n.º 18
0
        private async Task KeepExtendingLeaseAsync(Func <Task> extendLeaseAsync, TimeSpan howLong, CancellationToken cancellationToken, string resource)
        {
            await EnsureExists();

            var thisLong = new TimeSpan(2 * howLong.Ticks / 3); // RATM: how long? This long, what you reap is what you sew!
            await Task.Delay(thisLong, cancellationToken);

            while (true)
            {
                try
                {
                    if (cancellationToken.IsCancellationRequested)
                    {
                        break;
                    }

                    await extendLeaseAsync();

                    TheTrace.TraceInformation("Extended the lifetime of the lease for {0}...", resource);
                    await Task.Delay(thisLong, cancellationToken);
                }
                catch (Exception exception)
                {
                    if (!cancellationToken.IsCancellationRequested) // it is OK if cancellation requested, it would have been cancellation
                    {
                        TheTrace.TraceError(exception.ToString());
                    }
                    break;
                }
            }
        }
Ejemplo n.º 19
0
        public Task <Tuple <IEnumerable <Event>, bool> > TryScheduleAsync(DiagnosticsSource source)
        {
            var key = source.ToTypeKey();

            if (source.IsActive.GetValueOrDefault(true))
            {
                var consume = EventHubConsumer.Consumers.AddOrUpdate(key,
                                                                     new Lazy <EventHubConsumer>(() =>
                {
                    TheTrace.TraceInformation("Just added this eventHub consumer {0}", key);
                    return(new EventHubConsumer(_pusher, source.ToSummary()));
                }),
                                                                     (kk, vv) => vv);

                // to make sure it gets accessed and created if new otherwise system is 'lazy'
                TheTrace.TraceInformation("This is the EventHub thing I was talking about: {0}", consume.Value.Source.TypeName);
            }
            else
            {
                Lazy <EventHubConsumer> consumer = null;

                if (EventHubConsumer.Consumers.TryRemove(key, out consumer))
                {
                    consumer.Value.Dispose();
                    TheTrace.TraceInformation("Just removed this eventHub consumer {0}", key);
                }
            }

            return(Task.FromResult(new Tuple <IEnumerable <Event>, bool>(new Event[0], false)));
        }
Ejemplo n.º 20
0
        private void SetupPeerAppendLogJobs(IEnumerable <Peer> peers)
        {
            foreach (var w in _workers.GetWorkers(Queues.PeerAppendLog))
            {
                w.Start();
            }

            _workers.GetWorkers(Queues.ProcessCommandQueue).Single().Start();

            foreach (var p in peers)
            {
                var localP = p;
                var q      = Queues.PeerAppendLog + localP.Address;
                TheTrace.TraceInformation($"[{_meAsAPeer.ShortName}] setting up peer append log for queue {q}");
                var todo = PeerAppendLog(localP);

                _workers.Enqueue(q,
                                 new Job(todo,
                                         TheTrace.LogPolicy(_meAsAPeer.ShortName).WaitAndRetryAsync(3, (i) => TimeSpan.FromMilliseconds(i * i * 50)),
                                         TimeSpan.FromMilliseconds(30)));
            }

            // Applying commands received from the clients
            Func <CancellationToken, Task> pcq = ProcessCommandsQueue;

            _workers.Enqueue(Queues.ProcessCommandQueue,
                             new Job(pcq,
                                     TheTrace.LogPolicy(_meAsAPeer.ShortName).RetryForeverAsync(),
                                     _settings.ElectionTimeoutMin.Multiply(0.2)));
        }
        protected override Task <IEnumerable <Event> > DoSchedule(DiagnosticsSource source)
        {
            if (source.LastOffsetPoint == null)
            {
                source.LastOffsetPoint = DateTimeOffset.UtcNow.AddDays(-1).DropSecondAndMilliseconds().ToString("O");
            }

            var lastOffset   = DateTimeOffset.Parse(source.LastOffsetPoint);
            var events       = new List <Event>();
            var graceMinutes = source.GracePeriodMinutes ?? 3;

            var now           = DateTimeOffset.UtcNow.DropSecondAndMilliseconds();
            var newLastOffset = lastOffset;
            int n             = 1; // start from a minute after

            while (now >= lastOffset.Add(TimeSpan.FromMinutes(graceMinutes + n)))
            {
                newLastOffset = lastOffset.Add(TimeSpan.FromMinutes(n))
                                .DropSecondAndMilliseconds(); // just to be sure
                var shardKeys = GetShardKeys(newLastOffset);
                events.AddRange(shardKeys.Select(shardKey => new Event(new ShardKeyArrived {
                    Source = source.ToSummary(), ShardKey = shardKey
                })));
                if (source.MaxItemsInAScheduleRun.HasValue && n >= source.MaxItemsInAScheduleRun)
                {
                    break;
                }
                n++;
                TheTrace.TraceInformation("Scheduling {0} for minute {1} and shardkey {2} => {0}_{1} AND {0}_{2}", source.ToTypeKey(), newLastOffset.ToString("yyyyMMddHHmm"), shardKeys.First());
            }

            source.LastOffsetPoint = newLastOffset.ToString("O");
            return(Task.FromResult((IEnumerable <Event>)events));
        }
        public async Task <IEnumerable <DynamicTableEntity> > QueryAsync(ShardKeyArrived shardKeyArrived)
        {
            //var account = CloudStorageAccount.Parse(shardKeyArrived.Source.ConnectionString);
            CloudStorageAccount account = null;

            if (!String.IsNullOrWhiteSpace(shardKeyArrived.Source.AccountSasKey))
            {
                // Create new storage credentials using the SAS token.
                var accountSas = new StorageCredentials(shardKeyArrived.Source.AccountSasKey);
                // Use these credentials and the account name to create a Blob service client.
                try
                {
                    account = new CloudStorageAccount(accountSas, shardKeyArrived.Source.AccountName, endpointSuffix: "", useHttps: true);
                }
                catch (Exception ex)
                {
                    TheTrace.TraceError(ex.ToString());
                }
            }
            else
            {
                account = CloudStorageAccount.Parse(shardKeyArrived.Source.ConnectionString);
            }
            var client = account.CreateCloudTableClient();
            var table  = client.GetTableReference(shardKeyArrived.Source.DynamicProperties["TableName"].ToString());


            return(await table.ExecuteQueryAsync(new TableQuery().Where(TableQuery.GenerateFilterCondition("PartitionKey", "eq", shardKeyArrived.ShardKey))).ConfigureAwait(false));
        }
Ejemplo n.º 23
0
        public async Task <IEnumerable <Event> > ProcessAsync(Event evnt)
        {
            var blobFileArrived = evnt.GetBody <BlobFileArrived>();

            _telemetryProvider.WriteTelemetry(
                "BlobFileActor receive message delay duration",
                (long)(DateTime.UtcNow - evnt.Timestamp).TotalMilliseconds,
                blobFileArrived.Source.TypeName);

            await _durationInstrumentor.InstrumentAsync(async() =>
            {
                TheTrace.TraceInformation("Got {0} from {1}", blobFileArrived.BlobId,
                                          blobFileArrived.Source.TypeName);
                //var account = CloudStorageAccount.Parse(blobFileArrived.Source.ConnectionString);
                CloudStorageAccount account;
                if (!String.IsNullOrWhiteSpace(blobFileArrived.Source.AccountSasKey))
                {
                    // Create new storage credentials using the SAS token.
                    var accountSas = new StorageCredentials(blobFileArrived.Source.AccountSasKey);
                    // Use these credentials and the account name to create a Blob service client.
                    account = new CloudStorageAccount(accountSas, blobFileArrived.Source.AccountName, "", useHttps: true);
                }
                else
                {
                    account = CloudStorageAccount.Parse(blobFileArrived.Source.ConnectionString);
                }
                var client    = account.CreateCloudBlobClient();
                var container = client.GetContainerReference(blobFileArrived.Source.DynamicProperties["ContainerName"].ToString());
                var uri       = new Uri(blobFileArrived.BlobId);
                var id        = string.Join("", uri.Segments.Skip(2));
                var blob      = container.GetBlockBlobReference(id);
                if (!blob.Exists())
                {
                    throw new InvalidOperationException("Blob does not exist: " + id);
                }
                var stream = new MemoryStream();
                await blob.DownloadToStreamAsync(stream);
                var parser      = FactoryHelper.Create <IParser>(blobFileArrived.Source.DynamicProperties["Parser"].ToString(), typeof(IisLogParser));
                var hasAnything = false;
                var minDateTime = DateTimeOffset.UtcNow;

                var records = parser.Parse(() => stream, blob.Uri, blobFileArrived.Source, new ParseCursor(blobFileArrived.Position ?? 0)
                {
                    EndPosition = blobFileArrived.EndPosition ?? 0
                });
                var seenPages = await _pusher.PushAll(records, blobFileArrived.Source).ConfigureAwait(false);
                hasAnything   = seenPages > 0;

                if (hasAnything)
                {
                    _telemetryProvider.WriteTelemetry(
                        "BlobFileActor message processing duration",
                        (long)(DateTimeOffset.UtcNow - minDateTime).TotalMilliseconds,
                        blobFileArrived.Source.TypeName);
                }
            }, blobFileArrived.Source.TypeName);

            return(Enumerable.Empty <Event>());
        }
Ejemplo n.º 24
0
        private async Task Candidacy(CancellationToken c)
        {
            while (_role == Role.Candidate)
            {
                var forMe     = 1; // vote for yourself
                var againstMe = 0;

                var peers     = _peerManager.GetPeers().ToArray();
                var concensus = (peers.Length / 2) + 1;
                var proxies   = peers.Select(x => _peerManager.GetProxy(x.Address));
                var retry     = TheTrace.LogPolicy(_meAsAPeer.ShortName).WaitAndRetryAsync(3, (i) => TimeSpan.FromMilliseconds(i * i * 30));
                var policy    = Policy.TimeoutAsync(_settings.CandidacyTimeout).WrapAsync(retry);
                var request   = new RequestVoteRequest()
                {
                    CandidateId  = State.Id,
                    CurrentTerm  = State.CurrentTerm,
                    LastLogIndex = _logPersister.LastIndex,
                    LastLogTerm  = _logPersister.LastEntryTerm
                };

                var all = await Task.WhenAll(proxies.Select(p => policy.ExecuteAndCaptureAsync(() => p.RequestVoteAsync(request))));

                var maxTerm = 0L;
                foreach (var r in all)
                {
                    if (r.Outcome == OutcomeType.Successful)
                    {
                        if (r.Result.CurrentTerm > maxTerm)
                        {
                            maxTerm = r.Result.CurrentTerm;
                        }

                        if (r.Result != null && r.Result.VoteGranted)
                        {
                            forMe++;
                        }
                        else
                        {
                            againstMe++;
                        }
                    }
                }

                if (againstMe >= concensus)
                {
                    TheTrace.TraceInformation($"[{_meAsAPeer.ShortName}] Result of the candidacy for term {State.CurrentTerm}. I got rejected with {againstMe} votes :/");
                    BecomeFollower(maxTerm);
                }
                else if (forMe >= concensus)
                {
                    TheTrace.TraceInformation($"[{_meAsAPeer.ShortName}] Result of the candidacy for term {State.CurrentTerm}. I got elected with {forMe} votes! :)");
                    BecomeLeader();
                }
                else
                {
                    TheTrace.TraceInformation($"[{_meAsAPeer.ShortName}] Result of the candidacy for term {State.CurrentTerm}. Non-conclusive with {forMe} for me and {againstMe} against me.");
                }
            }
        }
Ejemplo n.º 25
0
 public void Dispose()
 {
     TheTrace.TraceInformation($"[{_meAsAPeer.ShortName}] Disposing server.");
     _workers.Stop();
     TheTrace.TraceInformation($"[{_meAsAPeer.ShortName}] Disposing server. Workers stopped.");
     _logPersister.Dispose();
     TheTrace.TraceInformation($"[{_meAsAPeer.ShortName}] Disposing server. Log Persister stopped.");
 }
Ejemplo n.º 26
0
        protected override Task <IEnumerable <Event> > DoSchedule(DiagnosticsSource source)
        {
            TheTrace.TraceInformation("IisBlobScheduler - Starting scheduling");
            //var account = CloudStorageAccount.Parse(source.ConnectionString);
            CloudStorageAccount account;

            if (!String.IsNullOrWhiteSpace(source.AccountSasKey))
            {
                // Create new storage credentials using the SAS token.
                var accountSas = new StorageCredentials(source.AccountSasKey);
                // Use these credentials and the account name to create a Blob service client.
                account = new CloudStorageAccount(accountSas, source.AccountName, "", useHttps: true);
            }
            else
            {
                account = CloudStorageAccount.Parse(source.ConnectionString);
            }
            var client   = account.CreateCloudBlobClient();
            var blobPath = source.GetProperty <string>("BlobPath");

            TheTrace.TraceInformation("IisBlobScheduler - pathformat: {0}", blobPath);
            blobPath = blobPath.TrimEnd('/') + "/"; // ensure path ends with /
            var offset = FileOffset.Parse(source.LastOffsetPoint);

            if (offset == null)
            {
                throw new InvalidOperationException("FileOffset failed parsing: => " + source.LastOffsetPoint);
            }

            DateTimeOffset maxOffset = offset.TimeOffset;
            FileOffset     newOffset = null;
            var            events    = new List <Event>();

            foreach (var blob in client.ListBlobs(blobPath).Where(itm => itm is CloudBlockBlob)
                     .Cast <CloudBlockBlob>().OrderBy(x => x.Properties.LastModified))
            {
                if (blob.Properties.LastModified > offset.TimeOffset)
                {
                    var filename = blob.Uri.ToString();
                    newOffset = new FileOffset(filename, blob.Properties.LastModified ?? DateTimeOffset.UtcNow, 0);
                    TheTrace.TraceInformation("IisBlobScheduler - found {0}", blob.Uri);

                    events.Add(new Event(new BlobFileArrived()
                    {
                        Source      = source.ToSummary(),
                        BlobId      = filename,
                        Position    = 0,
                        EndPosition = blob.Properties.Length
                    }));

                    TheTrace.TraceInformation("Created BlobFileArrived for file: {0}", filename);
                }
            }

            source.LastOffsetPoint = newOffset == null?offset.ToString() : newOffset.ToString();

            return(Task.FromResult((IEnumerable <Event>)events));
        }
Ejemplo n.º 27
0
 private void BecomeFollower(long term)
 {
     State.LastVotedForId = null;
     DestroyPeerAppendLogJobs();
     _lastHeartbeat.Set(); // important not to become candidate again at least for another timeout
     TheTrace.TraceInformation($"[{_meAsAPeer.ShortName}] About to set term from {State.CurrentTerm} to {term}");
     State.CurrentTerm   = term;
     OnRoleChanged(_role = Role.Follower);
 }
Ejemplo n.º 28
0
        private async Task HeartBeatSend(CancellationToken c)
        {
            if (_role != Role.Leader)
            {
                return;
            }

            if (_lastHeartbeatSent.Since() < _settings.ElectionTimeoutMin.Multiply(0.2))
            {
                return;
            }

            var currentTerm = State.CurrentTerm; // create a var. Could change during the method leading to confusing logs.

            var req = new AppendEntriesRequest()
            {
                CurrentTerm       = currentTerm,
                Entries           = new byte[0][],
                LeaderCommitIndex = _volatileState.CommitIndex,
                LeaderId          = State.Id,
                PreviousLogIndex  = long.MaxValue,
                PreviousLogTerm   = long.MaxValue
            };

            var peers   = _peerManager.GetPeers().ToArray();
            var proxies = peers.Select(x => _peerManager.GetProxy(x.Address));
            var retry   = TheTrace.LogPolicy(_meAsAPeer.ShortName).RetryForeverAsync();
            var policy  = Policy.TimeoutAsync(_settings.ElectionTimeoutMin.Multiply(0.2)).WrapAsync(retry);
            var all     = await Task.WhenAll(proxies.Select(p => policy.ExecuteAndCaptureAsync(() => p.AppendEntriesAsync(req))));

            var maxTerm = currentTerm;

            foreach (var r in all)
            {
                if (r.Outcome == OutcomeType.Successful)
                {
                    if (!r.Result.IsSuccess)
                    {
                        TheTrace.TraceWarning($"[{_meAsAPeer.ShortName}] Got this reason for unsuccessful AppendEntriesAsync from a peer: {r.Result.Reason}");
                    }

                    // NOTE: We do NOT change leadership if they send higher term, since they could be candidates whom will not become leaders
                    // we actually do not need to do anything with the result other than logging it
                    if (r.Result.CurrentTerm > maxTerm)
                    {
                        maxTerm = r.Result.CurrentTerm;
                    }
                }
            }

            if (maxTerm > State.CurrentTerm)
            {
                TheTrace.TraceWarning($"[{_meAsAPeer.ShortName}] Revolution brewing. Terms as high as {maxTerm} (vs my {currentTerm}) were seen.");
            }

            _lastHeartbeatSent.Set();
        }
Ejemplo n.º 29
0
        public async Task <IEnumerable <Event> > ProcessAsync(Event evnt)
        {
            var shardKeyArrived = evnt.GetBody <ShardKeyArrived>();

            _telemetryProvider.WriteTelemetry(
                "ShardKey receive message delay duration",
                (long)(DateTime.UtcNow - evnt.Timestamp).TotalMilliseconds,
                shardKeyArrived.Source.TypeName);

            await _durationInstrumentor.InstrumentAsync(async() =>
            {
                TheTrace.TraceInformation("Got {0} from {1}", shardKeyArrived.ShardKey,
                                          shardKeyArrived.Source.TypeName);

                var shardKeyQuerier = (string)shardKeyArrived.Source.GetDynamicProperty(ConveyorBeltConstants.ShardKeyQuery);
                var query           = FactoryHelper.Create <IShardKeyQuery>(shardKeyQuerier, typeof(TableStorageShardKeyQuery));
                var entities        = await query.QueryAsync(shardKeyArrived);

                var minDateTime  = DateTimeOffset.MaxValue;
                var hasAnything  = false;
                int n            = 0;
                var shardKeyTime = shardKeyArrived.GetDateTimeOffset().ToString("yyyyMMddHHmm");

                foreach (var entity in entities)
                {
                    var eventDateTimeOffset = entity.GetEventDateTimeOffset();
                    var delayInSeconds      = entity.Timestamp.Subtract(eventDateTimeOffset).TotalSeconds;
                    if (delayInSeconds >= _shardKeyDelayWarning)
                    {
                        TheTrace.TraceWarning("SHARD_KEY_ACTOR_DELAY_DETECTED => Delay of {0} seconds for {1} in shardKey {2} and time {3}",
                                              delayInSeconds, shardKeyArrived.Source.TypeName, shardKeyArrived.ShardKey, shardKeyTime);
                    }

                    entity.Timestamp = eventDateTimeOffset;
                    await _pusher.PushAsync(entity, shardKeyArrived.Source);
                    hasAnything = true;
                    minDateTime = minDateTime > entity.Timestamp ? entity.Timestamp : minDateTime;
                    n++;
                }

                TheTrace.TraceInformation("Gathered {0} records for {1} and ShardKey {2} => {1}_{2} {1}_{3}", n,
                                          shardKeyArrived.Source.TypeName, shardKeyArrived.ShardKey, shardKeyTime);

                if (hasAnything)
                {
                    await _pusher.FlushAsync();

                    _telemetryProvider.WriteTelemetry(
                        "ShardKeyArrivedActor log delay duration",
                        (long)(DateTimeOffset.UtcNow - minDateTime).TotalMilliseconds,
                        shardKeyArrived.Source.TypeName);
                }
            });

            return(Enumerable.Empty <Event>());
        }
Ejemplo n.º 30
0
 private void BecomeCandidate()
 {
     TheTrace.TraceInformation($"[{_meAsAPeer.ShortName}] BecomeCandidate start");
     State.IncrementTerm();
     State.LastVotedForId = State.Id;
     _leaderAddress       = null;
     DestroyPeerAppendLogJobs();
     OnRoleChanged(_role = Role.Candidate);
     TheTrace.TraceInformation($"[{_meAsAPeer.ShortName}] BecomeCandidate end");
 }