这是indexloc提供的服务,不要输入任何密码
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
5dd3a49
wip
colombod Aug 23, 2019
67e7aa2
add test
colombod Aug 23, 2019
df3ee45
InterruptExecution command
colombod Aug 23, 2019
a6fe0a5
wip
colombod Aug 23, 2019
09ed47b
Merge branch 'master' into feature/interrupt_evaluation
colombod Aug 27, 2019
638ac34
format file
colombod Aug 27, 2019
d48a0e5
Merge branch 'master' into feature/interrupt_evaluation
colombod Aug 28, 2019
e7c2939
Merge branch 'master' into feature/incomplete_submission
colombod Aug 28, 2019
f6c2d72
Merge branch 'master' into feature/interrupt_evaluation
colombod Aug 28, 2019
07ba4d8
Merge branch 'master' into feature/split_value_events
colombod Aug 29, 2019
a65def9
split files
colombod Aug 29, 2019
9a4a50d
Merge branch 'master' into feature/default_enum_value
colombod Aug 29, 2019
02a5b28
Merge branch 'master' into feature/interrupt_evaluation
colombod Aug 30, 2019
3a740e4
rename command and event
colombod Aug 30, 2019
87224c3
wip
colombod Aug 30, 2019
c0f1246
Merge branch 'master' into feature/interrupt_evaluation
colombod Aug 30, 2019
bf5d857
Merge branch 'master' into feature/interrupt_evaluation
colombod Aug 30, 2019
b8730a5
rename command and event
colombod Sep 3, 2019
3759d15
add handler tests
colombod Sep 3, 2019
de5291d
wire handler and kernel
colombod Sep 3, 2019
7ed2d2f
is this the right thing to do???
colombod Sep 3, 2019
2effa6b
wip
colombod Sep 3, 2019
ec13fd3
Merge branch 'master' into feature/interrupt_evaluation
colombod Sep 3, 2019
47ba751
WIP
colombod Sep 3, 2019
4c32f76
Merge branch 'master' into feature/interrupt_evaluation
colombod Sep 3, 2019
16c1788
add locks
colombod Sep 3, 2019
d2d8562
fixed event publishing order
colombod Sep 3, 2019
17c32fe
Merge branch 'master' into feature/interrupt_evaluation
colombod Sep 3, 2019
7557550
separate files
colombod Sep 3, 2019
42c965d
code formatted
colombod Sep 3, 2019
1a3a1cc
rename command and event for current command cancellation
colombod Sep 3, 2019
3ab8f75
unify cancellation check on source
colombod Sep 3, 2019
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
4 changes: 1 addition & 3 deletions FSharpWorkspaceShim/FSharpWorkspaceShim.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@
<PropertyGroup Condition="$(TargetFramework.StartsWith('netstandard')) AND '$(OS)' == 'Windows_NT'">
<!-- the 2.1.503 F# compiler can produce PDBs that can't properly be converted, see https://github.com/Microsoft/visualfsharp/issues/5976 -->
<PublishWindowsPdb>false</PublishWindowsPdb>
</PropertyGroup>


</PropertyGroup>


<ItemGroup>
Expand Down
1 change: 0 additions & 1 deletion MLS.Agent/CommandLine/KernelServerCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using System.CommandLine;
using System.Threading.Tasks;
using Microsoft.DotNet.Interactive;
using WorkspaceServer.Kernel;

namespace MLS.Agent.CommandLine
{
Expand Down
9 changes: 9 additions & 0 deletions Microsoft.DotNet.Interactive.FSharp/FSharpKernel.fs
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,19 @@ type FSharpKernel() =
context.Publish(CodeSubmissionEvaluated(codeSubmission))
context.Complete()
}

let handleCancelCurrentCommand (cancelCurrentCommand: CancelCurrentCommand) (context: KernelInvocationContext) =
async {
let reply = CurrentCommandCancelled(cancelCurrentCommand)
context.Publish(reply)
context.Complete()
}

override __.HandleAsync(command: IKernelCommand, _context: KernelInvocationContext): Task =
async {
match command with
| :? SubmitCode as submitCode -> submitCode.Handler <- fun invocationContext -> (handleSubmitCode submitCode invocationContext) |> Async.StartAsTask :> Task
| :? CancelCurrentCommand as cancelCurrentCommand -> cancelCurrentCommand.Handler <- fun invocationContext -> (handleCancelCurrentCommand cancelCurrentCommand invocationContext) |> Async.StartAsTask :> Task
| _ -> ()
} |> Async.StartAsTask :> Task

Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using System.Linq;
using System.Threading.Tasks;
using FluentAssertions;
using Microsoft.DotNet.Interactive.Jupyter.Protocol;
using Recipes;
using WorkspaceServer.Kernel;
using Xunit;

namespace Microsoft.DotNet.Interactive.Jupyter.Tests
{
public class InterruptRequestHandlerTests
{
private readonly MessageSender _ioPubChannel;
private readonly MessageSender _serverChannel;
private readonly RecordingSocket _serverRecordingSocket;
private readonly RecordingSocket _ioRecordingSocket;
private readonly KernelStatus _kernelStatus;

public InterruptRequestHandlerTests()
{
var signatureValidator = new SignatureValidator("key", "HMACSHA256");
_serverRecordingSocket = new RecordingSocket();
_serverChannel = new MessageSender(_serverRecordingSocket, signatureValidator);
_ioRecordingSocket = new RecordingSocket();
_ioPubChannel = new MessageSender(_ioRecordingSocket, signatureValidator);
_kernelStatus = new KernelStatus();
}

[Fact]
public void cannot_handle_requests_that_are_not_InterruptRequest()
{
var kernel = new CSharpKernel();
var handler = new InterruptRequestHandler(kernel);
var request = Message.Create(new DisplayData(), null);
Func<Task> messageHandling = () => handler.Handle(new JupyterRequestContext(_serverChannel, _ioPubChannel, request, _kernelStatus));
messageHandling.Should().ThrowExactly<InvalidOperationException>();
}

[Fact]
public async Task handles_InterruptRequest()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we merge this one and the one below into one test as this one doesnt have any assertion ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it would throw if not using the right message

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. Thanks!

{
var kernel = new CSharpKernel();
var handler = new InterruptRequestHandler(kernel);
var request = Message.Create(new InterruptRequest(), null);
await handler.Handle(new JupyterRequestContext(_serverChannel, _ioPubChannel, request, _kernelStatus));
}

[Fact]
public async Task sends_InterruptReply()
{
var kernel = new CSharpKernel();
var handler = new InterruptRequestHandler(kernel);
var request = Message.Create(new InterruptRequest(), null);
await handler.Handle(new JupyterRequestContext(_serverChannel, _ioPubChannel, request, _kernelStatus));

_serverRecordingSocket.DecodedMessages.SingleOrDefault(message =>
message.Contains(MessageTypeValues.InterruptReply))
.Should()
.NotBeNullOrWhiteSpace();
}
}
}
64 changes: 64 additions & 0 deletions Microsoft.DotNet.Interactive.Jupyter/InterruptRequestHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.Reactive.Concurrency;
using System.Threading.Tasks;
using Microsoft.DotNet.Interactive.Commands;
using Microsoft.DotNet.Interactive.Events;
using Microsoft.DotNet.Interactive.Jupyter.Protocol;

namespace Microsoft.DotNet.Interactive.Jupyter
{
public class InterruptRequestHandler : RequestHandlerBase<InterruptRequest>
{

public InterruptRequestHandler(IKernel kernel, IScheduler scheduler = null)
: base(kernel, scheduler ?? CurrentThreadScheduler.Instance)
{

}

protected override void OnKernelEvent(IKernelEvent @event)
{
switch (@event)
{
case CurrentCommandCancelled kernelInterrupted:
OnExecutionInterrupted(kernelInterrupted);
break;
}
}

private void OnExecutionInterrupted(CurrentCommandCancelled currentCommandCancelled)
{
if (InFlightRequests.TryRemove(currentCommandCancelled.Command, out var openRequest))
{
// reply
var interruptReplyPayload = new InterruptReply();

// send to server
var interruptReply = Message.CreateResponse(
interruptReplyPayload,
openRequest.Context.Request);

openRequest.Context.ServerChannel.Send(interruptReply);
openRequest.Context.RequestHandlerStatus.SetAsIdle();
openRequest.Dispose();
}
}

public async Task Handle(JupyterRequestContext context)
{
var interruptRequest = GetJupyterRequest(context);

context.RequestHandlerStatus.SetAsBusy();

var command = new CancelCurrentCommand();

var openRequest = new InflightRequest(context, interruptRequest, 0);

InFlightRequests[command] = openRequest;

await Kernel.SendAsync(command);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,5 @@ private void OnKernelEvent(IKernelEvent @event, bool isComplete)
openRequest.Dispose();
}
}


}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ public class JupyterRequestContextHandler : ICommandHandler<JupyterRequestContex

private readonly ExecuteRequestHandler _executeHandler;
private readonly CompleteRequestHandler _completeHandler;
private IsCompleteRequestHandler _isCompleteHandler;
private readonly InterruptRequestHandler _interruptHandler;
private readonly IsCompleteRequestHandler _isCompleteHandler;

public JupyterRequestContextHandler(
IKernel kernel)
Expand All @@ -28,6 +29,7 @@ public JupyterRequestContextHandler(

_executeHandler = new ExecuteRequestHandler(kernel, scheduler);
_completeHandler = new CompleteRequestHandler(kernel, scheduler);
_interruptHandler = new InterruptRequestHandler(kernel, scheduler);
_isCompleteHandler = new IsCompleteRequestHandler(kernel, scheduler);

}
Expand All @@ -43,6 +45,9 @@ public async Task<ICommandDeliveryResult> Handle(
case MessageTypeValues.CompleteRequest:
await _completeHandler.Handle(delivery.Command);
break;
case MessageTypeValues.InterruptRequest:
await _interruptHandler.Handle(delivery.Command);
break;
}

return delivery.Complete();
Expand Down
11 changes: 11 additions & 0 deletions Microsoft.DotNet.Interactive.Jupyter/Protocol/InterruptReply.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace Microsoft.DotNet.Interactive.Jupyter.Protocol
{
[JupyterMessageType(MessageTypeValues.InterruptReply)]
public class InterruptReply : JupyterMessageContent
{

}
}
11 changes: 11 additions & 0 deletions Microsoft.DotNet.Interactive.Jupyter/Protocol/InterruptRequest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace Microsoft.DotNet.Interactive.Jupyter.Protocol
{
[JupyterMessageType(MessageTypeValues.InterruptRequest)]
public class InterruptRequest : JupyterMessageContent
{

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,5 +62,9 @@ public class MessageTypeValues
public const string CommInfoRequest = "comm_info_request";

public const string CommInfoReply = "comm_info_reply";

public const string InterruptRequest = "interrupt_request";

public const string InterruptReply = "interrupt_reply";
}
}
10 changes: 10 additions & 0 deletions Microsoft.DotNet.Interactive/Commands/CancelCurrentCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace Microsoft.DotNet.Interactive.Commands
{
public class CancelCurrentCommand : KernelCommandBase
{

}
}
2 changes: 0 additions & 2 deletions Microsoft.DotNet.Interactive/Commands/RequestCompletion.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;

Expand Down
1 change: 1 addition & 0 deletions Microsoft.DotNet.Interactive/Commands/SubmitCode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public SubmitCode(
public string Code { get; set; }

public string TargetKernelName { get; set; }

public SubmissionType SubmissionType { get; }

public override string ToString() => $"{base.ToString()}: {Code.TruncateForDisplay()}";
Expand Down
15 changes: 15 additions & 0 deletions Microsoft.DotNet.Interactive/Events/CurrentCommandCancelled.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using Microsoft.DotNet.Interactive.Commands;

namespace Microsoft.DotNet.Interactive.Events
{
public class CurrentCommandCancelled:KernelEventBase
{
public CurrentCommandCancelled(IKernelCommand command) : base(command)
{

}
}
}
1 change: 1 addition & 0 deletions Microsoft.DotNet.Interactive/KernelStreamClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public class KernelStreamClient
private readonly TextReader _input;
private readonly TextWriter _output;
private readonly CommandDeserializer _deserializer = new CommandDeserializer();

private readonly JsonSerializerSettings _jsonSerializerSettings = new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
Expand Down
22 changes: 22 additions & 0 deletions WorkspaceServer.Tests/Kernel/CSharpKernelTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,28 @@ public async Task it_produces_values_when_executing_Console_output()
new DisplayedValueProduced("value three", kernelCommand, new[] { new FormattedValue("text/plain", "value three"), }));
}

[Fact]
public async Task it_can_cancel_execution()
{
var kernel = CreateKernel();

var submitCodeCommand = new SubmitCode(@"System.Threading.Thread.Sleep(90000000);");
var codeSubmission = kernel.SendAsync(submitCodeCommand);
var interruptionCommand = new CancelCurrentCommand();
await kernel.SendAsync(interruptionCommand);
await codeSubmission;

KernelEvents
.ValuesOnly()
.Single(e => e is CurrentCommandCancelled);

KernelEvents
.ValuesOnly()
.OfType<CommandFailed>()
.Should()
.BeEquivalentTo(new CommandFailed(null, interruptionCommand, "Command cancelled"));
}

[Fact]
public async Task it_produces_a_final_value_if_the_code_expression_evaluates()
{
Expand Down
Loading