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

synced api with the one from the platform #1089

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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