Commit resync writes in one transaction
Each insert, delete and rescore update was its own commit to disk, so a resync of about a thousand QSOs froze the window thread. LogStore has a new Batch() scope that commits its writes together. ContestSession uses it in AddRangeFromNetwork, ClearFromNetwork and Rescore. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -128,9 +128,12 @@ public sealed class ContestSession
|
|||||||
&& q.TimestampUtc >= fromUtc
|
&& q.TimestampUtc >= fromUtc
|
||||||
&& q.TimestampUtc < fromUtc + length)
|
&& q.TimestampUtc < fromUtc + length)
|
||||||
.ToList();
|
.ToList();
|
||||||
foreach (Qso qso in gone)
|
using (store.Batch())
|
||||||
{
|
{
|
||||||
store.Delete(qso.Id);
|
foreach (Qso qso in gone)
|
||||||
|
{
|
||||||
|
store.Delete(qso.Id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (gone.Count > 0)
|
if (gone.Count > 0)
|
||||||
{
|
{
|
||||||
@@ -152,10 +155,13 @@ public sealed class ContestSession
|
|||||||
{
|
{
|
||||||
Log.Rescore();
|
Log.Rescore();
|
||||||
int written = 0;
|
int written = 0;
|
||||||
foreach (Qso qso in Log.Qsos.Where(q => q.TimestampUtc >= fromUtc))
|
using (store.Batch())
|
||||||
{
|
{
|
||||||
store.Update(qso);
|
foreach (Qso qso in Log.Qsos.Where(q => q.TimestampUtc >= fromUtc))
|
||||||
written++;
|
{
|
||||||
|
store.Update(qso);
|
||||||
|
written++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Changed?.Invoke(this, EventArgs.Empty);
|
Changed?.Invoke(this, EventArgs.Empty);
|
||||||
return written;
|
return written;
|
||||||
@@ -216,11 +222,14 @@ public sealed class ContestSession
|
|||||||
{
|
{
|
||||||
HashSet<string> held = [.. Log.Qsos.Select(q => q.Id)];
|
HashSet<string> held = [.. Log.Qsos.Select(q => q.Id)];
|
||||||
List<Qso> stored = [];
|
List<Qso> stored = [];
|
||||||
foreach (Qso qso in arriving)
|
using (store.Batch())
|
||||||
{
|
{
|
||||||
if (held.Add(qso.Id))
|
foreach (Qso qso in arriving)
|
||||||
{
|
{
|
||||||
stored.Add(store.Add(FromNetwork(qso)));
|
if (held.Add(qso.Id))
|
||||||
|
{
|
||||||
|
stored.Add(store.Add(FromNetwork(qso)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (stored.Count == 0)
|
if (stored.Count == 0)
|
||||||
|
|||||||
@@ -28,4 +28,9 @@ public interface LogStore : IDisposable
|
|||||||
void Update(Qso qso);
|
void Update(Qso qso);
|
||||||
|
|
||||||
void Delete(string id);
|
void Delete(string id);
|
||||||
|
|
||||||
|
/// Writes made until the returned scope is disposed are committed
|
||||||
|
/// together. A write on its own is a commit to disk, which makes a burst
|
||||||
|
/// of a thousand contacts take seconds.
|
||||||
|
IDisposable Batch();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -188,6 +188,18 @@ public sealed class SqliteLogStore : LogStore
|
|||||||
|
|
||||||
public void Dispose() => connection.Dispose();
|
public void Dispose() => connection.Dispose();
|
||||||
|
|
||||||
|
public IDisposable Batch() => new CommitOnDispose(connection.BeginTransaction());
|
||||||
|
|
||||||
|
/// Disposing a `SqliteTransaction` rolls it back, so this commits first.
|
||||||
|
private sealed class CommitOnDispose(SqliteTransaction transaction) : IDisposable
|
||||||
|
{
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
transaction.Commit();
|
||||||
|
transaction.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void Insert(Qso qso)
|
private void Insert(Qso qso)
|
||||||
{
|
{
|
||||||
using SqliteCommand command = connection.CreateCommand();
|
using SqliteCommand command = connection.CreateCommand();
|
||||||
|
|||||||
@@ -57,7 +57,16 @@ public sealed class FakeLogStore : LogStore
|
|||||||
|
|
||||||
public void Delete(string id) => qsos.RemoveAll(q => q.Id == id);
|
public void Delete(string id) => qsos.RemoveAll(q => q.Id == id);
|
||||||
|
|
||||||
|
public IDisposable Batch() => new NoBatch();
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private sealed class NoBatch : IDisposable
|
||||||
|
{
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user