I have a dotnet Core 3.1 app with the following Host created in Program.cs
public static async Task Main(string[] args)
{
var configuration = ConfigurationFactory.CreateConfiguration();
var appName = configuration.GetAppName();
Log.Logger = configuration.CreateSerilogLogger();
try
{
Log.Information("Configuring console host ({ApplicationContext})...", appName);
var host = Host.CreateDefaultBuilder(args)
.UseConsoleLifetime(opts => opts.SuppressStatusMessages = true)
.ConfigureServices((hostContext, services) =>
{
services
.AddHostedService<EventRehydratorService>()
}).Build();
Log.Information("Starting console host ({ApplicationContext})...", appName);
await host.StartAsync();
await host.StopAsync();
}
catch (Exception ex)
{
Log.Fatal(ex, "Program terminated unexpectedly ({ApplicationContext})!", appName);
Environment.Exit(-1);
}
finally
{
Log.CloseAndFlush();
}
Environment.Exit(1);
}
EventRehydratorService implements IHostedService
internal class EventRehydratorService : IHostedService
{
private readonly IHostApplicationLifetime appLifetime;
private readonly IConfiguration configuration;
public IEventSourceService EventSourceService { get; }
public IDocumentStore Store { get; }
public EventRehydratorService(
IHostApplicationLifetime appLifetime,
IEventSourceService eventSourceService,
IDocumentStore store,
IConfiguration configuration)
{
this.appLifetime = appLifetime;
EventSourceService = eventSourceService;
Store = store;
this.configuration = configuration;
}
public Task StartAsync(CancellationToken cancellationToken)
{
appLifetime.ApplicationStopping.Register(OnStopping);
appLifetime.ApplicationStopped.Register(OnStopped);
return Task.CompletedTask;
}
private void OnStopping()
{
Log.Information("OnStopping has been called.");
}
private void OnStopped()
{
Log.Information("OnStopped has been called.");
}
public Task StopAsync(CancellationToken cancellationToken)
{
appLifetime.StopApplication();
return Task.CompletedTask;
}
}
}
Docker file:
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
WORKDIR /app
FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
WORKDIR /src
COPY ["Shophattan.EventRehydrator/EventRehydrator.csproj", "Shophattan.EventRehydrator/"]
COPY ["Common/Shophattan.Common/Shophattan.Common.csproj", "Common/Shophattan.Common/"]
COPY ["RavenDB.DependencyInjection/RavenDB.DependencyInjection.csproj", "RavenDB.DependencyInjection/"]
RUN dotnet restore "Shophattan.EventRehydrator/EventRehydrator.csproj"
COPY . .
WORKDIR "/src/Shophattan.EventRehydrator"
RUN dotnet build "EventRehydrator.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "EventRehydrator.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "EventRehydrator.dll"]
All events are called but container remains running. That is a problem with Kubernetes CronJob because Job never completes. I tried to Kill a Current process, throw an exception, Environment.Exit() in OnStopped method but docker never finishes. Not sure what am I doing wrong?
figured it out - it is simple as exiting with zero. For some reason, I thought it should be a positive number.
Environment.Exit(0);
Now Job completes successfully:
NAME COMPLETIONS DURATION AGE
dev-eventrehydrator-1586018400 1/1 3s 15m