示例#1
0
        public AsyncSubject <Unit> Vacuum()
        {
            // Vacuum is a special snowflake. We want to delete all the expired rows before
            // actually vacuuming. Unfortunately vacuum can't be run in a transaction so we'll
            // claim an exclusive lock on the queue, drain it and run the delete first before
            // running our vacuum op without any transactions.
            var ret = new AsyncSubject <Unit>();

            Task.Run(async() =>
            {
                IDisposable @lock = null;
                try
                {
                    // NB. While the documentation for SemaphoreSlim (which powers AsyncLock)
                    // doesn't guarantee ordering the actual (current) implementation[1]
                    // uses a linked list to queue incoming requests so by adding ourselves
                    // to the queue first and then sending a no-op to the main queue to
                    // force it to finish up and release the lock we avoid any potential
                    // race condition where the main queue reclaims the lock before we
                    // have had a chance to acquire it.
                    //
                    // 1. http://referencesource.microsoft.com/#mscorlib/system/threading/SemaphoreSlim.cs,d57f52e0341a581f
                    var lockTask = flushLock.LockAsync(shouldQuit.Token);
                    operationQueue.Add(OperationQueueItem.CreateUnit(OperationType.DoNothing));

                    try
                    {
                        @lock = await lockTask;
                    }
                    catch (OperationCanceledException) { }

                    var deleteOp = OperationQueueItem.CreateUnit(OperationType.DeleteExpiredSqliteOperation);
                    operationQueue.Add(deleteOp);

                    FlushInternal();

                    await deleteOp.CompletionAsUnit;

                    var vacuumOp = OperationQueueItem.CreateUnit(OperationType.VacuumSqliteOperation);

                    MarshalCompletion(vacuumOp.Completion, vacuum.Value.PrepareToExecute(), Observable.Return(Unit.Default));

                    await vacuumOp.CompletionAsUnit;
                }
                finally
                {
                    if (@lock != null)
                    {
                        @lock.Dispose();
                    }
                }
            })
            .ToObservable()
            .ObserveOn(scheduler)
            .Multicast(ret)
            .PermaRef();

            return(ret);
        }
示例#2
0
        public AsyncSubject <Unit> InvalidateAll()
        {
            var ret = OperationQueueItem.CreateUnit(OperationType.InvalidateAllSqliteOperation);

            _operationQueue.Add(ret);

            return(ret.CompletionAsUnit);
        }
示例#3
0
        public IObservable <Unit> Flush()
        {
            var noop = OperationQueueItem.CreateUnit(OperationType.DoNothing);

            _operationQueue.Add(noop);

            return(noop.CompletionAsUnit);
        }
示例#4
0
        public AsyncSubject <Unit> Vacuum()
        {
            var ret = OperationQueueItem.CreateUnit(OperationType.VacuumSqliteOperation);

            operationQueue.Add(ret);

            return(ret.CompletionAsUnit);
        }
示例#5
0
        public IObservable <Unit> Flush()
        {
            var ret = new AsyncSubject <Unit>();

            return(Task.Run(async() =>
            {
                // NB: We add a "DoNothing" operation so that the thread waiting
                // on an item will always have one instead of waiting the full timeout
                // before we can run the flush
                operationQueue.Add(OperationQueueItem.CreateUnit(OperationType.DoNothing));

                using (await flushLock.LockAsync())
                {
                    FlushInternal();
                }
            }).ToObservable());
        }
示例#6
0
        public IObservable <Unit> Flush()
        {
            var ret = new AsyncSubject <Unit>();

            return(Task.Run(async() =>
            {
                // NB: We add a "DoNothing" operation so that the thread waiting
                // on an item will always have one instead of waiting the full timeout
                // before we can run the flush
                operationQueue.Add(OperationQueueItem.CreateUnit(OperationType.DoNothing));

                using (await flushLock.LockAsync())
                {
                    var newQueue = new BlockingCollection <OperationQueueItem>();
                    var existingItems = Interlocked.Exchange(ref operationQueue, newQueue).ToList();

                    ProcessItems(CoalesceOperations(existingItems));
                }
            }).ToObservable());
        }
示例#7
0
        public AsyncSubject <Unit> Vacuum()
        {
            // Vacuum is a special snowflake. We want to delete all the expired rows before
            // actually vacuuming. Unfortunately vacuum can't be run in a transaction so we'll
            // claim an exclusive lock on the queue, drain it and run the delete first before
            // running our vacuum op without any transactions.
            var ret = new AsyncSubject <Unit>();

            Task.Run(async() =>
            {
                // NB: We add a "DoNothing" operation so that the thread waiting
                // on an item will always have one instead of waiting the full timeout
                // before we can run the flush
                operationQueue.Add(OperationQueueItem.CreateUnit(OperationType.DoNothing));

                using (await flushLock.LockAsync())
                {
                    var deleteOp = OperationQueueItem.CreateUnit(OperationType.DeleteExpiredSqliteOperation);
                    operationQueue.Add(deleteOp);

                    FlushInternal();

                    await deleteOp.CompletionAsUnit;

                    var vacuumOp = OperationQueueItem.CreateUnit(OperationType.VacuumSqliteOperation);

                    MarshalCompletion(vacuumOp.Completion, vacuum.PrepareToExecute(), Observable.Return(Unit.Default));

                    await vacuumOp.CompletionAsUnit;
                }
            })
            .ToObservable()
            .ObserveOn(scheduler)
            .Multicast(ret)
            .PermaRef();

            return(ret);
        }