Example #1
0
        /// <summary>
        /// Add a new item to the database
        /// </summary>
        /// <param name="fileIndexItem">the item</param>
        /// <returns>item with id</returns>
        public virtual async Task <FileIndexItem> AddItemAsync(FileIndexItem fileIndexItem)
        {
            async Task <FileIndexItem> LocalDefaultQuery()
            {
                var context = new InjectServiceScope(_scopeFactory).Context();

                return(await LocalQuery(context));
            }

            async Task <FileIndexItem> LocalQuery(ApplicationDbContext context)
            {
                // only in test case fileIndex is null
                if (context.FileIndex != null)
                {
                    await context.FileIndex.AddAsync(fileIndexItem);
                }
                await context.SaveChangesAsync();

                // Fix for: The instance of entity type 'Item' cannot be tracked because
                // another instance with the same key value for {'Id'} is already being tracked
                context.Entry(fileIndexItem).State = EntityState.Unchanged;
                AddCacheItem(fileIndexItem);
                return(fileIndexItem);
            }

            try
            {
                return(await LocalQuery(_context));
            }
            catch (Microsoft.Data.Sqlite.SqliteException e)
            {
                _logger?.LogInformation(e, $"catch-ed SqliteException going to retry 2 times {fileIndexItem.FilePath}");
                return(await RetryHelper.DoAsync(
                           LocalDefaultQuery, TimeSpan.FromSeconds(2), 2));
            }
            catch (DbUpdateException e)
            {
                _logger?.LogInformation(e, $"catch-ed DbUpdateException going to retry 2 times {fileIndexItem.FilePath}");
                return(await RetryHelper.DoAsync(
                           LocalDefaultQuery, TimeSpan.FromSeconds(2), 2));
            }
            catch (ObjectDisposedException)
            {
                var context = new InjectServiceScope(_scopeFactory).Context();
                return(await LocalQuery(context));
            }
        }
Example #2
0
        /// <summary>
        /// Retry when an Exception has occured
        /// </summary>
        /// <param name="updateStatusContent"></param>
        /// <param name="e">Exception</param>
        private async Task RetrySaveChangesAsync(FileIndexItem updateStatusContent, Exception e)
        {
            _logger?.LogInformation(e, "[RetrySaveChangesAsync] retry catch-ed exception ");
            _logger?.LogInformation("[RetrySaveChangesAsync] next retry ~>");

            async Task LocalRetrySaveChangesAsyncQuery()
            {
                // InvalidOperationException: A second operation started on this context before a previous operation completed.
                // https://go.microsoft.com/fwlink/?linkid=2097913
                await Task.Delay(5);

                var context = new InjectServiceScope(_scopeFactory).Context();

                context.Attach(updateStatusContent).State = EntityState.Modified;
                await context.SaveChangesAsync();

                context.Attach(updateStatusContent).State = EntityState.Detached;
                await context.DisposeAsync();
            }

            try
            {
                await LocalRetrySaveChangesAsyncQuery();
            }
            catch (MySqlException mySqlException)
            {
                _logger?.LogError(mySqlException, "[RetrySaveChangesAsync] MySqlException catch-ed and retry again");
                await LocalRetrySaveChangesAsyncQuery();
            }
            catch (DbUpdateConcurrencyException concurrencyException)
            {
                SolveConcurrency.SolveConcurrencyExceptionLoop(concurrencyException.Entries);
                try
                {
                    _logger?.LogInformation("[RetrySaveChangesAsync] SolveConcurrencyExceptionLoop disposed item");
                    var context = new InjectServiceScope(_scopeFactory).Context();
                    await context.SaveChangesAsync();
                }
                catch (DbUpdateConcurrencyException retry2Exception)
                {
                    _logger?.LogInformation(retry2Exception,
                                            "[RetrySaveChangesAsync] save failed after DbUpdateConcurrencyException");
                }
            }
        }