private async Task FlushCurrentBufferAsync(int?ownedDocumentIndex)
        {
            IEnumerable <BulkInsertItemState> response = null;

            try
            {
                response = await Client.ExecuteStoredProcedureAsync <IEnumerable <BulkInsertItemState> >(storedProcedureLink, surrogate, Configuration.DisableIdGeneration);
            }
            catch (Exception exception)
            {
                // In case of a stored procedure failure - fail all items: sorry, it's a bulk operation :)
                FailAllActiveBatches(exception, ownedDocumentIndex.HasValue);

                // If executing as part of the write - rethrow, otherwise ignore - will be reported on the item's task
                if (ownedDocumentIndex.HasValue)
                {
                    throw;
                }

                return;
            }

            // Clean-up the buffer, because as soon as we start reporting completion - more items will be added, and buffer is not thread-safe
            buffer.SkipForward(response.Count());

            Exception ownedDocumentError = null;

            foreach (var item in response)
            {
                var itemError = String.IsNullOrEmpty(item.ErrorMessage) ? null : Errors.FailedToCreateDocument(item.ErrorMessage);

                TaskCompletionSource <object> waitHandle;
                if (!activeBulkItems.TryRemove(item.DocumentIndex, out waitHandle))
                {
                    // We are in the task that is responsible to report the state of the document, preserve the error
                    if (item.DocumentIndex == ownedDocumentIndex && itemError != null)
                    {
                        ownedDocumentError = itemError;
                    }
                    continue;
                }

                if (itemError == null)
                {
                    waitHandle.SetResult(null);
                }
                else
                {
                    waitHandle.SetException(itemError);
                }
            }

            if (ownedDocumentError != null)
            {
                throw ownedDocumentError;
            }
        }
예제 #2
0
        private async Task FlushWhileAsync(Func <bool> condition, bool lockAcquired, CancellationToken cancellationToken)
        {
            // NOTE: This task will run in the background, so we need to make sure it is robust enough

            try
            {
                while (condition())
                {
                    if (lockAcquired)
                    {
                        // Actual lock will be released in the finally
                        lockAcquired = false;
                    }
                    else
                    {
                        await flushSemaphore.WaitAsync(cancellationToken);
                    }

                    IEnumerable <BulkInsertItemState> response;
                    try
                    {
                        if (!condition())
                        {
                            continue;
                        }

                        response = await FlushCurrentBufferAsync();

                        buffer.SkipForward(response.Count());
                    }
                    finally
                    {
                        flushSemaphore.Release();
                    }

                    ReportTasksStatus(response);
                }
            }
            finally
            {
                if (lockAcquired)
                {
                    // If while condition was not satisfied - finally block did not execute, release the lock
                    flushSemaphore.Release();
                }
            }
        }