Fix things

This commit is contained in:
Cyberboss
2018-07-24 15:46:56 -04:00
parent d2d63e235b
commit d18c584f63
8 changed files with 34 additions and 51 deletions
@@ -33,9 +33,9 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Http.Extensions" Version="2.1.0-preview2-final" />
<PackageReference Include="Microsoft.AspNetCore.Http.Extensions" Version="2.1.1" />
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.6.0" />
<PackageReference Include="System.ComponentModel.Annotations" Version="4.4.1" />
<PackageReference Include="System.ComponentModel.Annotations" Version="4.5.0" />
</ItemGroup>
</Project>
@@ -25,9 +25,10 @@ namespace Tgstation.Server.Host.Watchdog
/// <summary>
/// Loads the <see cref="Assembly"/> at <see cref="assemblyPath"/> and creates an <see cref="IServer"/> from it
/// </summary>
/// <param name="args">The arguments for the <see cref="IServer"/></param>
/// <param name="args">The arguments for the <see cref="IServer"/></param>
/// <param name="updatePath">The updatePath for the <see cref="IServer"/></param>
/// <returns>A new <see cref="IServer"/></returns>
public IServer CreateServer(string[] args)
public IServer CreateServer(string[] args, string updatePath)
{
var assembly = LoadFromAssemblyPath(assemblyPath);
//find the IServerFactory implementation
@@ -36,7 +37,7 @@ namespace Tgstation.Server.Host.Watchdog
var serverFactoryImplementationType = assembly.GetTypes().Where(x => serverFactoryInterfaceType.IsAssignableFrom(x)).First();
var serverFactory = (IServerFactory)Activator.CreateInstance(serverFactoryImplementationType);
return serverFactory.CreateServer(args);
return serverFactory.CreateServer(args, updatePath);
}
//honestly have no idea what this is for, but the examples i see just return null and it seems to work just fine
+21 -12
View File
@@ -57,27 +57,36 @@ namespace Tgstation.Server.Host.Watchdog
logger.LogTrace("Determining location of host assembly...");
var assemblyPath = serverFactory.GetType().Assembly.Location;
logger.LogDebug("Path to initial host assembly: {0}", assemblyPath);
var assemblyName = Path.GetFileName(assemblyPath);
const string UpdatePath = "Updates";
var newAssemblyDirectory = Path.Combine(Path.GetDirectoryName(assemblyPath), UpdatePath);
var firstIteration = true;
do
using (logger.BeginScope("Host invocation"))
{
var server = serverFactory.CreateServer(args);
logger.LogTrace("Running server...");
await server.RunAsync(cancellationToken).ConfigureAwait(false);
logger.LogInformation("Active host exited.");
Guid updateGuid;
using (var server = serverFactory.CreateServer(args, newAssemblyDirectory))
{
logger.LogTrace("Running server...");
await server.RunAsync(cancellationToken).ConfigureAwait(false);
logger.LogInformation("Active host exited.");
if (server.UpdatePath == null)
break;
if (!server.UpdateGuid.HasValue)
break;
updateGuid = server.UpdateGuid.Value;
}
logger.LogInformation("Update path is set to \"{0}\", attempting host assembly hotswap...", server.UpdatePath);
logger.LogInformation("Update path is set to \"{0}\", attempting host assembly hotswap...", updateGuid);
GC.Collect(Int32.MaxValue, GCCollectionMode.Forced, true, true);
logger.LogTrace("Deleting old host assembly");
activeAssemblyDeleter.DeleteActiveAssembly(assemblyPath);
logger.LogTrace("Moving new host assembly in place...");
File.Move(server.UpdatePath, assemblyPath);
if (!firstIteration)
{
logger.LogTrace("Deleting old host assembly");
//TODO: make this use directories
//activeAssemblyDeleter.DeleteActiveAssembly(newAssemblyDirectory);
}
logger.LogTrace("Atttempting to create new server factory...");
serverFactory = isolatedAssemblyLoader.CreateIsolatedServerFactory(assemblyPath);
serverFactory = isolatedAssemblyLoader.CreateIsolatedServerFactory(Path.Combine(newAssemblyDirectory, updateGuid.ToString(), assemblyName));
firstIteration = false;
}
while (!cancellationToken.IsCancellationRequested);
@@ -272,7 +272,7 @@ namespace Tgstation.Server.Host.IO
zipFileBytes = null;
using (var archive = new ZipArchive(ms))
{
string GetEntryName(ZipArchiveEntry entry) => ConcatPath(path, GetDirectoryName(entry.FullName));
string GetEntryName(ZipArchiveEntry entry) => ConcatPath(path, entry.FullName);
//create directories first
await Task.WhenAll(archive.Entries.Where(x => x.Name.Length == 0).Select(x => CreateDirectory(GetEntryName(x), cancellationToken))).ConfigureAwait(false);
//extract files
+1 -1
View File
@@ -7,6 +7,6 @@ namespace Tgstation.Server.Host
public sealed class ServerFactory : IServerFactory
{
/// <inheritdoc />
public IServer CreateServer(string[] args) => new Server(WebHost.CreateDefaultBuilder(args));
public IServer CreateServer(string[] args, string updatePath) => new Server(WebHost.CreateDefaultBuilder(args), updatePath);
}
}
@@ -4,14 +4,16 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Tgstation.Server.Host.IO;
namespace Tgstation.Server.Host.Core.Tests
{
[TestClass]
public sealed class TestApplication : IServerUpdater
{
public void ApplyUpdate(string updatePath) => throw new NotImplementedException();
public Task ApplyUpdate(byte[] updateZipData, IIOManager ioManager, CancellationToken cancellationToken) => throw new NotImplementedException();
public void RegisterForUpdate(Action action) => throw new NotImplementedException();
@@ -20,7 +20,7 @@ namespace Tgstation.Server.Host.Watchdog.Tests
public void TestLoading()
{
var isf = new IsolatedServerFactory(typeof(ServerFactory).Assembly.Location);
Assert.IsNotNull(isf.CreateServer(Array.Empty<string>()));
Assert.IsNotNull(isf.CreateServer(Array.Empty<string>(), String.Empty));
}
}
}
@@ -29,7 +29,7 @@ namespace Tgstation.Server.Host.Watchdog.Tests
{
readonly IServer server;
public MockServerFactory(IServer server) => this.server = server;
public IServer CreateServer(string[] args) => server;
public IServer CreateServer(string[] args, string updatePath) => server;
}
[TestMethod]
@@ -50,34 +50,5 @@ namespace Tgstation.Server.Host.Watchdog.Tests
mockServer.VerifyAll();
}
}
[TestMethod]
public async Task TestRunAsyncWithUpdate()
{
var mockServer = new Mock<IServer>();
mockServer.Setup(x => x.UpdatePath).Returns(GetType().Assembly.Location).Verifiable();
var mockServerFactory = new MockServerFactory(mockServer.Object);
var mockActiveAssemblyDeleter = new Mock<IActiveAssemblyDeleter>();
var mockIsolatedServerContextFactory = new Mock<IIsolatedAssemblyContextFactory>();
mockIsolatedServerContextFactory.Setup(x => x.CreateIsolatedServerFactory(GetType().Assembly.Location)).Returns(mockServerFactory).Verifiable();
var mockLogger = new LoggerFactory().CreateLogger<Watchdog>();
var wd = new Watchdog(mockServerFactory, mockActiveAssemblyDeleter.Object, mockIsolatedServerContextFactory.Object, mockLogger);
using (var cts = new CancellationTokenSource())
{
int count = 0;
mockServer.Setup(x => x.RunAsync(cts.Token)).Callback(() =>
{
if (++count > 1)
cts.Cancel();
}).Returns(Task.CompletedTask).Verifiable();
await wd.RunAsync(Array.Empty<string>(), cts.Token).ConfigureAwait(false);
mockServer.VerifyAll();
mockActiveAssemblyDeleter.Verify(x => x.DeleteActiveAssembly(GetType().Assembly.Location), Times.Exactly(2));
mockIsolatedServerContextFactory.VerifyAll();
}
}
}
}