Skip to content

Commit 6b9e016

Browse files
committed
Better cleanup in tests, fix issues with orphaned tasks / disposal order
1 parent 3d562f3 commit 6b9e016

8 files changed

Lines changed: 236 additions & 149 deletions

File tree

PowerSync/PowerSync.Common/Client/PowerSyncDatabase.cs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -286,18 +286,22 @@ public async Task WaitForStatus(Func<SyncStatus, bool> predicate, CancellationTo
286286
}
287287

288288
var tcs = new TaskCompletionSource<bool>();
289-
var cts = new CancellationTokenSource();
289+
var cts = CancellationTokenSource.CreateLinkedTokenSource(masterCts.Token);
290290

291-
_ = Task.Run(() =>
291+
_ = Task.Run(async () =>
292292
{
293-
foreach (var update in Listen(cts.Token))
293+
try
294294
{
295-
if (update.StatusChanged != null && predicate(update.StatusChanged))
295+
await foreach (var update in ListenAsync(cts.Token))
296296
{
297-
cts.Cancel();
298-
tcs.TrySetResult(true);
297+
if (update.StatusChanged != null && predicate(update.StatusChanged))
298+
{
299+
cts.Cancel();
300+
tcs.TrySetResult(true);
301+
}
299302
}
300303
}
304+
catch (OperationCanceledException) { }
301305
});
302306

303307
cancellationToken?.Register(() =>

PowerSync/PowerSync.Common/MDSQLite/MDSQLiteAdapter.cs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ public class MDSQLiteAdapter : EventStream<DBAdapterEvent>, IDBAdapter
3131

3232
protected RequiredMDSQLiteOptions resolvedMDSQLiteOptions;
3333
private CancellationTokenSource? tablesUpdatedCts;
34+
private Task? tablesUpdatedTask;
3435

3536
private readonly AsyncLock writeMutex = new();
3637
private readonly AsyncLock readMutex = new();
@@ -86,11 +87,7 @@ private async Task Init()
8687

8788
foreach (var statement in writeConnectionStatements)
8889
{
89-
for (int tries = 0; tries < 30; tries++)
90-
{
91-
await writeConnection!.Execute(statement);
92-
tries = 30;
93-
}
90+
await writeConnection!.Execute(statement);
9491
}
9592

9693
foreach (var statement in readConnectionStatements)
@@ -99,9 +96,9 @@ private async Task Init()
9996
}
10097

10198
tablesUpdatedCts = new CancellationTokenSource();
102-
var _ = Task.Run(() =>
99+
tablesUpdatedTask = Task.Run(async () =>
103100
{
104-
foreach (var notification in writeConnection!.Listen(tablesUpdatedCts.Token))
101+
await foreach (var notification in writeConnection!.ListenAsync(tablesUpdatedCts.Token))
105102
{
106103
if (notification.TablesUpdated != null)
107104
{
@@ -139,6 +136,7 @@ protected virtual void LoadExtension(SqliteConnection db)
139136
public new void Close()
140137
{
141138
tablesUpdatedCts?.Cancel();
139+
try { tablesUpdatedTask?.Wait(TimeSpan.FromSeconds(2)); } catch { }
142140
base.Close();
143141
writeConnection?.Close();
144142
readConnection?.Close();

PowerSync/PowerSync.Common/MDSQLite/MDSQLiteConnection.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,6 @@ public async Task<NonQueryResult> Execute(string query, object?[]? parameters =
212212
DynamicParameters? dynamicParams = PrepareQuery(ref query, parameters);
213213
int rowsAffected = await Db.ExecuteAsync(query, dynamicParams, commandType: CommandType.Text);
214214

215-
FlushUpdates();
216215
return new NonQueryResult
217216
{
218217
InsertId = raw.sqlite3_last_insert_rowid(Db.Handle),

Tests/PowerSync/PowerSync.Common.Tests/Client/PowerSyncDatabaseTests.cs

Lines changed: 77 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ namespace PowerSync.Common.Tests.Client;
66

77
using PowerSync.Common.Client;
88
using PowerSync.Common.Tests.Models;
9+
using PowerSync.Common.Tests.Utils;
910

1011
/// <summary>
1112
/// dotnet test -v n --framework net8.0 --filter "PowerSyncDatabaseTests"
@@ -678,96 +679,114 @@ await db.Execute(
678679
public async Task WatchSchemaResetTest()
679680
{
680681
var dbId = Guid.NewGuid().ToString();
682+
var localDbName = $"powerSyncWatch_{dbId}.db";
681683
var db = new PowerSyncDatabase(new()
682684
{
683685
Database = new SQLOpenOptions
684686
{
685-
DbFilename = $"powerSyncWatch_{dbId}.db",
687+
DbFilename = localDbName,
686688
},
687689
Schema = TestSchema.MakeOptionalSyncSchema(false)
688690
});
689691

690-
using var sem = new SemaphoreSlim(0);
691-
long lastCount = 0;
692-
693-
const string QUERY = "SELECT COUNT(*) AS count FROM assets";
694-
var listener = db.Watch<CountResult>(QUERY, null, new() { Signal = testCts.Token });
695-
_ = Task.Run(async () =>
692+
try
696693
{
697-
await foreach (var result in listener)
694+
using var sem = new SemaphoreSlim(0);
695+
long lastCount = 0;
696+
697+
const string QUERY = "SELECT COUNT(*) AS count FROM assets";
698+
var listener = db.Watch<CountResult>(QUERY, null, new() { Signal = testCts.Token });
699+
_ = Task.Run(async () =>
698700
{
699-
if (result.Length > 0)
701+
await foreach (var result in listener)
700702
{
701-
lastCount = result[0].count;
703+
if (result.Length > 0)
704+
{
705+
lastCount = result[0].count;
706+
}
707+
sem.Release();
702708
}
703-
sem.Release();
704-
}
705-
});
709+
});
706710

707-
var resolved = await db.GetSourceTables(QUERY, null);
708-
Assert.Single(resolved);
709-
Assert.Contains("ps_data_local__local_assets", resolved);
711+
var resolved = await db.GetSourceTables(QUERY, null);
712+
Assert.Single(resolved);
713+
Assert.Contains("ps_data_local__local_assets", resolved);
710714

711-
for (int i = 0; i < 3; i++)
712-
{
713-
await db.Execute(
714-
"insert into assets(id, description, make) values (?, ?, ?)",
715-
[Guid.NewGuid().ToString(), "some desc", "some make"]
716-
);
717-
Assert.True(await sem.WaitAsync(100));
718-
Assert.Equal(i + 1, lastCount);
719-
}
720-
Assert.Equal(3, lastCount);
715+
for (int i = 0; i < 3; i++)
716+
{
717+
await db.Execute(
718+
"insert into assets(id, description, make) values (?, ?, ?)",
719+
[Guid.NewGuid().ToString(), "some desc", "some make"]
720+
);
721+
Assert.True(await sem.WaitAsync(100));
722+
Assert.Equal(i + 1, lastCount);
723+
}
724+
Assert.Equal(3, lastCount);
721725

722-
await db.UpdateSchema(TestSchema.MakeOptionalSyncSchema(true));
726+
await db.UpdateSchema(TestSchema.MakeOptionalSyncSchema(true));
723727

724-
resolved = await db.GetSourceTables(QUERY);
725-
Assert.Single(resolved);
726-
Assert.Contains("ps_data__assets", resolved);
728+
resolved = await db.GetSourceTables(QUERY);
729+
Assert.Single(resolved);
730+
Assert.Contains("ps_data__assets", resolved);
727731

728-
Assert.True(await sem.WaitAsync(100));
729-
Assert.Equal(0, lastCount);
732+
Assert.True(await sem.WaitAsync(100));
733+
Assert.Equal(0, lastCount);
730734

731-
await db.Execute("insert into assets select * from inactive_local_assets");
732-
Assert.True(await sem.WaitAsync(500));
733-
Assert.Equal(3, lastCount);
735+
await db.Execute("insert into assets select * from inactive_local_assets");
736+
Assert.True(await sem.WaitAsync(500));
737+
Assert.Equal(3, lastCount);
734738

735-
// Sanity check
736-
testCts.Cancel();
737-
await Task.Delay(100);
739+
// Sanity check
740+
testCts.Cancel();
741+
await Task.Delay(100);
738742

739-
await db.Execute("delete from assets");
740-
Assert.False(await sem.WaitAsync(100));
741-
Assert.Equal(3, lastCount);
743+
await db.Execute("delete from assets");
744+
Assert.False(await sem.WaitAsync(100));
745+
Assert.Equal(3, lastCount);
746+
}
747+
finally
748+
{
749+
await db.Close();
750+
DatabaseUtils.CleanDb(localDbName);
751+
}
742752
}
743753

744754
[Fact]
745755
public async Task Attributes_ColumnAliasing()
746756
{
757+
var localDbName = $"PowerSyncAttributesTest-{Guid.NewGuid():N}.db";
747758
var db = new PowerSyncDatabase(new PowerSyncDatabaseOptions
748759
{
749-
Database = new SQLOpenOptions { DbFilename = "PowerSyncAttributesTest.db" },
760+
Database = new SQLOpenOptions { DbFilename = localDbName },
750761
Schema = TestSchemaAttributes.AppSchema,
751762
});
752-
await db.DisconnectAndClear();
763+
try
764+
{
765+
await db.DisconnectAndClear();
753766

754-
var id = Guid.NewGuid().ToString();
755-
var description = "Test description";
756-
var completed = false;
757-
var createdAt = DateTimeOffset.Now;
767+
var id = Guid.NewGuid().ToString();
768+
var description = "Test description";
769+
var completed = false;
770+
var createdAt = DateTimeOffset.Now;
758771

759-
await db.Execute(
760-
"INSERT INTO todos(id, description, completed, created_at, list_id) VALUES(?, ?, ?, ?, uuid())",
761-
[id, description, completed, createdAt]
762-
);
772+
await db.Execute(
773+
"INSERT INTO todos(id, description, completed, created_at, list_id) VALUES(?, ?, ?, ?, uuid())",
774+
[id, description, completed, createdAt]
775+
);
763776

764-
var results = await db.GetAll<Todo>("SELECT * FROM todos");
765-
Assert.Single(results);
766-
var row = results.First();
767-
Assert.Equal(id, row.TodoId);
768-
Assert.Equal(description, row.Description);
769-
Assert.Equal(completed, row.Completed);
770-
Assert.Equal(createdAt, row.CreatedAt);
777+
var results = await db.GetAll<Todo>("SELECT * FROM todos");
778+
Assert.Single(results);
779+
var row = results.First();
780+
Assert.Equal(id, row.TodoId);
781+
Assert.Equal(description, row.Description);
782+
Assert.Equal(completed, row.Completed);
783+
Assert.Equal(createdAt, row.CreatedAt);
784+
}
785+
finally
786+
{
787+
await db.Close();
788+
DatabaseUtils.CleanDb(localDbName);
789+
}
771790
}
772791

773792
[Fact]

0 commit comments

Comments
 (0)