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

Switch client/server to anonymous #1775

Open
wants to merge 33 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
58d228b
Scaffolding server: use pipes
yecril71pl Dec 31, 2021
6ac1bd5
remember the ports
yecril71pl Dec 31, 2021
54039c0
pass both ports to the client
yecril71pl Dec 31, 2021
11f01f0
wait for the server task
yecril71pl Dec 31, 2021
c881f17
using System.Threading.Tasks
yecril71pl Dec 31, 2021
158ecd3
Scaffolding client: use pipes
yecril71pl Dec 31, 2021
66742a2
port is a string now
yecril71pl Dec 31, 2021
4d7d7ee
ScaffoldingClient.Connect is synchronous now
yecril71pl Dec 31, 2021
324de6f
typo fix
yecril71pl Dec 31, 2021
a60333a
typo fix
yecril71pl Dec 31, 2021
5ea7a51
using System.Threading.Tasks
yecril71pl Dec 31, 2021
99e82cf
HandleInheritability.Inheritable
yecril71pl Dec 31, 2021
32c2bca
Command: split Execute to Start and Wait
yecril71pl Dec 31, 2021
5685e65
no empty statements
yecril71pl Dec 31, 2021
0a5459e
no empty statements
yecril71pl Dec 31, 2021
972bd04
typo fix
yecril71pl Dec 31, 2021
01ef781
typo fix
yecril71pl Dec 31, 2021
26fa451
no variable for EndOfStreamException
yecril71pl Dec 31, 2021
a4d8947
await this._reader.ReadStringAsync
yecril71pl Dec 31, 2021
c056f9e
Too early for server.Accept() in StartServer
yecril71pl Dec 31, 2021
43026d9
oops, there is no ReadStringAsync
yecril71pl Dec 31, 2021
99958ac
await app.OnExecute
yecril71pl Dec 31, 2021
3fdfe46
static async Task Execute
yecril71pl Dec 31, 2021
f1662a0
rv changes
yecril71pl Dec 31, 2021
437460e
await executor.ExecuteAsync
yecril71pl Dec 31, 2021
df8f513
CodeGenCommand: await actionInvoker.ExecuteAsync
yecril71pl Dec 31, 2021
69a862e
using System.Threading.Tasks
yecril71pl Dec 31, 2021
0f605f9
async Task ActionInvoker.ExecuteAsync
yecril71pl Dec 31, 2021
8044e23
await actionInvoker.ExecuteAsync
yecril71pl Dec 31, 2021
f6092b7
await Assert.ThrowsAsync
yecril71pl Dec 31, 2021
5b76661
no return actionInvoker.ExecuteAsync
yecril71pl Dec 31, 2021
5593c5f
CodeGenCommandExecutor.ExecuteAsync
yecril71pl Dec 31, 2021
92e174f
using System.Threading.Tasks
yecril71pl Dec 31, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/Scaffolding/VS.Web.CG.Core/ActionInvoker.cs
Expand Up @@ -27,7 +27,7 @@ public ActionDescriptor ActionDescriptor
private set;
}

public void Execute(string[] args)
public async Task ExecuteAsync(string[] args)
{
var app = new CommandLineApplication();

Expand All @@ -37,7 +37,8 @@ public void Execute(string[] args)
BuildCommandLine(c);
});

app.Execute(args);
// until #1760
await Task.Run(() => app.Execute(args));
}

internal void BuildCommandLine(CommandLineApplication command)
Expand Down
5 changes: 3 additions & 2 deletions src/Scaffolding/VS.Web.CG.Design/CodeGenCommandExecutor.cs
Expand Up @@ -4,6 +4,7 @@
using System;
using System.IO;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.DotNet.Scaffolding.Shared;
using Microsoft.DotNet.Scaffolding.Shared.ProjectModel;
Expand Down Expand Up @@ -45,7 +46,7 @@ public CodeGenCommandExecutor(IProjectContext projectInformation, string[] codeG
_isSimulationMode = isSimulationMode;
}

public int Execute(Action<IEnumerable<FileSystemChangeInformation>> simModeAction = null)
public async Task<int> ExecuteAsync(Action<IEnumerable<FileSystemChangeInformation>> simModeAction = null)
{
var serviceProvider = new ServiceProvider();
AddFrameworkServices(serviceProvider, _projectInformation);
Expand All @@ -54,7 +55,7 @@ public int Execute(Action<IEnumerable<FileSystemChangeInformation>> simModeActio

try
{
codeGenCommand.Execute(_codeGenArguments);
await codeGenCommand.ExecuteAsync(_codeGenArguments);

if (_isSimulationMode && simModeAction != null)
{
Expand Down
6 changes: 3 additions & 3 deletions src/Scaffolding/VS.Web.CG.Design/Program.cs
Expand Up @@ -67,8 +67,8 @@ private static void Execute(string[] args, ConsoleLogger logger)
project = Path.GetFullPath(project);
var configuration = appConfiguration.Value();

var portNumber = int.Parse(port.Value());
using (var client = await ScaffoldingClient.Connect(portNumber, logger))
var portNumber = port.Value();
using (var client = ScaffoldingClient.Connect(portNumber, logger))
{
var messageOrchestrator = new MessageOrchestrator(client, logger);
var projectInformation = messageOrchestrator.GetProjectInformation();
Expand All @@ -83,7 +83,7 @@ private static void Execute(string[] args, ConsoleLogger logger)
logger,
isSimulationMode);

exitCode = executor.Execute((changes) => messageOrchestrator.SendFileSystemChangeInformation(changes));
exitCode = await executor.ExecuteAsync((changes) => messageOrchestrator.SendFileSystemChangeInformation(changes));

messageOrchestrator.SendScaffoldingCompletedMessage();
}
Expand Down
42 changes: 18 additions & 24 deletions src/Scaffolding/VS.Web.CG.Design/ScaffoldingClient.cs
Expand Up @@ -6,8 +6,7 @@
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.IO.Pipes;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.DotNet.Scaffolding.Shared;
Expand All @@ -21,8 +20,7 @@ public class ScaffoldingClient : IDisposable, IMessageSender
{
private static readonly string HostId = typeof(ScaffoldingClient).GetTypeInfo().Assembly.GetName().Name;

private int _port;
private TcpClient _client;
private string _port;
private BinaryWriter _writer;
private BinaryReader _reader;

Expand All @@ -34,39 +32,35 @@ public class ScaffoldingClient : IDisposable, IMessageSender

public int CurrentProtocolVersion => 1;

public static async Task<ScaffoldingClient> Connect(int port, ILogger logger)
public static ScaffoldingClient Connect(string port, ILogger logger)
{
TcpClient client = new TcpClient();
await client.ConnectAsync(IPAddress.Loopback, port);

return new ScaffoldingClient(client, logger, port);
return new ScaffoldingClient(logger, port);
}

public ScaffoldingClient(TcpClient client, ILogger logger, int port)
public ScaffoldingClient(ILogger logger, string port)
{
if (logger == null)
{
throw new ArgumentNullException(nameof(logger));
}
_client = client;
_logger = logger;
_port = port;
this._logger = logger;
this._port = port;
Init();
}

public void Init()
{
if (_client.Connected)
{
var stream = _client.GetStream();
_writer = new BinaryWriter(stream);
_reader = new BinaryReader(stream);
return;
}
else
{
throw new InvalidOperationException(string.Format(Resources.ConnectToServerError, _port));
}
var ports = this._port.Split(':');
if (0X2 != ports.Length) throw new ArgumentException("port", "Expected input:output");
var stream = new AnonymousPipeClientStream(PipeDirection.Out, ports[0X0]);
try {
this._writer = new BinaryWriter(stream);
stream = null;
} finally { using (stream) {} }
try {
this._reader = new BinaryReader(stream = new AnonymousPipeClientStream(PipeDirection.In, ports[0X1]));
stream = null;
} finally { using (stream) {} }
}

[SuppressMessage("supressing re-throw exception", "CA2200")]
Expand Down
5 changes: 3 additions & 2 deletions src/Scaffolding/VS.Web.CG/CodeGenCommand.cs
Expand Up @@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.DotNet.Scaffolding.Shared;

namespace Microsoft.VisualStudio.Web.CodeGeneration
Expand All @@ -30,7 +31,7 @@ public CodeGenCommand(ILogger logger, ICodeGeneratorLocator locator)
_logger = logger;
}

public int Execute(string [] args)
public async Task<int> ExecuteAsync(string [] args)
{
if (args == null || args.Length == 0 || IsHelpArgument(args[0]))
{
Expand All @@ -46,7 +47,7 @@ public int Execute(string [] args)
var actionInvoker = new ActionInvoker(generatorDescriptor.CodeGeneratorAction);

_logger.LogMessage("Running the generator '" + codeGeneratorName + "'...");
actionInvoker.Execute(args);
await actionInvoker.ExecuteAsync(args);
}
catch (Exception ex)
{
Expand Down
40 changes: 26 additions & 14 deletions src/Shared/Microsoft.DotNet.Scaffolding.Shared/Cli.Utils/Command.cs
Expand Up @@ -63,31 +63,43 @@ public Command WithEnvironmentVariable(string name, string value)
return this;
}

public CommandResult Execute()
public Command Start()
{
ThrowIfRunning();
_running = true;
_process.EnableRaisingEvents = true;
var process = this._process;
var psi = process.StartInfo;

this.ThrowIfRunning();
this._running = true;
process.EnableRaisingEvents = true;

process.OutputDataReceived += OnOutputReceived;
process.ErrorDataReceived += OnErrorReceived;

process.Start();
if (psi.RedirectStandardOutput) process.BeginOutputReadLine();
if (psi.RedirectStandardError) process.BeginErrorReadLine();

_process.OutputDataReceived += OnOutputReceived;
_process.ErrorDataReceived += OnErrorReceived;
return this;
}

_process.Start();
_process.BeginOutputReadLine();
_process.BeginErrorReadLine();
public CommandResult WaitForExit()
{
var process = this._process;

_process.WaitForExit();
process.WaitForExit();

var exitCode = _process.ExitCode;
var exitCode = process.ExitCode;

_process.OutputDataReceived -= OnOutputReceived;
_process.ErrorDataReceived -= OnErrorReceived;
process.OutputDataReceived -= OnOutputReceived;
process.ErrorDataReceived -= OnErrorReceived;

return new CommandResult(
_process.StartInfo,
process.StartInfo,
exitCode);
}

public CommandResult Execute() => this.Start().WaitForExit();

private void OnErrorReceived(object sender, DataReceivedEventArgs e)
{
if (e.Data != null)
Expand Down
13 changes: 7 additions & 6 deletions test/Scaffolding/VS.Web.CG.Core.Test/ActionInvokerTests.cs
Expand Up @@ -3,6 +3,7 @@

using System;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Moq;
using Xunit;
Expand All @@ -12,7 +13,7 @@ namespace Microsoft.VisualStudio.Web.CodeGeneration.Core.Test
public class ActionInvokerTests
{
[Fact]
public void ActionInvoker_Invokes_GenerateCode_Method_With_Right_ActionModel()
public async Task ActionInvoker_Invokes_GenerateCode_Method_With_Right_ActionModel()
{
//Arrange
bool methodCalled = false;
Expand Down Expand Up @@ -41,7 +42,7 @@ public void ActionInvoker_Invokes_GenerateCode_Method_With_Right_ActionModel()
var actionInvoker = new ActionInvoker(actionDescriptor);

//Act
actionInvoker.Execute("CodeGeneratorSample StringValuePassed --BoolProperty".Split(' '));
await actionInvoker.ExecuteAsync("CodeGeneratorSample StringValuePassed --BoolProperty".Split(' '));

//Assert
Assert.True(methodCalled);
Expand All @@ -51,7 +52,7 @@ public void ActionInvoker_Invokes_GenerateCode_Method_With_Right_ActionModel()
}

[Fact]
public void ActionInvoker_Throws_With_Inner_Exception()
public async Task ActionInvoker_Throws_With_Inner_Exception()
{
//Arrange
const string NOT_IMPLEMENTED_MESSAGE = "This action is intentionally not implemented.";
Expand All @@ -77,9 +78,9 @@ public void ActionInvoker_Throws_With_Inner_Exception()
var actionInvoker = new ActionInvoker(actionDescriptor);

//Act
var ex =
Assert.Throws<InvalidOperationException>(
() => actionInvoker.Execute("CodeGeneratorSample StringValuePassed --BoolProperty".Split(' ')));
var ex = await
Assert.ThrowsAsync<InvalidOperationException>(
async () => await actionInvoker.ExecuteAsync("CodeGeneratorSample StringValuePassed --BoolProperty".Split(' ')));

//Assert
Assert.Equal(NOT_IMPLEMENTED_MESSAGE, ex.InnerException.Message);
Expand Down
29 changes: 15 additions & 14 deletions tools/dotnet-aspnet-codegenerator/Program.cs
Expand Up @@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
using System.Linq;
using System.Reflection;
using Microsoft.Extensions.Internal;
Expand Down Expand Up @@ -184,29 +185,30 @@ internal int Execute(string[] args, bool isNoBuild)
}

// Start server
var server = StartServer(logger, context);
try
using (var server = StartServer(logger, context))
{
// The command must be started before the server starts accepting
var command = CreateDipatchCommand(
context,
args,
buildBasePath,
configuration,
tfmMoniker,
shortFramework,
server);

var exitCode = command
server)
.OnErrorLine(e => logger.LogMessage(e, LogMessageLevel.Error))
.OnOutputLine(e => logger.LogMessage(e, LogMessageLevel.Information))
.Execute()
.ExitCode;
.Start();

return exitCode;
}
finally
{
server.WaitForExit(TimeSpan.FromSeconds(ServerWaitTimeForExit));
using (var serverTask = server.Accept()) {
if (default == serverTask.Status) serverTask.Start();
try {
return command.WaitForExit().ExitCode;
}
finally {
serverTask.Wait(TimeSpan.FromSeconds(ServerWaitTimeForExit));
}
}
}
}

Expand Down Expand Up @@ -256,7 +258,7 @@ internal int Execute(string[] args, bool isNoBuild)
var dependencyArgs = ToolCommandLineHelper.GetProjectDependencyCommandArgs(
args,
shortFramework,
server.Port.ToString());
string.Join(':', server.Port));

return DotnetToolDispatcher.CreateDispatchCommand(
runtimeConfigPath: runtimeConfigPath,
Expand Down Expand Up @@ -341,7 +343,6 @@ private ScaffoldingServer StartServer(ILogger logger, IProjectContext projectInf
server = ScaffoldingServer.Listen(logger);
server.AddHandler(new ProjectInformationMessageHandler(projectInformation, logger));
server.AddHandler(new FileSystemChangeMessageHandler(logger));
server.Accept();
return server;
}
}
Expand Down