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 #1089 from equilobe/234-port-back-to-hippo-the-cha…
Browse files Browse the repository at this point in the history
…nges-made-in-the-fermyon-platform

synced api with the one from the platform
  • Loading branch information
bacongobbler authored Aug 9, 2022
2 parents fc2a433 + 24db8d7 commit 703bd35
Show file tree
Hide file tree
Showing 24 changed files with 1,581 additions and 91 deletions.
14 changes: 14 additions & 0 deletions src/Application/ChannelStatuses/Queries/ChannelJobStatusItem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using Hippo.Application.Jobs;
using Newtonsoft.Json;
using System.ComponentModel.DataAnnotations;

namespace Hippo.Application.ChannelStatuses.Queries;

public class ChannelJobStatusItem
{
[Required]
public Guid ChannelId { get; set; }

[Required]
public JobStatus Status { get; set; }
}
95 changes: 95 additions & 0 deletions src/Application/ChannelStatuses/Queries/GetChannelStatusesQuery.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
using Hippo.Application.Common.Exceptions;
using Hippo.Application.Common.Interfaces;
using Hippo.Application.Jobs;
using Hippo.Core.Models;
using MediatR;

namespace Hippo.Application.ChannelStatuses.Queries;

public class GetChannelStatusesQuery : SearchFilter, IRequest<Page<ChannelJobStatusItem>>
{
public Guid? ChannelId { get; set; }
}

public class GetChannelStatusesQueryHandler : IRequestHandler<GetChannelStatusesQuery, Page<ChannelJobStatusItem>>
{
private readonly IApplicationDbContext _context;
private readonly IJobService _jobService;

public GetChannelStatusesQueryHandler(IApplicationDbContext context,
IJobService jobService)
{
_context = context;
_jobService = jobService;
}

public async Task<Page<ChannelJobStatusItem>> Handle(GetChannelStatusesQuery request, CancellationToken cancellationToken)
{
List<ChannelJobStatusItem> entities;
int totalItems;

if (!request.ChannelId.HasValue)
{
(totalItems, entities) = GetPaginatedChannelsStatuses(request.Offset, request.PageSize);
}
else
{
entities = new List<ChannelJobStatusItem>();
entities.Add(GetChannelStatus(request.ChannelId.Value));
totalItems = 1;
}

return await Task.FromResult(new Page<ChannelJobStatusItem>
{
Items = entities,
PageIndex = request.PageIndex,
PageSize = request.PageSize,
TotalItems = totalItems
});
}

private static JobStatus FindJobAndGetStatus(List<Job>? jobs, Guid jobId)
{
if (jobs is null)
{
return JobStatus.Unknown;
}

var job = jobs.FirstOrDefault(job => job.Id == jobId);

return GetJobStatus(job);
}

private (int, List<ChannelJobStatusItem>) GetPaginatedChannelsStatuses(int offset, int pageSize)
{
var jobs = _jobService.GetJobs()?.ToList();
var totalItems = jobs?.Count ?? 0;
var paginatedChannelsStatuses = _context.Channels
.Select(c => new ChannelJobStatusItem
{
ChannelId = c.Id,
Status = FindJobAndGetStatus(jobs, c.Id),
})
.Skip(offset)
.Take(pageSize)
.ToList();

return (totalItems, paginatedChannelsStatuses);
}

private ChannelJobStatusItem GetChannelStatus(Guid channelId)
{
var job = _jobService.GetJob(channelId.ToString());

return new ChannelJobStatusItem
{
ChannelId = channelId,
Status = GetJobStatus(job),
};
}

private static JobStatus GetJobStatus(Job? job)
{
return job?.Status ?? JobStatus.Dead;
}
}
51 changes: 51 additions & 0 deletions src/Application/Channels/Commands/UpdateDesiredStatusCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
using System.ComponentModel.DataAnnotations;
using Hippo.Application.Common.Exceptions;
using Hippo.Application.Common.Interfaces;
using Hippo.Core.Entities;
using Hippo.Core.Enums;
using Hippo.Core.Events;
using MediatR;
using Microsoft.EntityFrameworkCore;

namespace Hippo.Application.Channels.Commands;

public class UpdateDesiredStatusCommand : IRequest
{
[Required]
public Guid ChannelId { get; set; }

[Required]
public DesiredStatus DesiredStatus { get; set; }
}

public class UpdateDesiredStatusCommandHandler : IRequestHandler<UpdateDesiredStatusCommand>
{
private readonly IApplicationDbContext _context;

public UpdateDesiredStatusCommandHandler(IApplicationDbContext context)
{
_context = context;
}

public async Task<Unit> Handle(UpdateDesiredStatusCommand request, CancellationToken cancellationToken)
{
var entity = _context.Channels
.Include(c => c.ActiveRevision)
.Include(c => c.EnvironmentVariables)
.Include(c => c.App)
.FirstOrDefault(c => c.Id == request.ChannelId);

if (entity is null)
{
throw new NotFoundException(nameof(Channel), request.ChannelId);
}

entity.DesiredStatus = request.DesiredStatus;

entity.AddDomainEvent(new ModifiedEvent<Channel>(entity));

await _context.SaveChangesAsync(cancellationToken);

return Unit.Value;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
using Hippo.Application.Common.Interfaces;
using Hippo.Application.Jobs;
using Hippo.Core.Entities;
using Hippo.Core.Enums;
using Hippo.Core.Events;
using MediatR;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;

namespace Hippo.Application.Channels.EventHandlers;

public class ChannelStatusModifiedEventHandler : INotificationHandler<ModifiedEvent<Channel>>
{
private readonly ILogger<ChannelStatusModifiedEventHandler> _logger;
private readonly IJobService _jobService;
private readonly IApplicationDbContext _context;

public ChannelStatusModifiedEventHandler(ILogger<ChannelStatusModifiedEventHandler> logger, IJobService jobService, IApplicationDbContext context)
{
_logger = logger;
_jobService = jobService;
_context = context;
}

public Task Handle(ModifiedEvent<Channel> notification, CancellationToken cancellationToken)
{
var channel = _context.Channels
.Include(c => c.ActiveRevision)
.Include(c => c.EnvironmentVariables)
.Include(c => c.App)
.First(c => c.Id == notification.Entity.Id);

_logger.LogInformation($"Hippo Domain Event: {notification.GetType().Name}");

if (channel.DesiredStatus == DesiredStatus.Running)
{
if (channel.ActiveRevision is not null)
{
_logger.LogInformation($"{channel.App.Name}: Starting channel {channel.Name} at revision {channel.ActiveRevision.RevisionNumber}");
var environmentVariables = channel.EnvironmentVariables.ToDictionary(
e => e.Key!,
e => e.Value!
);
_jobService.StartJob(channel.Id, $"{channel.App.StorageId}/{channel.ActiveRevision.RevisionNumber}", environmentVariables, channel.Domain);
_logger.LogInformation($"Started {channel.App.Name} Channel {channel.Name} at revision {channel.ActiveRevision.RevisionNumber}");
}
else
{
_logger.LogInformation($"Not starting {channel.App.Name} Channel {channel.Name}: no active revision");
}
}
else if (channel.DesiredStatus == DesiredStatus.Dead)
{
_jobService.DeleteJob(channel.Id.ToString());
}

return Task.CompletedTask;
}
}
1 change: 1 addition & 0 deletions src/Core/Entities/Channel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public class Channel : AuditableEntity
public Revision? ActiveRevision { get; set; }

public DateTime? LastPublishAt { get; set; }
public DesiredStatus DesiredStatus { get; set; }

public Guid? CertificateId { get; set; }

Expand Down
11 changes: 11 additions & 0 deletions src/Core/Enums/DesiredStatus.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

namespace Hippo.Core.Enums;

[JsonConverter(typeof(StringEnumConverter))]
public enum DesiredStatus
{
Running = 2,
Dead = 3,
}
Loading

0 comments on commit 703bd35

Please sign in to comment.