Skip to content
This repository has been archived by the owner on Oct 28, 2024. It is now read-only.

Commit

Permalink
Merge pull request #370 from bacongobbler/start-serving
Browse files Browse the repository at this point in the history
start serving requests for the channel via IReverseProxy
  • Loading branch information
bacongobbler authored Jan 12, 2022
2 parents 3bef3a7 + b6fc11c commit 190529b
Show file tree
Hide file tree
Showing 9 changed files with 63 additions and 39 deletions.
16 changes: 3 additions & 13 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,7 @@
// this will not work as Headers don't seem to be forwarded by the Codespaces proxy.
"forwardPorts": [
5309,
32768,
32769,
32770
8080
],
"remoteUser": "vscode",
"updateRemoteUserUID": false,
Expand All @@ -41,16 +39,8 @@
"label": "Hippo HTTPS Port",
"protocol": "https"
},
"32768": {
"label": "Application Channel HTTP Port ",
"protocol": "http"
},
"32769": {
"label": "Application Channel HTTP Port",
"protocol": "http"
},
"32770": {
"label": "Application Channel HTTP Port",
"8080": {
"label": "Bindle HTTP Port",
"protocol": "http"
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,13 @@ public class ActiveRevisionChangedEventHandler : INotificationHandler<DomainEven

private readonly IJobScheduler _jobScheduler;

public ActiveRevisionChangedEventHandler(ILogger<ActiveRevisionChangedEventHandler> logger, IJobScheduler jobScheduler)
private readonly IReverseProxy _reverseProxy;

public ActiveRevisionChangedEventHandler(ILogger<ActiveRevisionChangedEventHandler> logger, IJobScheduler jobScheduler, IReverseProxy reverseProxy)
{
_logger = logger;
_jobScheduler = jobScheduler;
_reverseProxy = reverseProxy;
}

public Task Handle(DomainEventNotification<ActiveRevisionChangedEvent> notification, CancellationToken cancellationToken)
Expand All @@ -26,15 +29,21 @@ public Task Handle(DomainEventNotification<ActiveRevisionChangedEvent> notificat

if (domainEvent.Channel.ActiveRevision != null)
{
_logger.LogInformation($"ExecuteAsync: stopping {domainEvent.Channel.App.Name} channel {domainEvent.Channel.Name} at rev {domainEvent.Channel.ActiveRevision.RevisionNumber}");
_logger.LogInformation($"{domainEvent.Channel.App.Name}: Stopping channel {domainEvent.Channel.Name} at revision {domainEvent.Channel.ActiveRevision.RevisionNumber}");
_jobScheduler.Stop(domainEvent.Channel);
_logger.LogInformation($"ExecuteAsync: starting {domainEvent.Channel.App.Name} channel {domainEvent.Channel.Name} at rev {domainEvent.Channel.ActiveRevision.RevisionNumber}");
_jobScheduler.Start(domainEvent.Channel);
_logger.LogInformation($"ExecuteAsync: started {domainEvent.Channel.App.Name} channel {domainEvent.Channel.Name} at rev {domainEvent.Channel.ActiveRevision.RevisionNumber}");
_logger.LogInformation($"{domainEvent.Channel.App.Name}: Starting channel {domainEvent.Channel.Name} at revision {domainEvent.Channel.ActiveRevision.RevisionNumber}");
var status = _jobScheduler.Start(domainEvent.Channel);
if (!status.IsRunning)
{
_logger.LogInformation($"{domainEvent.Channel.App.Name}: Channel {domainEvent.Channel.Name} at revision {domainEvent.Channel.ActiveRevision.RevisionNumber} failed to start");
_reverseProxy.Stop(domainEvent.Channel);
}
_logger.LogInformation($"Started {domainEvent.Channel.App.Name} Channel {domainEvent.Channel.Name} at revision {domainEvent.Channel.ActiveRevision.RevisionNumber}");
_reverseProxy.Start(domainEvent.Channel, status.ListenAddress);
}
else
{
_logger.LogInformation($"ExecuteAsync: not restarting {domainEvent.Channel.App.Name} channel {domainEvent.Channel.Name}: no active revision");
_logger.LogInformation($"Not restarting {domainEvent.Channel.App.Name} Channel {domainEvent.Channel.Name}: no active revision");
}

return Task.CompletedTask;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ public Task Handle(DomainEventNotification<ChannelCreatedEvent> notification, Ca

_logger.LogInformation("Hippo Domain Event: {DomainEvent}", domainEvent.GetType().Name);

// TODO: schedule a "parking lot" app instance to start serving requests

return Task.CompletedTask;
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using Hippo.Application.Common.Interfaces;
using Hippo.Application.Common.Models;
using Hippo.Core.Events;
using MediatR;
Expand All @@ -9,9 +10,15 @@ public class ChannelDeletedEventHandler : INotificationHandler<DomainEventNotifi
{
private readonly ILogger<ChannelDeletedEventHandler> _logger;

public ChannelDeletedEventHandler(ILogger<ChannelDeletedEventHandler> logger)
private readonly IJobScheduler _jobScheduler;

private readonly IReverseProxy _reverseProxy;

public ChannelDeletedEventHandler(ILogger<ChannelDeletedEventHandler> logger, IJobScheduler jobScheduler, IReverseProxy reverseProxy)
{
_logger = logger;
_jobScheduler = jobScheduler;
_reverseProxy = reverseProxy;
}

public Task Handle(DomainEventNotification<ChannelDeletedEvent> notification, CancellationToken cancellationToken)
Expand All @@ -20,6 +27,9 @@ public Task Handle(DomainEventNotification<ChannelDeletedEvent> notification, Ca

_logger.LogInformation("Hippo Domain Event: {DomainEvent}", domainEvent.GetType().Name);

_reverseProxy.Stop(domainEvent.Channel);
_jobScheduler.Stop(domainEvent.Channel);

return Task.CompletedTask;
}
}
2 changes: 1 addition & 1 deletion src/Application/Common/Interfaces/IJobScheduler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ public interface IJobScheduler
/// <summary>
/// Schedule the current release.
/// </summary>
void Start(Channel c);
ChannelStatus Start(Channel c);

/// <summary>
/// Gracefully shut down the current release.
Expand Down
12 changes: 12 additions & 0 deletions src/Application/Common/Interfaces/IReverseProxy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,15 @@ public interface IReverseProxy

void Stop(Channel c);
}

public class ChannelStatus
{
public readonly bool IsRunning;
public readonly string ListenAddress;

public ChannelStatus(bool isRunning, string listenAddress)
{
IsRunning = isRunning;
ListenAddress = listenAddress;
}
}
13 changes: 6 additions & 7 deletions src/Infrastructure/JobSchedulers/LocalJobScheduler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public LocalJobScheduler(ILogger<LocalJobScheduler> logger, IConfiguration confi
});
}

public void Start(Channel c)
public ChannelStatus Start(Channel c)
{
var port = c.PortId + EphemeralPortStartRange;
var wagiProgram = WagiBinaryPath();
Expand All @@ -56,7 +56,7 @@ public void Start(Channel c)
if (c.ActiveRevision == null || string.IsNullOrWhiteSpace(c.ActiveRevision.RevisionNumber))
{
_logger.LogWarning($"Can't start {c.App.Name}:{c.Name}: no active revision");
return;
return new ChannelStatus(false, "");
}

var env = String.Join(' ', c.EnvironmentVariables.Select(ev => $"--env {ev.Key}=\"{ev.Value}\""));
Expand All @@ -81,7 +81,7 @@ public void Start(Channel c)
{
// TODO: probably want to throw an Exception here instead
_logger.LogError($"Process {psi.FileName} with arguments {psi.Arguments} never started");
return;
return new ChannelStatus(false, "");
}

process.EnableRaisingEvents = true;
Expand All @@ -100,11 +100,10 @@ public void Start(Channel c)
if (process.HasExited)
{
_logger.LogError($"Process {psi.FileName} with arguments {psi.Arguments} terminated unexpectedly");
return new ChannelStatus(false, "");
}
else
{
_wagiProcessIds[c.Id] = (process.Id, log);
}
_wagiProcessIds[c.Id] = (process.Id, log);
return new ChannelStatus(true, listenAddress);
}
}
catch (Win32Exception e) // yes, even on Linux
Expand Down
12 changes: 7 additions & 5 deletions src/Infrastructure/ReverseProxies/YarpReverseProxy.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
using Hippo.Application.Common.Interfaces;
using Hippo.Core.Entities;
using Hippo.Infrastructure.ReverseProxies.Configuration;
using Microsoft.Extensions.Logging;
using Yarp.ReverseProxy.Configuration;

namespace Hippo.Infrastructure.ReverseProxies;

public class YarpReverseProxy : IReverseProxy
{
// TODO: when the host restarts, we should re-hydrate the reverse proxy route config
//
// We could fix this by implementing a file-backed config provider.
private readonly InMemoryConfigProvider _configProvider;

public YarpReverseProxy(InMemoryConfigProvider configProvider)
Expand All @@ -26,10 +30,8 @@ public void Start(Channel c, string address)
ClusterId = key,
Match = new RouteMatch
{
Hosts = new List<string>()
{
c.Domain
}
Hosts = new List<string>(){c.Domain},
Path = "{**catch-all}"
}
};

Expand All @@ -41,7 +43,7 @@ public void Start(Channel c, string address)
{
key, new DestinationConfig()
{
Address = address
Address = "http://" + address
}
}
}
Expand Down
12 changes: 6 additions & 6 deletions src/Web/appsettings.Development.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
{
"Logging": {
"LogLevel": {
"Default": "Debug",
"Hippo.Application": "Debug",
"Hippo.Core": "Debug",
"Hippo.Infrastructure": "Debug",
"Hippo.Web": "Debug",
"System": "Information",
"Default": "Information",
"Microsoft": "Information",
"Microsoft.AspNetCore": "Warning",
"Microsoft.EntityFrameworkCore": "Warning",
"System": "Information",

"Hippo": "Debug",
"Yarp" : "Debug"
}
},
Expand Down

0 comments on commit 190529b

Please sign in to comment.