Skip to content
This repository was archived by the owner on May 12, 2026. It is now read-only.

Commit 72bfdb6

Browse files
Debounce RunPushGeoJsonAsync to reduce GeoJSON rebuilds on main thread
1 parent 410365d commit 72bfdb6

2 files changed

Lines changed: 21 additions & 5 deletions

File tree

Alidade/Handlers/EditBuffer/GeoJsonPushRequested.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@ public class GeoJsonPushRequested(EditBufferService editBuffer)
88
/// Raised when the edit buffer changes and the full GeoJSON map sources need rebuilding.
99
/// </summary>
1010
/// <param name="State">The current edit buffer state to push.</param>
11-
public record Notification(EditBufferState State) : NotificationBase;
11+
/// <param name="Sequence">Monotonically increasing counter used to discard superseded pushes.</param>
12+
public record Notification(EditBufferState State, int Sequence) : NotificationBase;
1213

1314
/// <inheritdoc />
1415
public async Task Handle(Notification notification, CancellationToken cancellationToken)
1516
{
16-
await editBuffer.RunPushGeoJsonAsync(notification.State);
17+
await editBuffer.RunPushGeoJsonNotificationAsync(notification.State, notification.Sequence);
1718
}
1819
}

Alidade/Services/EditBufferService.cs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ public class EditBufferService : IDisposable
3333
private CancellationTokenSource? _saveCts;
3434
private bool _hadDirtyState;
3535

36+
// GeoJSON push debouncing
37+
private int _geoJsonPushSeq;
38+
3639
// Selection push debouncing and delta tracking
3740
private int _selectionPushSeq;
3841
private ImmutableHashSet<OsmElementRef> _lastPushedSelected = [];
@@ -81,7 +84,7 @@ public EditBufferService(
8184

8285
private void OnEditBufferChanged(object? sender, EventArgs e)
8386
{
84-
_ = _mediator.Publish(new GeoJsonPushRequested.Notification(_editState.State));
87+
_ = _mediator.Publish(new GeoJsonPushRequested.Notification(_editState.State, ++_geoJsonPushSeq));
8588
_selectedNeedsRepush = true;
8689
RequestSelectionPush();
8790
_validation?.ScheduleValidation(_editState.State);
@@ -127,8 +130,20 @@ private void RequestSelectionPush()
127130
_ = _mediator.Publish(new SelectionPushRequested.Notification(seq));
128131
}
129132

133+
internal async Task RunPushGeoJsonNotificationAsync(EditBufferState state, int seq)
134+
{
135+
await Task.Yield();
136+
if (_geoJsonPushSeq != seq)
137+
{
138+
return;
139+
}
140+
141+
await RunPushGeoJsonAsync(state);
142+
}
143+
130144
internal async Task RunSelectionPushAsync(int seq)
131145
{
146+
await Task.Yield();
132147
if (_selectionPushSeq != seq)
133148
{
134149
return;
@@ -306,7 +321,7 @@ internal async Task RunPushGeoJsonAsync(EditBufferState state)
306321
await SetSourceAsync("osm-ways", ways);
307322
}
308323

309-
private async Task PushSelectionAsync(Models.Selection.SelectionState sel, EditBufferState buf, bool includeSelected)
324+
private async Task PushSelectionAsync(SelectionState sel, EditBufferState buf, bool includeSelected)
310325
{
311326
IReadOnlyDictionary<long, OsmNode> liveNodes = buf.Nodes
312327
.Where(kv => buf.EditStates.GetValueOrDefault(kv.Value.Ref) != EditState.Deleted)
@@ -395,7 +410,7 @@ private async Task PushSelectionAsync(Models.Selection.SelectionState sel, EditB
395410
await SetSourceAsync("osm-hover", hoverFeatures);
396411
}
397412

398-
private async Task SetSourceAsync(string sourceId, IReadOnlyList<NetTopologySuite.Features.IFeature> features)
413+
private async Task SetSourceAsync(string sourceId, IReadOnlyList<IFeature> features)
399414
{
400415
if (features.Count == 0)
401416
{

0 commit comments

Comments
 (0)