/// <inheritdoc /> public void Start(CancellationToken token) { // check that the file does exists. if (!File.Exists(_config.Source)) { try { SQLiteConnection.CreateFile(_config.Source); } catch (Exception ex) { _logger.Exception(ex); throw new FileNotFoundException(); } } // the connection string var connectionString = $"Data Source={_config.Source};Version=3;Pooling=True;Max Pool Size=100;"; // the readonly. _connectionReadOnly = new SQLiteConnection($"{connectionString}Read Only=True;"); _connectionReadOnly.Open(); // create the connection spinner and pass the function to create transactions. _transactionSpinner = new TransactionsManager(_performance, _logger); // initiialise everything Initialise(token).GetAwaiter().GetResult(); }
/// <summary> /// Given a list of words, re-create the ones that we need to insert. /// </summary> /// <param name="words"></param> /// <param name="token"></param> /// <returns></returns> private async Task <IList <long> > InsertWordsAsync( interfaces.IO.IWords words, CancellationToken token) { // if we have nothing to do... we are done. if (!words.Any()) { return(new List <long>()); } // the ids of the words we just added var ids = new List <long>(words.Count); try { foreach (var word in words) { // get out if needed. token.ThrowIfCancellationRequested(); // if the word is not valid, there isn't much we can do. if (!IsValidWord(word)) { continue; } // the word we want to insert. var wordId = await InsertWordAsync(word, token).ConfigureAwait(false); if (-1 == wordId) { // we log errors in the insert function continue; } // we added this id. ids.Add(wordId); } // all done, return whatever we did. return(ids); } catch (OperationCanceledException) { _logger.Warning("Received cancellation request - Insert multiple words"); throw; } catch (Exception ex) { _logger.Exception(ex); throw; } }
/// <inheritdoc /> public async Task <long> WorkAsync(CancellationToken token) { // check if we are active at the current time. if (!_active.IsActive()) { // we are not active ... so we have nothing to do. _logger.Verbose("Maintenance Process ignored, out of active hours."); return(0); } var stopwatch = new Stopwatch(); stopwatch.Start(); var success = false; try { _logger.Information("Started Maintenance Process."); await _persister.MaintenanceAsync(token).ConfigureAwait(false); await _parser.MaintenanceAsync(token).ConfigureAwait(false); // it worked success = true; } catch (OperationCanceledException) { // nothing to log throw; } catch (Exception e) { _logger.Exception("Error while processing Maintenance.", e); throw; } finally { _logger.Information(success ? $"Complete Maintenance Process (Time Elapsed: {stopwatch.Elapsed:g})." : $"Complete Maintenance Process with errors (Time Elapsed: {stopwatch.Elapsed:g})."); } return(0); }
/// <inheritdoc /> public async Task MaintenanceAsync(CancellationToken token) { lock (_taskLock) { // are we still running the start? if (!_runningTask?.IsCompleted ?? true) { return; } } var factory = await _persister.BeginWrite(token).ConfigureAwait(false); try { const string configParse = "maintenance.parse"; var lastParse = await _persister.Config.GetConfigValueAsync(configParse, DateTime.MinValue, factory, token).ConfigureAwait(false); // between 3 and 5 hours to prevent running at the same time as others. var randomHours = (new Random(DateTime.UtcNow.Millisecond)).Next(3, 5); if ((DateTime.UtcNow - lastParse).TotalHours > randomHours) { // // Do maintenance work // _logger.Information("Maintenance files/folders parser"); // save the date and commit ... because the parser needs its own factory. await _persister.Config.SetConfigValueAsync(configParse, DateTime.UtcNow, factory, token).ConfigureAwait(false); } _persister.Commit(factory); } catch (Exception e) { _persister.Rollback(factory); _logger.Exception("There was an exception re-parsing the directories.", e); throw; } }