diff --git a/source/Octopus.Tentacle/Commands/RegisterMachineCommandBase.cs b/source/Octopus.Tentacle/Commands/RegisterMachineCommandBase.cs index 02a96e28c..72f07f6db 100644 --- a/source/Octopus.Tentacle/Commands/RegisterMachineCommandBase.cs +++ b/source/Octopus.Tentacle/Commands/RegisterMachineCommandBase.cs @@ -177,11 +177,14 @@ async Task RegisterMachine(IOctopusSystemAsyncRepository systemRepository, IOcto } configuration.Value.AddOrUpdateTrustedOctopusServer(server); + configuration.Value.SetIsWorker(IsRegisteredAsWorker); VoteForRestart(); log.Info("Machine registered successfully"); } + protected virtual bool IsRegisteredAsWorker => false; + protected abstract void CheckArgs(); protected abstract void EnhanceOperation(TRegistrationOperationType registerOperation); diff --git a/source/Octopus.Tentacle/Commands/RegisterWorkerCommandBase.cs b/source/Octopus.Tentacle/Commands/RegisterWorkerCommandBase.cs index add9a363d..bfb92c810 100644 --- a/source/Octopus.Tentacle/Commands/RegisterWorkerCommandBase.cs +++ b/source/Octopus.Tentacle/Commands/RegisterWorkerCommandBase.cs @@ -29,6 +29,8 @@ public RegisterWorkerCommandBase(Lazy lazyRegisterMach Options.Add("workerpool=", "The worker pool name, slug or Id to add the machine to - e.g., 'Windows Pool'; specify this argument multiple times to add to multiple pools", s => workerpools.Add(s)); } + protected override bool IsRegisteredAsWorker => true; + protected override void CheckArgs() { if (workerpools.Count == 0 || string.IsNullOrWhiteSpace(workerpools.First())) diff --git a/source/Octopus.Tentacle/Communications/HalibutInitializer.cs b/source/Octopus.Tentacle/Communications/HalibutInitializer.cs index 92ca8982e..180f983fc 100644 --- a/source/Octopus.Tentacle/Communications/HalibutInitializer.cs +++ b/source/Octopus.Tentacle/Communications/HalibutInitializer.cs @@ -115,19 +115,21 @@ void AddPollingEndpoints() } } - const int MaximumPollingConnectionCount = 8; - + const uint MinimumPollingConnectionCount = 2; + const uint MaximumPollingConnectionCount = 8; + uint GetPollingConnectionCount() { - //Open multiple polling connections if the env var is set to a non-zero/negative number - var connectionCount = 1u; + // Default to one connection per CPU core (clamped to [min, max]) for workers; deployment targets stay at 1 + var connectionCount = configuration.IsWorker + ? (uint)Math.Clamp(Environment.ProcessorCount, MinimumPollingConnectionCount, MaximumPollingConnectionCount) + : 1u; if (uint.TryParse(Environment.GetEnvironmentVariable(EnvironmentVariables.TentaclePollingConnectionCount), out var count)) { log.InfoFormat("Requested polling connection count: {0}", count); connectionCount = count; } - //Coerce the requested value as it might be outside our max & min switch (connectionCount) { case > MaximumPollingConnectionCount: diff --git a/source/Octopus.Tentacle/Configuration/ITentacleConfiguration.cs b/source/Octopus.Tentacle/Configuration/ITentacleConfiguration.cs index 675b657bb..63907eb02 100644 --- a/source/Octopus.Tentacle/Configuration/ITentacleConfiguration.cs +++ b/source/Octopus.Tentacle/Configuration/ITentacleConfiguration.cs @@ -75,6 +75,8 @@ public interface ITentacleConfiguration bool IsRegistered { get; } + bool IsWorker { get; } + void WriteTo(IWritableKeyValueStore outputStore, IEnumerable excluding); } @@ -92,6 +94,8 @@ public interface IWritableTentacleConfiguration : ITentacleConfiguration bool SetIsRegistered(bool isRegistered = true); + bool SetIsWorker(bool isWorker = true); + /// /// Sets the IP address to listen on. /// diff --git a/source/Octopus.Tentacle/Configuration/TentacleConfiguration.cs b/source/Octopus.Tentacle/Configuration/TentacleConfiguration.cs index e74380aa8..a358a5e56 100644 --- a/source/Octopus.Tentacle/Configuration/TentacleConfiguration.cs +++ b/source/Octopus.Tentacle/Configuration/TentacleConfiguration.cs @@ -19,6 +19,7 @@ namespace Octopus.Tentacle.Configuration internal class TentacleConfiguration : ITentacleConfiguration { internal const string IsRegisteredSettingName = "Tentacle.Services.IsRegistered"; + internal const string IsWorkerSettingName = "Tentacle.Services.IsWorker"; internal const string ServicesPortSettingName = "Tentacle.Services.PortNumber"; internal const string ServicesListenIPSettingName = "Tentacle.Services.ListenIP"; internal const string ServicesNoListenSettingName = "Tentacle.Services.NoListen"; @@ -70,6 +71,8 @@ public IEnumerable TrustedOctopusThumbprints public bool IsRegistered => settings.Get(IsRegisteredSettingName, false); + public bool IsWorker => settings.Get(IsWorkerSettingName, false); + public void WriteTo(IWritableKeyValueStore outputStore, IEnumerable excluding) { excluding = new HashSet(excluding); @@ -191,6 +194,11 @@ public bool SetIsRegistered(bool isRegistered = true) return settings.Set(IsRegisteredSettingName, isRegistered); } + public bool SetIsWorker(bool isWorker = true) + { + return settings.Set(IsWorkerSettingName, isWorker); + } + public bool SetListenIpAddress(string? address) { return settings.Set(ServicesListenIPSettingName, address);