public async Task <IActionResult> SignatureHelp( [FromBody] WorkspaceRequest request, [FromHeader(Name = "Timeout")] string timeoutInMilliseconds = "15000") { if (Debugger.IsAttached && !(Clock.Current is VirtualClock)) { _disposables.Add(VirtualClock.Start()); } using (var operation = Log.OnEnterAndConfirmOnExit()) { operation.Info("Processing workspaceType {workspaceType}", request.Workspace.WorkspaceType); if (!int.TryParse(timeoutInMilliseconds, out var timeoutMs)) { return(BadRequest()); } var runTimeout = TimeSpan.FromMilliseconds(timeoutMs); var budget = new TimeBudget(runTimeout); var server = GetServerForWorkspace(request.Workspace); var result = await server.GetSignatureHelp(request, budget); budget.RecordEntry(); operation.Succeed(); return(Ok(result)); } }
public async Task <IActionResult> Compile( [FromBody] WorkspaceRequest request, [FromHeader(Name = "Timeout")] string timeoutInMilliseconds = "45000") { using (var operation = Log.OnEnterAndConfirmOnExit()) { var workspaceType = request.Workspace.WorkspaceType; operation.Info("Compiling workspaceType {workspaceType}", workspaceType); if (!int.TryParse(timeoutInMilliseconds, out var timeoutMs)) { return(BadRequest()); } if (string.Equals(workspaceType, "script", StringComparison.OrdinalIgnoreCase)) { return(BadRequest()); } var runTimeout = TimeSpan.FromMilliseconds(timeoutMs); var budget = new TimeBudget(runTimeout); var result = await _workspaceServer.Compile(request, budget); budget.RecordEntry(); operation.Succeed(); return(Ok(result)); } }
public async Task TimeBudget_ToString_describes_entries() { var budget = new TimeBudget(5.Seconds()); await Clock.Current.Wait(1.Seconds()); budget.RecordEntry("one"); await Clock.Current.Wait(10.Seconds()); budget.RecordEntry("two"); budget.ToString() .Should() .Be($"TimeBudget: 5 seconds{NewLine} ✔ one @ 1.00 seconds{NewLine} ❌ two @ 11.00 seconds (budget of 5 seconds exceeded by 6.00 seconds.)"); }
public async Task TimeBudget_ToString_truncates_durations_for_readability() { var budget = new TimeBudget(5.Seconds()); await Clock.Current.Wait(TimeSpan.FromMilliseconds(1010.235)); budget.RecordEntry("one"); await Clock.Current.Wait(10.Seconds()); await Clock.Current.Wait(TimeSpan.FromMilliseconds(1100.052)); budget.RecordEntry("two"); budget.ToString() .Should() .Be($"TimeBudget: 5 seconds{NewLine} ✔ one @ 1.01 seconds{NewLine} ❌ two @ 12.11 seconds (budget of 5 seconds exceeded by 7.11 seconds.)"); }
public async Task TimeBudget_can_be_used_to_mark_down_time_spent_in_an_operation() { var budget = new TimeBudget(15.Seconds()); await Clock.Current.Wait(5.Seconds()); budget.RecordEntry("one"); await Clock.Current.Wait(8.Seconds()); budget.RecordEntry("two"); await Clock.Current.Wait(13.Seconds()); budget.RecordEntry("three"); budget.Entries .Select(e => e.ToString()) .Should() .BeEquivalentTo( "✔ one @ 5.00 seconds", "✔ two @ 13.00 seconds", "❌ three @ 26.00 seconds (budget of 15 seconds exceeded by 11.00 seconds.)"); }
public async Task When_time_budget_expires_in_user_code_then_a_417_is_returned() { using (VirtualClock.Start()) { var budget = new TimeBudget(10.Seconds()); await Clock.Current.Wait(11.Seconds()); budget.RecordEntry(ScriptingWorkspaceServer.UserCodeCompletedBudgetEntryName); var exception = new BudgetExceededException(budget); exception.ToHttpStatusCode().Should().Be(417); } }
public async Task TimeBudget_ToString_does_not_change_when_time_passes_but_no_new_entries_are_added() { var budget = new TimeBudget(2.Seconds()); await Clock.Current.Wait(1.Seconds()); budget.RecordEntry(); var stringAt1Second = budget.ToString(); await Clock.Current.Wait(2.Seconds()); var stringAt1Minute = budget.ToString(); stringAt1Minute.Should().Be(stringAt1Second); }
public async Task Adding_entries_after_cancellation_captures_elapsed_duration_relative_to_budget_start() { var budget = new TimeBudget(3.Seconds()); await Clock.Current.Wait(2.Seconds()); budget.Cancel(); await Clock.Current.Wait(2.Seconds()); budget.RecordEntry(); var lastEntry = budget.Entries.Last(); lastEntry.BudgetWasExceeded.Should().BeTrue(); lastEntry.ElapsedDuration.Should().Be(4.Seconds()); }
public async Task TimeBudget_throws_an_informative_exception_if_no_time_is_left() { var budget = new TimeBudget(5.Seconds()); await Clock.Current.Wait(1.Seconds()); budget.RecordEntry("one"); await Clock.Current.Wait(10.Seconds()); Action action = () => budget.RecordEntryAndThrowIfBudgetExceeded("two"); action.ShouldThrow <BudgetExceededException>() .Which .Message .Should() .Be($"Budget of 5 seconds exceeded.{NewLine}" + $" ✔ one @ 1.00 seconds{NewLine}" + $" ❌ two @ 11.00 seconds (budget of 5 seconds exceeded by 6.00 seconds.)"); }
public async Task <IActionResult> Completion( [FromBody] WorkspaceRequest request, [FromHeader(Name = "Timeout")] string timeoutInMilliseconds = "15000") { using (var operation = Log.OnEnterAndConfirmOnExit()) { operation.Info("Processing workspaceType {workspaceType}", request.Workspace.WorkspaceType); if (!int.TryParse(timeoutInMilliseconds, out var timeoutMs)) { return(BadRequest()); } var runTimeout = TimeSpan.FromMilliseconds(timeoutMs); var budget = new TimeBudget(runTimeout); var server = GetServerForWorkspace(request.Workspace); var result = await server.GetCompletionList(request, budget); budget.RecordEntry(); operation.Succeed(); return(Ok(result)); } }
public async Task <IActionResult> Run( [FromBody] WorkspaceRequest request, [FromHeader(Name = "Timeout")] string timeoutInMilliseconds = "45000") { if (_options.IsLanguageService) { return(NotFound()); } using (var operation = Log.OnEnterAndConfirmOnExit()) { var workspaceType = request.Workspace.WorkspaceType; operation.Info("Processing workspaceType {workspaceType}", workspaceType); if (!int.TryParse(timeoutInMilliseconds, out var timeoutMs)) { return(BadRequest()); } RunResult result; var runTimeout = TimeSpan.FromMilliseconds(timeoutMs); var budget = new TimeBudget(runTimeout); if (string.Equals(workspaceType, "script", StringComparison.OrdinalIgnoreCase)) { var server = new ScriptingWorkspaceServer(); result = await server.Run( request, budget); } else { using (result = await _workspaceServer.Run(request, budget)) { _disposables.Add(result); if (result.Succeeded && request.HttpRequest != null) { var webServer = result.GetFeature <WebServer>(); if (webServer != null) { var response = await webServer.SendAsync( request.HttpRequest.ToHttpRequestMessage()) .CancelIfExceeds(budget); result = new RunResult( true, await response.ToDisplayString()); } } } } budget.RecordEntry(); operation.Succeed(); return(Ok(result)); } }