public async Task AddNewFiltersAsync(IEnumerable <FilterModel> filters, CancellationToken cancel) { var successAny = false; foreach (var filter in filters) { var success = false; using (await IndexLock.LockAsync(cancel).ConfigureAwait(false)) { success = TryProcessFilter(filter, enqueue: true); } successAny = successAny || success; if (success) { NewFilter?.Invoke(this, filter); // Event always outside the lock. } } if (successAny) { AbandonedTasks.AddAndClearCompleted(TryCommitToFileAsync(TimeSpan.FromSeconds(3), cancel)); } }
public async Task AddNewFiltersAsync(IEnumerable <FilterModel> filters, CancellationToken cancel) { foreach (var filter in filters) { using (await IndexLock.LockAsync()) { ProcessFilter(filter, enqueue: true); } NewFilter?.Invoke(this, filter); // Event always outside the lock. } _ = TryCommitToFileAsync(TimeSpan.FromSeconds(3), cancel); }
private void OnNewFilter(FilterModel filter) => NewFilter?.Invoke(this, filter);
public void Synchronize(TimeSpan requestInterval) { Guard.NotNull(nameof(requestInterval), requestInterval); Interlocked.Exchange(ref _running, 1); Task.Run(async() => { FilterModel bestKnownFilter = null; try { while (IsRunning) { try { // If stop was requested return. if (IsRunning == false) { return; } using (await IndexLock.LockAsync()) { bestKnownFilter = Index.Last(); } var filters = await WasabiClient.GetFiltersAsync(bestKnownFilter.BlockHash, 1000); if (!filters.Any()) { continue; } using (await IndexLock.LockAsync()) { var filtersList = filters.ToList(); // performance for (int i = 0; i < filtersList.Count; i++) { var filterModel = FilterModel.FromLine(filtersList[i], bestKnownFilter.BlockHeight + i + 1); Index.Add(filterModel); NewFilter?.Invoke(this, filterModel); } if (filtersList.Count == 1) // minor optimization { await File.AppendAllLinesAsync(IndexFilePath, new[] { Index.Last().ToLine() }); } else { await File.WriteAllLinesAsync(IndexFilePath, Index.Select(x => x.ToLine())); } Logger.LogInfo <IndexDownloader>($"Downloaded filters for blocks from {bestKnownFilter.BlockHeight.Value + 1} to {Index.Last().BlockHeight}."); } continue; } catch (HttpRequestException ex) when(ex.Message.StartsWith(HttpStatusCode.NotFound.ToReasonString())) { // Reorg happened var reorgedHash = bestKnownFilter.BlockHash; Logger.LogInfo <IndexDownloader>($"REORG Invalid Block: {reorgedHash}"); // 1. Rollback index using (await IndexLock.LockAsync()) { Index.RemoveAt(Index.Count - 1); } Reorged?.Invoke(this, reorgedHash); // 2. Serialize Index. (Remove last line.) var lines = File.ReadAllLines(IndexFilePath); File.WriteAllLines(IndexFilePath, lines.Take(lines.Length - 1).ToArray()); // 3. Skip the last valid block. continue; } catch (Exception ex) { Logger.LogError <IndexDownloader>(ex); } finally { await Task.Delay(requestInterval); // Ask for new index in every requestInterval. } } } finally { if (IsStopping) { Interlocked.Exchange(ref _running, 3); } } }); }
public static void Main(string[] args) { #region Single responsibility var j = new Journal(); j.AddEntry("hi"); j.AddEntry("hello world"); Console.WriteLine(j); //Console.ReadKey(); var p = new Persistance(); string fileName = @"C:\LOG\test.txt"; p.SaveFile(j, fileName, true); Process.Start(fileName); #endregion #region Open-closed principle var apple = new Product("Apple", Color.Green, Size.Small); var tree = new Product("Tree", Color.Green, Size.Large); var house = new Product("House", Color.Blue, Size.Large); Product[] products = { apple, tree, house }; var nf = new NewFilter(); Console.WriteLine("Green products"); var result1 = nf.Filter(products, new ColorSpecification(Color.Green)); foreach (var i in result1) { Console.WriteLine($" - {i.Name} is green"); } Console.WriteLine("Large products"); var result2 = nf.Filter(products, new SizeSpecification(Size.Large)); foreach (var i in result2) { Console.WriteLine($" - {i.Name} is large"); } Console.WriteLine("Blue and Large products"); var result3 = nf.Filter(products, new AndSpecification <Product> (new ColorSpecification(Color.Blue), new SizeSpecification(Size.Large) ) ); foreach (var i in result3) { Console.WriteLine($" - {i.Name} is large and blue"); } Console.ReadKey(); #endregion #region liskov principle Rectangle rec = new Rectangle(4, 3); var d = new Demo(); Console.WriteLine($"the area of the rectangle {rec} is {d.Area(rec)}"); Rectangle sq = new Square(); sq.Width = 5; Console.WriteLine($"the area of the square {sq} is {d.Area(sq)}"); Console.ReadKey(); #endregion #region DI principle var parent = new Person("John"); var child1 = new Person("Matt"); var child2 = new Person("Test"); Relationships rel = new Relationships(); rel.AddParentAndChild(parent, child1); rel.AddParentAndChild(parent, child2); Research rs = new Research(rel); Console.ReadKey(); #endregion }
public void Synchronize(TimeSpan requestInterval) { Guard.NotNull(nameof(requestInterval), requestInterval); Interlocked.Exchange(ref _running, 1); Task.Run(async() => { try { while (IsRunning) { try { // If stop was requested return. if (IsRunning == false) { return; } FilterModel bestKnownFilter; using (await IndexLock.LockAsync()) { bestKnownFilter = Index.Last(); } var response = await Client.SendAsync(HttpMethod.Get, $"/api/v1/btc/blockchain/filters?bestKnownBlockHash={bestKnownFilter.BlockHash}&count=1000"); if (response.StatusCode == HttpStatusCode.NoContent) { continue; } if (response.StatusCode == HttpStatusCode.OK) { var filters = await response.Content.ReadAsJsonAsync <List <string> >(); using (await IndexLock.LockAsync()) { for (int i = 0; i < filters.Count; i++) { var filterModel = FilterModel.FromLine(filters[i], bestKnownFilter.BlockHeight + i + 1); Index.Add(filterModel); NewFilter?.Invoke(this, filterModel); } if (filters.Count == 1) // minor optimization { await File.AppendAllLinesAsync(IndexFilePath, new[] { Index.Last().ToLine() }); } else { await File.WriteAllLinesAsync(IndexFilePath, Index.Select(x => x.ToLine())); } Logger.LogInfo <IndexDownloader>($"Downloaded filters for blocks from {bestKnownFilter.BlockHeight.Value + 1} to {Index.Last().BlockHeight}."); } continue; } else if (response.StatusCode == HttpStatusCode.NotFound) { // Reorg happened var reorgedHash = bestKnownFilter.BlockHash; Logger.LogInfo <IndexDownloader>($"REORG Invalid Block: {reorgedHash}"); // 1. Rollback index using (await IndexLock.LockAsync()) { Index.RemoveAt(Index.Count - 1); } Reorged?.Invoke(this, reorgedHash); // 2. Serialize Index. (Remove last line.) var lines = File.ReadAllLines(IndexFilePath); File.WriteAllLines(IndexFilePath, lines.Take(lines.Length - 1).ToArray()); // 3. Skip the last valid block. continue; } else { var error = await response.Content.ReadAsStringAsync(); throw new HttpRequestException($"{response.StatusCode.ToReasonString()}: {error}"); } } catch (Exception ex) { Logger.LogError <IndexDownloader>(ex); } finally { await Task.Delay(requestInterval); // Ask for new index in every requestInterval. } } } finally { if (IsStopping) { Interlocked.Exchange(ref _running, 3); } } }); }