public async Task SingleThreadedOpenAndCloseOfSameFile() { using var db1 = DisposableFile.GenerateInTemp("db", 1); var cs = db1.ConnectionString; await using var duckDBConnection = new DuckDBConnection(cs); await duckDBConnection.OpenAsync(); var createTable = "CREATE TABLE INSERTIONS(TASK_ID INTEGER, INSERTION_INDEX INTEGER);"; await duckDBConnection.ExecuteAsync(createTable); await using var dd1 = new DuckDBConnection(cs); await using var dd2 = new DuckDBConnection(cs); const int reps = 10; for (int i = 0; i < reps; i++) { Console.WriteLine(i); await dd1.OpenAsync(); var insertAValue = $"INSERT INTO INSERTIONS VALUES ({1}, {i});"; await dd1.ExecuteAsync(insertAValue); await dd2.OpenAsync(); insertAValue = $"INSERT INTO INSERTIONS VALUES ({2}, {i});"; await dd2.ExecuteAsync(insertAValue); await dd1.CloseAsync(); await dd2.CloseAsync(); } var expectedInsertions = 2 * reps; var insertions = await duckDBConnection.QuerySingleAsync <int>("SELECT COUNT(*) FROM INSERTIONS;"); insertions.Should().Be(expectedInsertions); }
public async Task MultiThreadedStress() { //with 1 task per file, should be good mix of reusing connections //and disposing of them const int fileCount = 20; const int taskCount = 20; const int insertionCount = 1000; const int totalInsertions = taskCount * insertionCount; var files = new DisposableFileList(fileCount, "db"); foreach (var f in files) { await using var duckDBConnection = new DuckDBConnection(f.ConnectionString); await duckDBConnection.OpenAsync(); var createTable = "CREATE TABLE INSERTIONS(TASK_ID INTEGER, INSERTION_INDEX INTEGER);"; await duckDBConnection.ExecuteAsync(createTable); } var insertionsWithRandomDelay = new Func <int, Task>(async ti => { var rnd = new Random(ti); for (int i = 0; i < insertionCount; i++) { //pick a random connection string for each test and jitter delays await Task.Delay(TimeSpan.FromMilliseconds(rnd.Next(0, 10))); var cs = files[rnd.Next(files.Count)].ConnectionString; await using var duckDBConnection = new DuckDBConnection(cs); await duckDBConnection.OpenAsync(); var insertAValue = $"INSERT INTO INSERTIONS VALUES ({ti}, {i});"; await duckDBConnection.ExecuteAsync(insertAValue); } }); var tasks = new Task[taskCount]; //it's hammer time baby! for (int i = 0; i < taskCount; i++) { var index = i; tasks[i] = Task.Run(async() => await insertionsWithRandomDelay(index)); } await Task.WhenAll(tasks); //sanity check of insertions int insertionCountPostRun = 0; foreach (var f in files) { var cs = f.ConnectionString; await using var duckDBConnection = new DuckDBConnection(cs); await duckDBConnection.OpenAsync(); var insertions = await duckDBConnection.QuerySingleAsync <int>("SELECT COUNT(*) FROM INSERTIONS;"); insertions.Should().BeGreaterThan(0); insertionCountPostRun += insertions; Console.WriteLine($"{insertions:0} Insertions for {cs}"); } insertionCountPostRun.Should().Be(totalInsertions, $"Insertions don't add up?"); //dispose here to make sure there isn't a connection still attached files.Dispose(); }