Browse Source

Couple of clean up from PR feedback (#242)

davidfowl/dependencies
David Fowler 7 years ago
committed by GitHub
parent
commit
77e01e4b91
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      src/Microsoft.Tye.Hosting/DockerRunner.cs
  2. 8
      src/Microsoft.Tye.Hosting/ProcessRunner.cs
  3. 50
      src/Microsoft.Tye.Hosting/ReplicaRegistry.cs
  4. 2
      src/Microsoft.Tye.Hosting/TyeHost.cs
  5. 2
      test/E2ETest/TestHelpers.cs
  6. 8
      test/E2ETest/TestOutputLogEventSink.cs
  7. 20
      test/E2ETest/TyePurgeTests.cs
  8. 42
      test/E2ETest/TyeRunTests.cs

8
src/Microsoft.Tye.Hosting/DockerRunner.cs

@ -15,7 +15,7 @@ namespace Microsoft.Tye.Hosting
{ {
public class DockerRunner : IApplicationProcessor public class DockerRunner : IApplicationProcessor
{ {
private const string DOCKER_REPLICA_STORE = "docker"; private const string DockerReplicaStore = "docker";
private static readonly TimeSpan DockerStopTimeout = TimeSpan.FromSeconds(30); private static readonly TimeSpan DockerStopTimeout = TimeSpan.FromSeconds(30);
private readonly ILogger _logger; private readonly ILogger _logger;
@ -301,7 +301,7 @@ namespace Microsoft.Tye.Hosting
private async Task PurgeFromPreviousRun() private async Task PurgeFromPreviousRun()
{ {
var dockerReplicas = await _replicaRegistry.GetEvents(DOCKER_REPLICA_STORE); var dockerReplicas = await _replicaRegistry.GetEvents(DockerReplicaStore);
foreach (var replica in dockerReplicas) foreach (var replica in dockerReplicas)
{ {
var container = replica["container"]; var container = replica["container"];
@ -309,12 +309,12 @@ namespace Microsoft.Tye.Hosting
_logger.LogInformation("removed contaienr {container} from previous run", container); _logger.LogInformation("removed contaienr {container} from previous run", container);
} }
_replicaRegistry.DeleteStore(DOCKER_REPLICA_STORE); _replicaRegistry.DeleteStore(DockerReplicaStore);
} }
private void WriteReplicaToStore(string container) private void WriteReplicaToStore(string container)
{ {
_replicaRegistry.WriteReplicaEvent(DOCKER_REPLICA_STORE, new Dictionary<string, string>() _replicaRegistry.WriteReplicaEvent(DockerReplicaStore, new Dictionary<string, string>()
{ {
["container"] = container ["container"] = container
}); });

8
src/Microsoft.Tye.Hosting/ProcessRunner.cs

@ -17,7 +17,7 @@ namespace Microsoft.Tye.Hosting
{ {
public class ProcessRunner : IApplicationProcessor public class ProcessRunner : IApplicationProcessor
{ {
private const string PROCESS_REPLICA_STORE = "process"; private const string ProcessReplicaStore = "process";
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly ProcessRunnerOptions _options; private readonly ProcessRunnerOptions _options;
@ -309,7 +309,7 @@ namespace Microsoft.Tye.Hosting
private async Task PurgeFromPreviousRun() private async Task PurgeFromPreviousRun()
{ {
var processReplicas = await _replicaRegistry.GetEvents(PROCESS_REPLICA_STORE); var processReplicas = await _replicaRegistry.GetEvents(ProcessReplicaStore);
foreach (var replica in processReplicas) foreach (var replica in processReplicas)
{ {
if (int.TryParse(replica["pid"], out var pid)) if (int.TryParse(replica["pid"], out var pid))
@ -319,12 +319,12 @@ namespace Microsoft.Tye.Hosting
} }
} }
_replicaRegistry.DeleteStore(PROCESS_REPLICA_STORE); _replicaRegistry.DeleteStore(ProcessReplicaStore);
} }
private void WriteReplicaToStore(string pid) private void WriteReplicaToStore(string pid)
{ {
_replicaRegistry.WriteReplicaEvent(PROCESS_REPLICA_STORE, new Dictionary<string, string>() _replicaRegistry.WriteReplicaEvent(ProcessReplicaStore, new Dictionary<string, string>()
{ {
["pid"] = pid ["pid"] = pid
}); });

50
src/Microsoft.Tye.Hosting/ReplicaRegistry.cs

@ -3,56 +3,52 @@
// See the LICENSE file in the project root for more information. // See the LICENSE file in the project root for more information.
using System; using System;
using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text.Json; using System.Text.Json;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Tye.Hosting.Model;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using System.Threading;
using System.Collections.Concurrent;
namespace Microsoft.Tye.Hosting namespace Microsoft.Tye.Hosting
{ {
public class ReplicaRegistry : IDisposable public class ReplicaRegistry : IDisposable
{ {
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly ConcurrentDictionary<string, SemaphoreSlim> _fileWriteSemaphores; private readonly ConcurrentDictionary<string, object> _fileWriteLocks;
private readonly string _tyeFolderPath; private readonly string _tyeFolderPath;
public ReplicaRegistry(Model.Application application, ILogger logger) public ReplicaRegistry(string directory, ILogger logger)
{ {
_logger = logger; _logger = logger;
_fileWriteSemaphores = new ConcurrentDictionary<string, SemaphoreSlim>(); _fileWriteLocks = new ConcurrentDictionary<string, object>();
_tyeFolderPath = Path.Join(Path.GetDirectoryName(application.Source), ".tye"); _tyeFolderPath = Path.Join(directory, ".tye");
}
public bool WriteReplicaEvent(string storeName, IDictionary<string, string> replicaRecord)
{
if (!Directory.Exists(_tyeFolderPath)) if (!Directory.Exists(_tyeFolderPath))
{ {
Directory.CreateDirectory(_tyeFolderPath); Directory.CreateDirectory(_tyeFolderPath);
} }
}
public bool WriteReplicaEvent(string storeName, IDictionary<string, string> replicaRecord)
{
var filePath = Path.Join(_tyeFolderPath, GetStoreFile(storeName)); var filePath = Path.Join(_tyeFolderPath, GetStoreFile(storeName));
var contents = JsonSerializer.Serialize(replicaRecord, new JsonSerializerOptions { WriteIndented = false }); var contents = JsonSerializer.Serialize(replicaRecord, new JsonSerializerOptions { WriteIndented = false });
var semaphore = GetSempahoreForStore(storeName); var lockObj = GetLockForStore(storeName);
semaphore.Wait(); lock (lockObj)
try
{ {
File.AppendAllText(filePath, contents + Environment.NewLine); try
return true; {
} File.AppendAllText(filePath, contents + Environment.NewLine);
catch (DirectoryNotFoundException ex) return true;
{ }
_logger.LogWarning(ex, "tye folder is not found. file: {file}", filePath); catch (DirectoryNotFoundException ex)
return false; {
} _logger.LogWarning(ex, "tye folder is not found. file: {file}", filePath);
finally return false;
{ }
semaphore.Release();
} }
} }
@ -75,7 +71,7 @@ namespace Microsoft.Tye.Hosting
public async ValueTask<IList<IDictionary<string, string>>> GetEvents(string storeName) public async ValueTask<IList<IDictionary<string, string>>> GetEvents(string storeName)
{ {
var filePath = Path.Join(_tyeFolderPath, GetStoreFile(storeName)); var filePath = Path.Join(_tyeFolderPath, GetStoreFile(storeName));
if (!File.Exists(filePath)) if (!File.Exists(filePath))
{ {
return Array.Empty<IDictionary<string, string>>(); return Array.Empty<IDictionary<string, string>>();
@ -89,9 +85,9 @@ namespace Microsoft.Tye.Hosting
.ToList(); .ToList();
} }
private SemaphoreSlim GetSempahoreForStore(string storeName) private object GetLockForStore(string storeName)
{ {
return _fileWriteSemaphores.GetOrAdd(storeName, _ => new SemaphoreSlim(1, 1)); return _fileWriteLocks.GetOrAdd(storeName, _ => new object());
} }
private string GetStoreFile(string storeName) => $"{storeName}_store"; private string GetStoreFile(string storeName) => $"{storeName}_store";

2
src/Microsoft.Tye.Hosting/TyeHost.cs

@ -83,7 +83,7 @@ namespace Microsoft.Tye.Hosting
var configuration = app.Configuration; var configuration = app.Configuration;
_replicaRegistry = new ReplicaRegistry(_application, _logger); _replicaRegistry = new ReplicaRegistry(_application.ContextDirectory, _logger);
_processor = CreateApplicationProcessor(_replicaRegistry, _args, _servicesToDebug, _logger, configuration); _processor = CreateApplicationProcessor(_replicaRegistry, _args, _servicesToDebug, _logger, configuration);

2
test/E2ETest/TestHelpers.cs

@ -128,7 +128,7 @@ namespace E2ETest
static async Task Purge(TyeHost host) static async Task Purge(TyeHost host)
{ {
var logger = host.DashboardWebApplication!.Logger; var logger = host.DashboardWebApplication!.Logger;
var replicaRegistry = new ReplicaRegistry(host.Application, logger); var replicaRegistry = new ReplicaRegistry(host.Application.ContextDirectory, logger);
var processRunner = new ProcessRunner(logger, replicaRegistry, new ProcessRunnerOptions()); var processRunner = new ProcessRunner(logger, replicaRegistry, new ProcessRunnerOptions());
var dockerRunner = new DockerRunner(logger, replicaRegistry); var dockerRunner = new DockerRunner(logger, replicaRegistry);

8
test/E2ETest/TestOutputLogEventSink.cs

@ -8,11 +8,11 @@ namespace E2ETest
{ {
public class TestOutputLogEventSink : ILogEventSink, IConsole, IStandardStreamWriter public class TestOutputLogEventSink : ILogEventSink, IConsole, IStandardStreamWriter
{ {
private readonly ITestOutputHelper output; private readonly ITestOutputHelper _output;
public TestOutputLogEventSink(ITestOutputHelper output) public TestOutputLogEventSink(ITestOutputHelper output)
{ {
this.output = output; _output = output;
} }
public IStandardStreamWriter Out => this; public IStandardStreamWriter Out => this;
@ -27,13 +27,13 @@ namespace E2ETest
public void Emit(LogEvent logEvent) public void Emit(LogEvent logEvent)
{ {
output.WriteLine(logEvent.RenderMessage()); _output.WriteLine(logEvent.RenderMessage());
} }
public void Write(string value) public void Write(string value)
{ {
// our usage of IConsole includes newlines, so strip them out. // our usage of IConsole includes newlines, so strip them out.
output.WriteLine(value.TrimEnd('\r', '\n')); _output.WriteLine(value.TrimEnd('\r', '\n'));
} }
} }
} }

20
test/E2ETest/TyePurgeTests.cs

@ -21,13 +21,13 @@ namespace E2ETest
{ {
public class TyePurgeTests public class TyePurgeTests
{ {
private readonly ITestOutputHelper output; private readonly ITestOutputHelper _output;
private readonly TestOutputLogEventSink sink; private readonly TestOutputLogEventSink _sink;
public TyePurgeTests(ITestOutputHelper output) public TyePurgeTests(ITestOutputHelper output)
{ {
this.output = output; _output = output;
sink = new TestOutputLogEventSink(output); _sink = new TestOutputLogEventSink(output);
} }
[Fact] [Fact]
@ -39,11 +39,11 @@ namespace E2ETest
var projectFile = new FileInfo(Path.Combine(tempDirectory.DirectoryPath, "tye.yaml")); var projectFile = new FileInfo(Path.Combine(tempDirectory.DirectoryPath, "tye.yaml"));
var tyeDir = new DirectoryInfo(Path.Combine(tempDirectory.DirectoryPath, ".tye")); var tyeDir = new DirectoryInfo(Path.Combine(tempDirectory.DirectoryPath, ".tye"));
var outputContext = new OutputContext(sink, Verbosity.Debug); var outputContext = new OutputContext(_sink, Verbosity.Debug);
var application = await ApplicationFactory.CreateAsync(outputContext, projectFile); var application = await ApplicationFactory.CreateAsync(outputContext, projectFile);
var host = new TyeHost(application.ToHostingApplication(), Array.Empty<string>()) var host = new TyeHost(application.ToHostingApplication(), Array.Empty<string>())
{ {
Sink = sink, Sink = _sink,
}; };
try try
@ -84,11 +84,11 @@ namespace E2ETest
var projectFile = new FileInfo(Path.Combine(tempDirectory.DirectoryPath, "tye.yaml")); var projectFile = new FileInfo(Path.Combine(tempDirectory.DirectoryPath, "tye.yaml"));
var tyeDir = new DirectoryInfo(Path.Combine(tempDirectory.DirectoryPath, ".tye")); var tyeDir = new DirectoryInfo(Path.Combine(tempDirectory.DirectoryPath, ".tye"));
var outputContext = new OutputContext(sink, Verbosity.Debug); var outputContext = new OutputContext(_sink, Verbosity.Debug);
var application = await ApplicationFactory.CreateAsync(outputContext, projectFile); var application = await ApplicationFactory.CreateAsync(outputContext, projectFile);
var host = new TyeHost(application.ToHostingApplication(), Array.Empty<string>()) var host = new TyeHost(application.ToHostingApplication(), Array.Empty<string>())
{ {
Sink = sink, Sink = _sink,
}; };
try try
@ -101,7 +101,7 @@ namespace E2ETest
Assert.True(Directory.Exists(tyeDir.FullName)); Assert.True(Directory.Exists(tyeDir.FullName));
Assert.Subset(new HashSet<int>(GetAllPids()), new HashSet<int>(pids)); Assert.Subset(new HashSet<int>(GetAllPids()), new HashSet<int>(pids));
Assert.Subset(new HashSet<string>(await DockerAssert.GetRunningContainersIdsAsync(output)), Assert.Subset(new HashSet<string>(await DockerAssert.GetRunningContainersIdsAsync(_output)),
new HashSet<string>(containers)); new HashSet<string>(containers));
await TestHelpers.PurgeHostAndWaitForGivenReplicasToStop(host, await TestHelpers.PurgeHostAndWaitForGivenReplicasToStop(host,
@ -110,7 +110,7 @@ namespace E2ETest
var runningPids = new HashSet<int>(GetAllPids()); var runningPids = new HashSet<int>(GetAllPids());
Assert.True(pids.All(pid => !runningPids.Contains(pid))); Assert.True(pids.All(pid => !runningPids.Contains(pid)));
var runningContainers = var runningContainers =
new HashSet<string>(await DockerAssert.GetRunningContainersIdsAsync(output)); new HashSet<string>(await DockerAssert.GetRunningContainersIdsAsync(_output));
Assert.True(containers.All(c => !runningContainers.Contains(c))); Assert.True(containers.All(c => !runningContainers.Contains(c)));
} }
finally finally

42
test/E2ETest/TyeRunTests.cs

@ -22,14 +22,14 @@ namespace E2ETest
{ {
public class TyeRunTests public class TyeRunTests
{ {
private readonly ITestOutputHelper output; private readonly ITestOutputHelper _output;
private readonly TestOutputLogEventSink sink; private readonly TestOutputLogEventSink _sink;
private readonly JsonSerializerOptions _options; private readonly JsonSerializerOptions _options;
public TyeRunTests(ITestOutputHelper output) public TyeRunTests(ITestOutputHelper output)
{ {
this.output = output; _output = output;
sink = new TestOutputLogEventSink(output); _sink = new TestOutputLogEventSink(output);
_options = new JsonSerializerOptions() _options = new JsonSerializerOptions()
{ {
@ -49,11 +49,11 @@ namespace E2ETest
DirectoryCopy.Copy(projectDirectory.FullName, tempDirectory.DirectoryPath); DirectoryCopy.Copy(projectDirectory.FullName, tempDirectory.DirectoryPath);
var projectFile = new FileInfo(Path.Combine(tempDirectory.DirectoryPath, "test-project.csproj")); var projectFile = new FileInfo(Path.Combine(tempDirectory.DirectoryPath, "test-project.csproj"));
var outputContext = new OutputContext(sink, Verbosity.Debug); var outputContext = new OutputContext(_sink, Verbosity.Debug);
var application = await ApplicationFactory.CreateAsync(outputContext, projectFile); var application = await ApplicationFactory.CreateAsync(outputContext, projectFile);
using var host = new TyeHost(application.ToHostingApplication(), Array.Empty<string>()) using var host = new TyeHost(application.ToHostingApplication(), Array.Empty<string>())
{ {
Sink = sink, Sink = _sink,
}; };
await host.StartAsync(); await host.StartAsync();
@ -91,8 +91,8 @@ namespace E2ETest
var response = await client.SendAsync(request); var response = await client.SendAsync(request);
var text = await response.Content.ReadAsStringAsync(); var text = await response.Content.ReadAsStringAsync();
output.WriteLine($"Logs for service: {service.Description.Name}"); _output.WriteLine($"Logs for service: {service.Description.Name}");
output.WriteLine(text); _output.WriteLine(text);
} }
} }
finally finally
@ -109,11 +109,11 @@ namespace E2ETest
DirectoryCopy.Copy(projectDirectory.FullName, tempDirectory.DirectoryPath); DirectoryCopy.Copy(projectDirectory.FullName, tempDirectory.DirectoryPath);
var projectFile = new FileInfo(Path.Combine(tempDirectory.DirectoryPath, "tye.yaml")); var projectFile = new FileInfo(Path.Combine(tempDirectory.DirectoryPath, "tye.yaml"));
var outputContext = new OutputContext(sink, Verbosity.Debug); var outputContext = new OutputContext(_sink, Verbosity.Debug);
var application = await ApplicationFactory.CreateAsync(outputContext, projectFile); var application = await ApplicationFactory.CreateAsync(outputContext, projectFile);
using var host = new TyeHost(application.ToHostingApplication(), Array.Empty<string>()) using var host = new TyeHost(application.ToHostingApplication(), Array.Empty<string>())
{ {
Sink = sink, Sink = _sink,
}; };
await host.StartAsync(); await host.StartAsync();
@ -146,11 +146,11 @@ namespace E2ETest
DirectoryCopy.Copy(projectDirectory.FullName, tempDirectory.DirectoryPath); DirectoryCopy.Copy(projectDirectory.FullName, tempDirectory.DirectoryPath);
var projectFile = new FileInfo(Path.Combine(tempDirectory.DirectoryPath, "tye.yaml")); var projectFile = new FileInfo(Path.Combine(tempDirectory.DirectoryPath, "tye.yaml"));
var outputContext = new OutputContext(sink, Verbosity.Debug); var outputContext = new OutputContext(_sink, Verbosity.Debug);
var application = await ApplicationFactory.CreateAsync(outputContext, projectFile); var application = await ApplicationFactory.CreateAsync(outputContext, projectFile);
using var host = new TyeHost(application.ToHostingApplication(), Array.Empty<string>()) using var host = new TyeHost(application.ToHostingApplication(), Array.Empty<string>())
{ {
Sink = sink, Sink = _sink,
}; };
var handler = new HttpClientHandler var handler = new HttpClientHandler
@ -198,8 +198,8 @@ namespace E2ETest
var response = await client.SendAsync(request); var response = await client.SendAsync(request);
var text = await response.Content.ReadAsStringAsync(); var text = await response.Content.ReadAsStringAsync();
output.WriteLine($"Logs for service: {s.Description.Name}"); _output.WriteLine($"Logs for service: {s.Description.Name}");
output.WriteLine(text); _output.WriteLine(text);
} }
await host.StopAsync(); await host.StopAsync();
@ -216,11 +216,11 @@ namespace E2ETest
DirectoryCopy.Copy(projectDirectory.FullName, tempDirectory.DirectoryPath); DirectoryCopy.Copy(projectDirectory.FullName, tempDirectory.DirectoryPath);
var projectFile = new FileInfo(Path.Combine(tempDirectory.DirectoryPath, "tye.yaml")); var projectFile = new FileInfo(Path.Combine(tempDirectory.DirectoryPath, "tye.yaml"));
var outputContext = new OutputContext(sink, Verbosity.Debug); var outputContext = new OutputContext(_sink, Verbosity.Debug);
var application = await ApplicationFactory.CreateAsync(outputContext, projectFile); var application = await ApplicationFactory.CreateAsync(outputContext, projectFile);
using var host = new TyeHost(application.ToHostingApplication(), new[] { "--docker" }) using var host = new TyeHost(application.ToHostingApplication(), new[] { "--docker" })
{ {
Sink = sink, Sink = _sink,
}; };
await host.StartAsync(); await host.StartAsync();
@ -258,11 +258,11 @@ namespace E2ETest
var projectFile = new FileInfo(Path.Combine(tempDirectory.DirectoryPath, "test-project.csproj")); var projectFile = new FileInfo(Path.Combine(tempDirectory.DirectoryPath, "test-project.csproj"));
// Debug targets can be null if not specified, so make sure calling host.Start does not throw. // Debug targets can be null if not specified, so make sure calling host.Start does not throw.
var outputContext = new OutputContext(sink, Verbosity.Debug); var outputContext = new OutputContext(_sink, Verbosity.Debug);
var application = await ApplicationFactory.CreateAsync(outputContext, projectFile); var application = await ApplicationFactory.CreateAsync(outputContext, projectFile);
using var host = new TyeHost(application.ToHostingApplication(), Array.Empty<string>()) using var host = new TyeHost(application.ToHostingApplication(), Array.Empty<string>())
{ {
Sink = sink, Sink = _sink,
}; };
await host.StartAsync(); await host.StartAsync();
@ -299,7 +299,7 @@ namespace E2ETest
var appResponse = await client.GetAsync(uriBackendProcess); var appResponse = await client.GetAsync(uriBackendProcess);
var content = await appResponse.Content.ReadAsStringAsync(); var content = await appResponse.Content.ReadAsStringAsync();
output.WriteLine(content); _output.WriteLine(content);
Assert.Equal(HttpStatusCode.OK, appResponse.StatusCode); Assert.Equal(HttpStatusCode.OK, appResponse.StatusCode);
if (serviceName == "frontend") if (serviceName == "frontend")
{ {
@ -317,8 +317,8 @@ namespace E2ETest
var response = await client.SendAsync(request); var response = await client.SendAsync(request);
var text = await response.Content.ReadAsStringAsync(); var text = await response.Content.ReadAsStringAsync();
output.WriteLine($"Logs for service: {s.Description.Name}"); _output.WriteLine($"Logs for service: {s.Description.Name}");
output.WriteLine(text); _output.WriteLine(text);
} }
} }
} }

Loading…
Cancel
Save