Exemplo n.º 1
0
        public void Cleanup(string db, bool skipIfActive, Func <TResource, bool> shouldSkip = null)
        {
            using (ResourcesStoresCache.WithAllLocks())
            {
                DateTime         time;
                Task <TResource> databaseTask;
                if (ResourcesStoresCache.TryGetValue(db, out databaseTask) == false)
                {
                    LastRecentlyUsed.TryRemove(db, out time);
                    return;
                }
                if (databaseTask.Status == TaskStatus.Faulted || databaseTask.Status == TaskStatus.Canceled)
                {
                    LastRecentlyUsed.TryRemove(db, out time);
                    ResourcesStoresCache.TryRemove(db, out databaseTask);
                    return;
                }
                if (databaseTask.Status != TaskStatus.RanToCompletion)
                {
                    return; // still starting up
                }

                var database = databaseTask.Result;
                if ((skipIfActive &&
                     (SystemTime.UtcNow - LastWork(database)).TotalMinutes < 10) ||
                    (shouldSkip != null && shouldSkip(database)))
                {
                    // this document might not be actively working with user, but it is actively doing indexes, we will
                    // wait with unloading this database until it hasn't done indexing for a while.
                    // This prevent us from shutting down big databases that have been left alone to do indexing work.
                    return;
                }
                try
                {
                    database.Dispose();
                }
                catch (Exception e)
                {
                    Logger.ErrorException("Could not cleanup tenant database: " + db, e);
                    return;
                }
                LastRecentlyUsed.TryRemove(db, out time);
                ResourcesStoresCache.TryRemove(db, out databaseTask);

                var onDatabaseCleanupOccured = CleanupOccured;
                if (onDatabaseCleanupOccured != null)
                {
                    onDatabaseCleanupOccured(db);
                }
            }
        }
Exemplo n.º 2
0
        protected void CleanupDatabase(string db, bool skipIfActive)
        {
            using (ResourcesStoresCache.WithAllLocks())
            {
                DateTime time;
                Task <DocumentDatabase> databaseTask;
                if (ResourcesStoresCache.TryGetValue(db, out databaseTask) == false)
                {
                    databaseLastRecentlyUsed.TryRemove(db, out time);
                    return;
                }
                if (databaseTask.Status == TaskStatus.Faulted || databaseTask.Status == TaskStatus.Canceled)
                {
                    databaseLastRecentlyUsed.TryRemove(db, out time);
                    ResourcesStoresCache.TryRemove(db, out databaseTask);
                    return;
                }
                if (databaseTask.Status != TaskStatus.RanToCompletion)
                {
                    return;                     // still starting up
                }

                var database = databaseTask.Result;
                if (skipIfActive && (SystemTime.UtcNow - database.WorkContext.LastWorkTime).TotalMinutes < 5)
                {
                    // this document might not be actively working with user, but it is actively doing indexes, we will
                    // wait with unloading this database until it hasn't done indexing for a while.
                    // This prevent us from shutting down big databases that have been left alone to do indexing work.
                    return;
                }
                try
                {
                    database.Dispose();
                }
                catch (Exception e)
                {
                    logger.ErrorException("Could not cleanup tenant database: " + db, e);
                    return;
                }
                databaseLastRecentlyUsed.TryRemove(db, out time);
                ResourcesStoresCache.TryRemove(db, out databaseTask);
            }
        }
Exemplo n.º 3
0
        private DatabaseConnectionState GetOrAddConnectionState(string name, string watchCommand, string unwatchCommand, string value)
        {
            var counter = _counters.GetOrAdd(name, s =>
            {
                async Task OnDisconnect()
                {
                    try
                    {
                        if (Connected)
                        {
                            await Send(unwatchCommand, value).ConfigureAwait(false);
                        }
                    }
                    catch (WebSocketException)
                    {
                        // if we are not connected then we unsubscribed already
                        // because connections drops with all subscriptions
                    }

                    DatabaseConnectionState state;
                    if (_counters.TryRemove(s, out state))
                    {
                        state.Dispose();
                    }
                }

                async Task <bool> OnConnect()
                {
                    try
                    {
                        if (Connected)
                        {
                            await Send(watchCommand, value).ConfigureAwait(false);
                            return(true);
                        }
                    }
                    catch (WebSocketException)
                    {
                        // if we are not connected then we will subscribe again after connection be established
                    }

                    return(false);
                }

                return(new DatabaseConnectionState(this, OnConnect, OnDisconnect));
            });

            return(counter);
        }
Exemplo n.º 4
0
        private DatabaseConnectionState GetOrAddConnectionState(string name, string watchCommand, string unwatchCommand, string value)
        {
            bool newValue = false;
            var  counter  = _counters.GetOrAdd(name, s =>
            {
                async Task OnDisconnect()
                {
                    try
                    {
                        if (Connected)
                        {
                            await Send(unwatchCommand, value).ConfigureAwait(false);
                        }
                    }
                    catch (WebSocketException)
                    {
                        // if we are not connected then we unsubscribed already
                        // because connections drops with all subscriptions
                    }

                    if (_counters.TryRemove(s, out var state))
                    {
                        state.Dispose();
                    }
                }

                async Task OnConnect()
                {
                    await Send(watchCommand, value).ConfigureAwait(false);
                }

                newValue = true;
                return(new DatabaseConnectionState(OnConnect, OnDisconnect));
            });

            // try to reconnect
            if (newValue && Volatile.Read(ref _immediateConnection) != 0)
            {
                counter.Set(counter.OnConnect());
            }

            return(counter);
        }
Exemplo n.º 5
0
        private void ExecuteTimer(object state)
        {
            var span = state.ToString();
            Tuple <Timer, ConcurrentSet <IRepeatedAction> > tuple;

            if (timers.TryGetValue(span, out tuple) == false)
            {
                return;
            }

            foreach (var repeatedAction in tuple.Item2)
            {
                if (repeatedAction.IsValid == false)
                {
                    tuple.Item2.TryRemove(repeatedAction);
                }

                try
                {
                    repeatedAction.Execute();
                }
                catch (Exception e)
                {
                    logger.ErrorException("Could not execute repeated task", e);
                }
            }

            if (tuple.Item2.Count != 0)
            {
                return;
            }

            if (timers.TryRemove(span, out tuple) == false)
            {
                return;
            }

            tuple.Item1.Dispose();
        }
Exemplo n.º 6
0
        public void Cleanup(string resource,
                            TimeSpan?skipIfActiveInDuration,
                            Func <TResource, bool> shouldSkip    = null,
                            DocumentChangeTypes notificationType = DocumentChangeTypes.None)
        {
            if (Cleanups.TryAdd(resource, new ManualResetEvent(false)) == false)
            {
                return;
            }

            try
            {
                using (ResourcesStoresCache.WithAllLocks())
                {
                    DateTime         time;
                    Task <TResource> resourceTask;
                    if (ResourcesStoresCache.TryGetValue(resource, out resourceTask) == false)
                    {
                        LastRecentlyUsed.TryRemove(resource, out time);
                        return;
                    }
                    if (resourceTask.Status == TaskStatus.Faulted || resourceTask.Status == TaskStatus.Canceled)
                    {
                        LastRecentlyUsed.TryRemove(resource, out time);
                        ResourcesStoresCache.TryRemove(resource, out resourceTask);
                        return;
                    }
                    if (resourceTask.Status != TaskStatus.RanToCompletion)
                    {
                        return;                 // still starting up
                    }

                    var database = resourceTask.Result;
                    if ((skipIfActiveInDuration != null && (SystemTime.UtcNow - LastWork(database)) < skipIfActiveInDuration) ||
                        (shouldSkip != null && shouldSkip(database)))
                    {
                        // this document might not be actively working with user, but it is actively doing indexes, we will
                        // wait with unloading this database until it hasn't done indexing for a while.
                        // This prevent us from shutting down big databases that have been left alone to do indexing work.
                        return;
                    }
                    try
                    {
                        database.Dispose();
                    }
                    catch (Exception e)
                    {
                        Logger.ErrorException("Could not cleanup tenant database: " + resource, e);
                        return;
                    }

                    LastRecentlyUsed.TryRemove(resource, out time);
                    ResourcesStoresCache.TryRemove(resource, out resourceTask);

                    if (notificationType == DocumentChangeTypes.Delete)
                    {
                        TransportState transportState;
                        ResourseTransportStates.TryRemove(resource, out transportState);
                        if (transportState != null)
                        {
                            transportState.Dispose();
                        }
                    }

                    var onResourceCleanupOccured = CleanupOccured;
                    if (onResourceCleanupOccured != null)
                    {
                        onResourceCleanupOccured(resource);
                    }
                }
            }
            finally
            {
                ManualResetEvent cleanupLock;
                if (Cleanups.TryRemove(resource, out cleanupLock))
                {
                    cleanupLock.Set();
                }
            }
        }