Example #1
0
        /// <summary>
        /// Starts the engine and updates the Cache from Database
        /// </summary>
        /// <returns>Returns task to wait for until Startup has completed (true) or failed (false)</returns>
        public static async Task <bool> StartupAsync(IConfigurationRoot configuration)
        {
            await lockStartup.WaitAsync();

            var engineConfig = configuration.GetSection("Engine");

            logger.Info("<<<<<<<<<<<<<<<<<<<< CarrierLink >>>>>>>>>>>>>>>>>>>>");
            logger.Info("Startup...");

            if (IsRunning())
            {
                logger.Error("Engine is already running");
                return(false);
            }

            Pool.Initialize(() => new PgSQL(configuration.GetConnectionString("CarrierLink")));

            // Message Buffer Setup
            if (!int.TryParse(engineConfig.GetValue <string>("Workers"), out int workers) || workers < 1)
            {
                throw new InvalidOperationException("Workers needs to be a positive number");
            }

            // WaitingTimeWarningThreshold
            if (!int.TryParse(engineConfig.GetValue <string>("WaitingTimeWarningThreshold"), out waitingTimeWarningThreshold) || waitingTimeWarningThreshold < 1 || waitingTimeWarningThreshold > 10)
            {
                logger.Warn(@"Configuration Parameter ""WaitingTimeWarningThreshold"" is not an Integer or not between 1 and 10, setting value to 2 (default)");
                waitingTimeWarningThreshold = 2;
            }
            waitingTimeWarningThreshold *= 1000;


            // YateMaximumWaitingTime
            if (!int.TryParse(engineConfig.GetValue <string>("YateMaximumWaitingTime"), out yateMaximumWaitingTime) || yateMaximumWaitingTime < 1 || yateMaximumWaitingTime > 300)
            {
                logger.Warn(@"Configuration Parameter ""YateMaximumWaitingTime"" is not an Integer or not between 1 and 300, setting value to 10 (default)");
                yateMaximumWaitingTime = 2;
            }
            yateMaximumWaitingTime *= 1000;


            messageBuffer = new ActionBlock <Message>(async message => await _ProcessMessage(message),
                                                      new ExecutionDataflowBlockOptions()
            {
                MaxDegreeOfParallelism    = workers,
                CancellationToken         = CancellationToken,
                SingleProducerConstrained = false
            }
                                                      );

            // Delete old registrations
            var database = Pool.Database.Get();

            try
            {
                Id = await database.ControllerStartup(engineConfig.GetValue <string>("ControlServerName"), CancellationToken);
            }
            catch
            {
                logger.Error($"Controller Name '{engineConfig.GetValue<string>("ControlServerName")}' is not registered in database. ABORTING.");

                throw new ArgumentException($"Controller Name '{engineConfig.GetValue<string>("ControlServerName")}' is not registered in database.");
            }

            await database.ControllerLog(Id, "Startup Initiated", CancellationToken);

            // Default Value
            State = EngineState.Stopped;

            Cache.Initialize();

            await database.ControllerLog(Id, "Updating Cache", CancellationToken);

            await Cache.Update(false);

            // Connection Management Timer
            connectionManagmentTimer = new System.Timers.Timer
            {
                AutoReset = true,
                Interval  = 2000
            };
            connectionManagmentTimer.Elapsed += _ConnectionManagmentTimer_Elapsed;

            State = EngineState.Running;

            await database.ControllerLog(Id, "Startup Completed", CancellationToken);

            Pool.Database.Put(database);

            // Start Timers
            connectionManagmentTimer.Start();
            AutomaticJobsManager.Start();

            logger.Info("Startup completed");

            lockStartup.Release();

            return(true);
        }
Example #2
0
        /// <summary>
        /// Removes the handlers and stops the engine
        /// </summary>
        /// <returns>Returns task to wait for until shutdown has completed</returns>
        public static async Task ShutdownAsync()
        {
            await lockShutdown.WaitAsync();

            logger.Info("Shutdown...");

            if (!IsRunning())
            {
                lockShutdown.Release();
                return;
            }

            var db = Pool.Database.Get();
            await db.ControllerLog(Id, "Shutdown Initiated", CancellationToken);

            State = EngineState.Stopping;

            // Stop jobs
            AutomaticJobsManager.Stop();

            // Disconnect connections
            connectionManagmentTimer.Stop();
            var connectionsToStop     = new List <Task>();
            var registeredConnections = nodeConnections.Select(nc => nc.Value).ToList();

            foreach (var node in registeredConnections)
            {
                if (node.IsConnected)
                {
                    connectionsToStop.Add(_Disconnect(node.Id));
                }
            }

            await Task.WhenAll(connectionsToStop);

            connectionsToStop = null;

            // Signal completition of message processing and wait for buffer to complete, max. 5 seconds
            messageBuffer.Complete();
            int timeout = 0;

            while (messageBuffer.InputCount > 0 && timeout < 20)
            {
                await Task.Delay(250);

                timeout++;
            }

            // Cancel parallel operations in Main
            logger.Debug("Cancelling processes, may take up to two minutes.");
            cancellationToken.Cancel();

            /// Wait 10 seconds
            await Task.Delay(10000);

            var databaseCancellationTokenSource = new CancellationTokenSource();

            databaseCancellationTokenSource.CancelAfter(30000);

            await db.ControllerLog(Id, "Remaining Connections terminated", databaseCancellationTokenSource.Token);

            await db.ControllerLog(Id, "Shutdown Completed", databaseCancellationTokenSource.Token);

            await db.ControllerShutdown(Id, databaseCancellationTokenSource.Token);

            Pool.Database.Put(db);

            databaseCancellationTokenSource.Dispose();
            databaseCancellationTokenSource = null;

            // Shutdown the Cache
            Cache.Shutdown();

            State = EngineState.Stopped;

            logger.Info("Shutdown completed");

            messageBuffer = null;

            cancellationToken.Dispose();
            cancellationToken = null;

            connectionManagmentTimer.Dispose();
            connectionManagmentTimer = null;

            lockShutdown.Release();
            lockShutdown.Dispose();
            lockShutdown = null;

            logger = null;
        }