internal async Task CreateAsync(UrlItem urlItem) { // Add item to database _dbContext.Urls.Add(urlItem); var success = false; Exception?lastException = null; // Try max 10 times before giving up string key = null; for (var i = 0; i < 10; i++) { // Create random id key = Helpers.GetRandomKey(_config.Url); // Try to add item to database urlItem.Key = key; try { await _dbContext.SaveChangesAsync(); success = true; } catch (DbUpdateException dbUpdateException) when((dbUpdateException.InnerException as SqlException)?.Number == 2601) { // Already exists: We need to retry _logger.LogInformation(dbUpdateException, $"Collision creating ShortUrl: {urlItem.Key}"); lastException = dbUpdateException; continue; } catch (Exception exception) { // Not sure what is wrong, log it and try again _logger.LogError(exception, $"Creating new ShortUrl: {JsonSerializer.Serialize(urlItem)}"); lastException = exception; continue; } } // Not success: Throw last error if (!success) { throw lastException !; } // Success: Add item to recent used cache since it will probably be used immediately var cacheEntryOptions = new MemoryCacheEntryOptions(); cacheEntryOptions.Size = 1; _cache.Set <UrlItem>(key, urlItem, cacheEntryOptions); }
internal Task Save() { return(ShortUrlDbContext.SaveChangesAsync()); }