Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add timeouts to fail faster #412

Merged
merged 2 commits into from
Sep 11, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 40 additions & 19 deletions Source/Bake/Cooking/Editor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,12 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Bake.Cooking.Ingredients.Gathers;
using Bake.Core;
using Bake.Extensions;
using Bake.Services;
using Bake.ValueObjects;
using Bake.ValueObjects.Artifacts;
using Bake.ValueObjects.Recipes;
using Microsoft.Extensions.Logging;

Expand Down Expand Up @@ -68,7 +63,43 @@ public async Task<Book> ComposeAsync(
context.Ingredients.WorkingDirectory,
context.Ingredients.Version);

await Task.WhenAll(_gathers.Select(g => g.GatherAsync(context.Ingredients, cancellationToken)));
await ExecuteGatherersAsync(context, cancellationToken);

var recipes = await ExecuteComposersAsync(context, cancellationToken);

var book = new Book(
context.Ingredients,
recipes.ToArray());

if (_logger.IsEnabled(LogLevel.Trace))
{
var yaml = await _yaml.SerializeAsync(book, cancellationToken);
_logger.LogTrace("Create the following YAML {Book}", yaml);
}

return book;
}

private async Task ExecuteGatherersAsync(Context context, CancellationToken cancellationToken)
{
using var timeout = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
timeout.CancelAfter(TimeSpan.FromMinutes(5));

try
{
await Task.WhenAll(_gathers.Select(g => g.GatherAsync(context.Ingredients, timeout.Token)));
}
catch (Exception e) when (e is TaskCanceledException or OperationCanceledException && timeout.IsCancellationRequested)
{
Console.WriteLine("Gathering repository meta data took too long! Aborting :(");
throw;
}
}

private async Task<List<Recipe>> ExecuteComposersAsync(Context context, CancellationToken cancellationToken)
{
using var timeout = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
timeout.CancelAfter(TimeSpan.FromMinutes(5));

var recipes = new List<Recipe>();
var composers = _composerOrdering.Order(_composers);
Expand All @@ -81,31 +112,21 @@ public async Task<Book> ComposeAsync(
composerTypeName);

var stopWatch = Stopwatch.StartNew();
var createdRecipes = await composer.ComposeAsync(context, cancellationToken);
var createdRecipes = await composer.ComposeAsync(context, timeout.Token);
_logger.LogInformation(
"Composer {ComposerType} finished after {TotalSeconds}",
composerTypeName,
stopWatch.Elapsed.TotalSeconds);

var createdArtifacts = createdRecipes
.SelectMany(r => r.Artifacts ?? Artifact.Empty)
.SelectMany(r => r.Artifacts)
.ToList();

recipes.AddRange(createdRecipes);
context.AddArtifacts(createdArtifacts);
}

var book = new Book(
context.Ingredients,
recipes.ToArray());

if (_logger.IsEnabled(LogLevel.Trace))
{
var yaml = await _yaml.SerializeAsync(book, cancellationToken);
_logger.LogTrace("Create the following YAML {Book}", yaml);
}

return book;
return recipes;
}
}
}
Loading