mirror of
https://github.com/tgstation/tgstation-server.git
synced 2026-08-30 00:22:40 +01:00
Fix things
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user