Skip to main content

Posts

Event sourcing instead of multiple resource transactions

In the previous post ( here ) I tried to describe the common transactional problems people deal with when it comes to communication via messages. In short - we need to dispatch or consume a message (or both) and store data in DB and we would like all those operations to be in one transaction. In order to understand where event sourcing comes from we need to look at how most of the modern databases work. I`ll use MS SQL as an example but with some variations it can apply to almost any relational db. If you look at the DB files you`ll find two types of files: DB file itself (.mdf in ms SQL) and a transactional log file(,ldf) Why we need two? Because MS SQL uses Write-Ahead Transaction Log pattern. If we simplify the process it looks about this: add transactions to commit log  tail commit-log and build DB (projection) based on that data  All writes go via commit log, all reads are hitting our projection. (Sounds like CQRS? Yep, that's it) Why does it matter?  Because m...
Recent posts

Resiliency in distributed messaging

A common unit of work in a distributed system involves at least two things: 1) Storing the result of work to DB 2) Notifying consumers about the changes The problem is - they often can't be done in the same transaction: Kafka, Redis, RabitMQ, AlmostAnyCloud messaging system - they all don't support XA transactions. ( And not because they are lazy to implement one, but that deserves a separate post ) Let's say we have a transaction scope opened(Tb) and we want to store some changes to DB and dispatch an event: Tb -> DB -> Message -> Tc  Looks valid, right? If DB changes fail we will rollback DB transaction. If dispatching an event failed, we still rollback. Seems quite transactional, where is the problem ¯\(°_o)/¯? Problem 1: Leaked notifications: on failure The problem is with the last part:  Tc  - Transaction commit (end) Why would it fail? It can be a network outage Our DB transaction can timeout while we are dispatching messages SQL Server might run ou...

.NET Core code coverage - the simplest ever solution

Ever wanted to see test coverage of your solution? 0. add coverlet.collector nuget  to test project 1. Install reporting tool:  dotnet tool install -g dotnet-reportgenerator-globaltool  2. Run tests and store results in a temp folder (you don't want those result file trashing your solution folder): dotnet test --collect:"XPlat Code Coverage" -r $env:TEMP\CodeCoverage;  or if you want to exclude some files, just add runsettings.xml: dotnet test --settings runsettings.xml -r $env:TEMP\CodeCoverage;  3. Generate report: Test results will be stored in a folder with guid, so the tricky part here is to find the lastest created folder  reportgenerator -reports:((gci $env:TEMP\CodeCoverage | sort CreationTime -desc | select -f 1).FullName +"\coverage.cobertura.xml") -targetdir:$env:TEMP\CodeCoverResult -reporttypes:Html; 4. Open it: start $env:TEMP\CodeCoverResult\index.html Join all in one PowerShell file and enjoy one-click code coverage or use...

Avoiding distributed transactions (DTC) with SQL Server and async code

Wrapping async code in transaction scope is not as straightforward as sync one. Let's say we have some simple code: await using (var connection = new SqlConnection(connectionString)) { await using var command = new SqlCommand("select 1", connection); await connection.OpenAsync(); await command.ExecuteScalarAsync(); } We can wrap it in transaction scope and test that it still works: using var ts = new TransactionScope(); await using (var connection = new SqlConnection(connectionString)) { await using var command = new SqlCommand("select 1", connection); await connection.OpenAsync(); await command.ExecuteScalarAsync(); } ts.Complete(); But if you try to run this code you will get: "A TransactionScope must be disposed on the same thread that it was created" exception.  The fix is easy: we need to add TransactionScopeAsyncFlowOption.Enabled option to the constructor: var options = new TransactionOptions { IsolationLevel = IsolationLevel.ReadCom...

Visual studio 2019 + Resharper. Performance tweaks

Recently had to move from one pc to another and got a feeling that Visual studio got a bit slower on startup and project load. In addition to that, the text became blurry, so I had to google what has changed recently and how to get back proper VS experience.  Writing this post for myself to remember where to look at next time 😊 High resolution: DPI problems on big screens are solved with a setting "optimize rendering for screens with different pixel densities . (Using build in search helps to find option without clicking here and there).  As text suggested, right after restart everything got sharp again. Visual studio settings: The first improvements suggest I found was to disable options ‘reopen docs on solution load’ and ‘restore projects hierarchy’ The next set of options comes from preview features: Autohide tool window and startup and ‘new git experience’ if you use git. Resharper: For those who use Resharper, jetbrains prepared a nice set of features you can enable to m...