/* * Copyright (c) 2022 Vaughn Nugent * * Library: VNLib * Package: VNLib.Plugins.Essentials.ServiceStack * File: HttpServiceStack.cs * * HttpServiceStack.cs is part of VNLib.Plugins.Essentials.ServiceStack which is part of the larger * VNLib collection of libraries and utilities. * * VNLib.Plugins.Essentials.ServiceStack is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 2 of the * License, or (at your option) any later version. * * VNLib.Plugins.Essentials.ServiceStack is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see https://www.gnu.org/licenses/. */ using VNLib.Utils; using VNLib.Net.Http; namespace VNLib.Plugins.Essentials.ServiceStack { /// /// The service domain controller that manages all /// servers for an application based on a /// /// public sealed class HttpServiceStack : VnDisposeable { private readonly LinkedList _servers; private readonly ServiceDomain _serviceDomain; private CancellationTokenSource? _cts; private Task WaitForAllTask; /// /// A collection of all loaded servers /// public IReadOnlyCollection Servers => _servers; /// /// The service domain's plugin controller /// public IPluginController PluginController => _serviceDomain; /// /// Initializes a new that will /// generate servers to listen for services exposed by the /// specified host context /// internal HttpServiceStack(LinkedList servers, ServiceDomain serviceDomain) { _servers = servers; _serviceDomain = serviceDomain; WaitForAllTask = Task.CompletedTask; } /// /// Starts all configured servers that observe a cancellation /// token to cancel /// /// The token to observe which may stop servers and cleanup the provider public void StartServers(CancellationToken parentToken = default) { Check(); //Init new linked cts to stop all servers if cancelled _cts = CancellationTokenSource.CreateLinkedTokenSource(parentToken); LinkedList runners = new(); foreach(HttpServer server in _servers) { //Start servers and add run task to list Task run = server.Start(_cts.Token); runners.AddLast(run); } //Task that waits for all to exit then cleans up WaitForAllTask = Task.WhenAll(runners) .ContinueWith(OnAllServerExit, CancellationToken.None, TaskContinuationOptions.RunContinuationsAsynchronously, TaskScheduler.Default); } /// /// Stops listening on all configured servers /// and returns a task that completes when the service /// host has stopped all servers and unloaded resources /// /// The task that completes when public Task StopAndWaitAsync() { _cts?.Cancel(); return WaitForAllTask; } private void OnAllServerExit(Task allExit) { //Unload the hosts _serviceDomain.UnloadAll(); } /// protected override void Free() { _cts?.Dispose(); _serviceDomain.Dispose(); //remove all lists _servers.Clear(); } } }