예제 #1
0
        private void ListeningLoop()
        {
            while (true)
            {
                // poll every 1 second
                Thread.Sleep(1000);

                if (!_dbFactory.Configured)
                {
                    // if we aren't configured, we just keep looping since we can't query the db
                    continue;
                }

                lock (_locker)
                {
                    // If cancellation has been requested we will just exit. Depending on timing of the shutdown,
                    // we will have already flagged _mainDomChanging = true, or we're shutting down faster than
                    // the other MainDom is taking to startup. In this case the db row will just be deleted and the
                    // new MainDom will just take over.
                    if (_cancellationTokenSource.IsCancellationRequested)
                    {
                        return;
                    }

                    var db = GetDatabase();

                    try
                    {
                        db.BeginTransaction(IsolationLevel.ReadCommitted);

                        // get a read lock
                        _sqlServerSyntax.ReadLock(db, Constants.Locks.MainDom);

                        // TODO: We could in theory just check if the main dom row doesn't exist, that could indicate that
                        // we are still the maindom. An empty value might be better because then we won't have any orphan rows
                        // if the app is terminated. Could that work?

                        if (!IsMainDomValue(_lockId))
                        {
                            // we are no longer main dom, another one has come online, exit
                            _mainDomChanging = true;
                            _logger.Debug <SqlMainDomLock>("Detected new booting application, releasing MainDom lock.");
                            return;
                        }
                    }
                    catch (Exception ex)
                    {
                        ResetDatabase();
                        // unexpected
                        _logger.Error <SqlMainDomLock>(ex, "Unexpected error, listening is canceled.");
                        _hasError = true;
                        return;
                    }
                    finally
                    {
                        db?.CompleteTransaction();
                    }
                }
            }
        }
예제 #2
0
        private void ListeningLoop()
        {
            while (true)
            {
                // poll every couple of seconds
                // local testing shows the actual query to be executed from client/server is approx 300ms but would change depending on environment/IO
                Thread.Sleep(2000);

                if (!_dbFactory.Configured)
                {
                    // if we aren't configured, we just keep looping since we can't query the db
                    continue;
                }

                lock (_locker)
                {
                    // If cancellation has been requested we will just exit. Depending on timing of the shutdown,
                    // we will have already flagged _mainDomChanging = true, or we're shutting down faster than
                    // the other MainDom is taking to startup. In this case the db row will just be deleted and the
                    // new MainDom will just take over.
                    if (_cancellationTokenSource.IsCancellationRequested)
                    {
                        _logger.Debug <SqlMainDomLock>("Task canceled, exiting loop");
                        return;
                    }
                    IUmbracoDatabase db = null;

                    try
                    {
                        db = _dbFactory.CreateDatabase();

                        if (!_hasTable)
                        {
                            // re-check if its still false, we don't want to re-query once we know its there since this
                            // loop needs to use minimal resources
                            _hasTable = db.HasTable(Constants.DatabaseSchema.Tables.KeyValue);
                            if (!_hasTable)
                            {
                                // the Db does not contain the required table, we just keep looping since we can't query the db
                                continue;
                            }
                        }

                        db.BeginTransaction(IsolationLevel.ReadCommitted);
                        // get a read lock
                        _sqlServerSyntax.ReadLock(db, _lockTimeout, Constants.Locks.MainDom);

                        if (!IsMainDomValue(_lockId, db))
                        {
                            // we are no longer main dom, another one has come online, exit
                            _mainDomChanging = true;
                            _logger.Debug <SqlMainDomLock>("Detected new booting application, releasing MainDom lock.");
                            return;
                        }
                    }
                    catch (Exception ex)
                    {
                        _logger.Error <SqlMainDomLock>(ex, "Unexpected error during listening.");

                        // We need to keep on listening unless we've been notified by our own AppDomain to shutdown since
                        // we don't want to shutdown resources controlled by MainDom inadvertently. We'll just keep listening otherwise.
                        if (_cancellationTokenSource.IsCancellationRequested)
                        {
                            _logger.Debug <SqlMainDomLock>("Task canceled, exiting loop");
                            return;
                        }
                    }
                    finally
                    {
                        // Even if any of the above fail like BeginTransaction, or even a query after the
                        // Transaction is started, the calls below will not throw. I've tried all sorts of
                        // combinations to see if I can make this throw but I can't. In any case, we'll be
                        // extra safe and try/catch/log
                        try
                        {
                            db?.CompleteTransaction();
                        }
                        catch (Exception ex)
                        {
                            _logger.Error <SqlMainDomLock>(ex, "Unexpected error completing transaction.");
                        }

                        try
                        {
                            db?.Dispose();
                        }
                        catch (Exception ex)
                        {
                            _logger.Error <SqlMainDomLock>(ex, "Unexpected error completing disposing.");
                        }
                    }
                }
            }
        }
예제 #3
0
        private void ListeningLoop()
        {
            while (true)
            {
                // poll every couple of seconds
                // local testing shows the actual query to be executed from client/server is approx 300ms but would change depending on environment/IO
                Thread.Sleep(_globalSettings.Value.MainDomReleaseSignalPollingInterval);

                if (!_dbFactory.Configured)
                {
                    // if we aren't configured, we just keep looping since we can't query the db
                    continue;
                }

                lock (_locker)
                {
                    // If cancellation has been requested we will just exit. Depending on timing of the shutdown,
                    // we will have already flagged _mainDomChanging = true, or we're shutting down faster than
                    // the other MainDom is taking to startup. In this case the db row will just be deleted and the
                    // new MainDom will just take over.
                    if (_cancellationTokenSource.IsCancellationRequested)
                    {
                        _logger.LogDebug("Task canceled, exiting loop");
                        return;
                    }
                    IUmbracoDatabase db = null;

                    try
                    {
                        db = _dbFactory.CreateDatabase();

                        if (!_hasTable)
                        {
                            // re-check if its still false, we don't want to re-query once we know its there since this
                            // loop needs to use minimal resources
                            _hasTable = db.HasTable(Cms.Core.Constants.DatabaseSchema.Tables.KeyValue);
                            if (!_hasTable)
                            {
                                // the Db does not contain the required table, we just keep looping since we can't query the db
                                continue;
                            }
                        }

                        // In case we acquired the main dom doing install when there was no database. We therefore have to insert our lockId now, but only handle this once.
                        if (_acquireWhenTablesNotAvailable)
                        {
                            _acquireWhenTablesNotAvailable = false;
                            InsertLockRecord(_lockId, db);
                        }

                        db.BeginTransaction(IsolationLevel.ReadCommitted);
                        // get a read lock
                        _sqlServerSyntax.ReadLock(db, Cms.Core.Constants.Locks.MainDom);

                        if (!IsMainDomValue(_lockId, db))
                        {
                            // we are no longer main dom, another one has come online, exit
                            _mainDomChanging = true;
                            _logger.LogDebug("Detected new booting application, releasing MainDom lock.");
                            return;
                        }
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError(ex, "Unexpected error during listening.");

                        // We need to keep on listening unless we've been notified by our own AppDomain to shutdown since
                        // we don't want to shutdown resources controlled by MainDom inadvertently. We'll just keep listening otherwise.
                        if (_cancellationTokenSource.IsCancellationRequested)
                        {
                            _logger.LogDebug("Task canceled, exiting loop");
                            return;
                        }
                    }
                    finally
                    {
                        db?.CompleteTransaction();
                        db?.Dispose();
                    }
                }
            }
        }
예제 #4
0
        private void ListeningLoop()
        {
            while (true)
            {
                // poll every couple of seconds
                // local testing shows the actual query to be executed from client/server is approx 300ms but would change depending on environment/IO
                Thread.Sleep(2000);

                if (!_dbFactory.Configured)
                {
                    // if we aren't configured, we just keep looping since we can't query the db
                    continue;
                }

                if (!_dbFactory.Configured)
                {
                    // if we aren't configured, we just keep looping since we can't query the db
                    continue;
                }

                lock (_locker)
                {
                    // If cancellation has been requested we will just exit. Depending on timing of the shutdown,
                    // we will have already flagged _mainDomChanging = true, or we're shutting down faster than
                    // the other MainDom is taking to startup. In this case the db row will just be deleted and the
                    // new MainDom will just take over.
                    if (_cancellationTokenSource.IsCancellationRequested)
                    {
                        return;
                    }

                    using var db          = _dbFactory.CreateDatabase();
                    using var transaction = db.GetTransaction(IsolationLevel.ReadCommitted);
                    try
                    {
                        // get a read lock
                        _sqlServerSyntax.ReadLock(db, Constants.Locks.MainDom);

                        if (!IsMainDomValue(_lockId, db))
                        {
                            // we are no longer main dom, another one has come online, exit
                            _mainDomChanging = true;
                            _logger.Debug <SqlMainDomLock>("Detected new booting application, releasing MainDom lock.");
                            return;
                        }
                    }
                    catch (Exception ex)
                    {
                        _logger.Error <SqlMainDomLock>(ex, "Unexpected error during listening.");

                        // We need to keep on listening unless we've been notified by our own AppDomain to shutdown since
                        // we don't want to shutdown resources controlled by MainDom inadvertently. We'll just keep listening otherwise.
                        if (_cancellationTokenSource.IsCancellationRequested)
                        {
                            return;
                        }
                    }
                    finally
                    {
                        transaction.Complete();
                    }
                }
            }
        }