private async Task HandleGitHubEvent(string gitHubEvent, DateTimeOffset messageEnqueueTime) { var eventJtoken = JToken.Parse(gitHubEvent); var eventType = eventJtoken["eventType"].ToString(); if (!Enum.TryParse( eventType, true, out GitHubEventActions parsedEvent)) { return; } if (gitHubEventHandlers.TryGetValue(parsedEvent, out var selectedEventHandler)) { await selectedEventHandler.HandleEvent(gitHubEvent); } else { // this should never happen // there must always be a handler for an accepted eventType logger.LogError("Received unknown event in GitHubEventHost. {eventType}", eventType); telemetry.RecordMetric("GitHubEventHost-UnknownEvent", 1); } var messageProcessingCompleteDelay = DateTimeOffset.UtcNow - messageEnqueueTime; telemetry.RecordMetric( "EndMessageProcessing-Delay", (long)messageProcessingCompleteDelay.TotalSeconds, ("EventType", eventType)); }
public async Task<byte[]> GetAsync(string key, CancellationToken token = new CancellationToken()) { logger.LogInformation($"get blob cache: key={key}"); var tokenInfo = await blobClient.GetBlobInfo(key, token); if (tokenInfo == null) { logger.LogInformation($"blob cache miss: key={key}"); appTelemetry.RecordMetric("blob-cache-miss", 1, ("key", key)); return null; } if (tokenInfo.CreatedOn.Add(cacheSettings.TimeToLive) < DateTimeOffset.UtcNow) { logger.LogInformation($"blob cache expired: key={key}"); appTelemetry.RecordMetric("blob-cache-expired", 1, ("key", key)); return null; } await blobClient.DownloadAsync(null, key, tempFolder, token); var downloadedBlogFile = Path.Combine(tempFolder, key); if (!File.Exists(downloadedBlogFile)) throw new InvalidOperationException($"blob download file not found: {downloadedBlogFile}"); var bytes = await File.ReadAllBytesAsync(downloadedBlogFile, token); File.Delete(downloadedBlogFile); logger.LogInformation($"blob cache downloaded: key={key}"); return bytes; }
public async Task HandleEvent(string gitHubEvent) { var payload = new Octokit.Internal.SimpleJsonSerializer().Deserialize <PullRequestEventPayload>(gitHubEvent); logger.LogInformation( "Quantifying pull request: {pullRequestUrl}|{pullRequestId}|{sha}", payload.PullRequest.HtmlUrl, payload.PullRequest.Id, payload.PullRequest.Head.Sha); telemetry.RecordMetric( "PullRequest-QuantifyRequest", 1); var quantifierResult = await QuantifyPullRequest(payload); logger.LogInformation( "Quantified pull request: {pullRequestUrl}|{pullRequestId}|{sha}|" + "{label}|{formula}|{absoluteLinesAdded}|{absoluteLinesDeleted}|" + "{quantifiedLinesAdded}|{quantifiedLinesDeleted}|" + "{percentileAddition}|{percentileDeletion}|{formulaPercentile}", payload.PullRequest.HtmlUrl, payload.PullRequest.Id, payload.PullRequest.Head.Sha, quantifierResult.Label, quantifierResult.Formula, quantifierResult.QuantifierInput.Changes.Sum(c => c.AbsoluteLinesAdded), quantifierResult.QuantifierInput.Changes.Sum(c => c.AbsoluteLinesDeleted), quantifierResult.QuantifiedLinesAdded, quantifierResult.QuantifiedLinesDeleted, quantifierResult.PercentileAddition, quantifierResult.PercentileDeletion, quantifierResult.FormulaPercentile); }
public async Task SubscribeAsync( Func <string, DateTimeOffset, Task> messageHandler, Func <Exception, Task> errorHandler, CancellationToken cancellationToken) { // add handler to process messages processor.ProcessMessageAsync += async args => { using var operation = telemetry.StartOperation <RequestTelemetry>(this, args.Message.CorrelationId); var messageProcessingStartDelay = DateTimeOffset.UtcNow - args.Message.EnqueuedTime; telemetry.RecordMetric( "StartMessageProcessing-Delay", (long)messageProcessingStartDelay.TotalSeconds); await messageHandler(args.Message.Body.ToString(), args.Message.EnqueuedTime); // delete the message await args.CompleteMessageAsync(args.Message, cancellationToken); }; // add handler to process any errors processor.ProcessErrorAsync += async args => { await errorHandler(args.Exception); }; // start processing await processor.StartProcessingAsync(cancellationToken); }
public async Task <byte[]> GetAsync(string key, CancellationToken token = new CancellationToken()) { logger.LogInformation($"get spillable memory cache: {key}"); try { if (memoryCache.TryGetValue(key, out var value) && value is byte[] cachedValue) { logger.LogInformation($"read cache from memory, key={key}"); appTelemetry.RecordMetric("memory-cache-hit", 1, ("key", key)); return(cachedValue); } appTelemetry.RecordMetric("memory-cache-miss", 1, ("key", key)); var cacheFile = Path.Combine(cacheFolder, key); if (File.Exists(cacheFile)) { if (File.GetCreationTimeUtc(cacheFile).Add(cacheSettings.TimeToLive) < DateTimeOffset.UtcNow) { logger.LogInformation($"read cache from file, key={key}"); appTelemetry.RecordMetric("file-cache-expired", 1, ("key", key)); return(null); } } else { appTelemetry.RecordMetric("file-cache-miss", 1, ("key", key)); return(null); } var fileContent = await File.ReadAllBytesAsync(cacheFile, token); appTelemetry.RecordMetric("file-cache-hit", 1, ("key", key)); var size = (int)Math.Ceiling((double)fileContent.Length / 1000000); // MB var entryOptions = new MemoryCacheEntryOptions() .SetSize(size) .SetSlidingExpiration(cacheSettings.TimeToLive); memoryCache.Set(key, fileContent, entryOptions); return(fileContent); } catch (Exception ex) { logger.LogError(ex, $"unable to get cache: {key}"); return(null); } }
protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { log.LogTrace("heartbeat"); metrics.RecordMetric("Heartbeat", 1); var sleepSeconds = 15; while (sleepSeconds-- > 0 && !stoppingToken.IsCancellationRequested) { await Task.Delay(TimeSpan.FromSeconds(1), stoppingToken); } } log.LogInformation("KeepAlive stopped!"); }
public Task HandleEvent(string gitHubEvent) { var payload = new Octokit.Internal.SimpleJsonSerializer().Deserialize <InstallationEventPayload>(gitHubEvent); logger.LogInformation( "Installation event: {accountId} | {accountLogin} | {accountUrl} | {accountType} | " + "{action} | {repositorySelection} | {repositories}", payload.Installation.Account.Id, payload.Installation.Account.Login, payload.Installation.Account.Url, payload.Installation.Account.Type.ToString(), payload.Action, payload.Installation.RepositorySelection, payload.Repositories != null ? string.Join(" , ", payload.Repositories.Select(r => r.FullName)) : string.Empty); telemetry.RecordMetric( "Installation-Event", 1, ("Action", payload.Action)); return(Task.CompletedTask); }
public async Task <T> GetOrUpdateAsync <T>( string key, Func <Task <DateTimeOffset> > getLastModificationTime, Func <Task <T> > getItem, CancellationToken cancel) where T : class, new() { logger.LogInformation($"get cached item, key={key}"); var value = await multilayerCache.GetAsync(key, cancel); CachedItem <T> cachedItem; async Task <T> RefreshItem() { var item = await getItem(); cachedItem = new CachedItem <T>(item); string serializeObject = Serialize(cachedItem); value = Encoding.UTF8.GetBytes(serializeObject); logger.LogInformation($"updating cache {key}..."); #pragma warning disable 4014 // ReSharper disable once MethodSupportsCancellation multilayerCache.SetAsync(key, value, cacheEntryOptions); #pragma warning restore 4014 return(item); } if (value == null) { appTelemetry.RecordMetric("cache-miss", 1, ("key", key)); return(await RefreshItem()); } var json = Encoding.UTF8.GetString(value); cachedItem = JsonConvert.DeserializeObject <CachedItem <T> >(json); var needRefresh = false; if (cachedItem.CreatedOn.Add(settings.TimeToLive) < DateTimeOffset.UtcNow) { appTelemetry.RecordMetric("cache-expired", 1, ("key", key)); needRefresh = true; } else { var lastUpdateTime = await getLastModificationTime(); if (lastUpdateTime != default && lastUpdateTime > cachedItem.CreatedOn) { needRefresh = true; } } if (needRefresh) { #pragma warning disable 4014 // ReSharper disable once MethodSupportsCancellation Task.Factory.StartNew(RefreshItem); #pragma warning restore 4014 } return(cachedItem.Value); }