Skip to content

Commit 81f4541

Browse files
committed
DBC22-6518: segfault fix for event notifications
1 parent e11aeb2 commit 81f4541

1 file changed

Lines changed: 32 additions & 41 deletions

File tree

src/backend/apps/event/tasks.py

Lines changed: 32 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -435,10 +435,8 @@ def generate_district_settings_message(subscription, test_time=None):
435435

436436

437437
def queue_route_event_notifications(saved_route, updated_event_ids):
438-
# Apply a 150m buffer to the route geometry
439-
saved_route.route.transform(3857)
440-
buffered_route = saved_route.route.buffer(150)
441-
buffered_route.transform(4326)
438+
# Same 150m flattened-route buffer used when sending notifications
439+
buffered_route = merge_multilinestring(saved_route.route)
442440

443441
updated_interecting_events = Event.objects.filter(
444442
id__in=updated_event_ids,
@@ -484,55 +482,43 @@ def update_event_area_relations():
484482
event.area.set(intersecting_areas)
485483

486484

487-
def merge_multilinestring(multilinestring):
488-
# Flatten all coordinates from each LineString in the MultiLineString
485+
def flatten_route_linestring(multilinestring):
486+
"""Flatten a MultiLineString into a single LineString (SRID unchanged)."""
489487
coords = []
490488
for line in multilinestring:
491489
coords.extend(line.coords)
492-
ls = LineString(coords, srid=multilinestring.srid)
490+
return LineString(coords, srid=multilinestring.srid)
491+
492+
493+
def merge_multilinestring(multilinestring):
494+
"""Return a 150m buffer (SRID 4326) around the flattened route."""
495+
ls = flatten_route_linestring(multilinestring)
496+
if ls.empty:
497+
return ls
493498

494-
# Apply a 150m buffer to the route geometry
495499
ls.transform(3857)
496500
buffered_route = ls.buffer(150)
497501
buffered_route.transform(4326)
498502

499503
return buffered_route
500504

501505

502-
def get_event_reference_point(event_location, route):
503-
# If event_location is a Point, return as is
504-
if event_location.geom_type == 'Point':
505-
return event_location
506-
507-
# If event_location is a LineString, get intersection with route
508-
elif event_location.geom_type == 'LineString':
509-
intersection = event_location.intersection(route)
510-
# If intersection is a Point, return it
511-
if intersection.geom_type == 'Point':
512-
return intersection
513-
514-
# If intersection is a MultiPoint or LineString, return centroid or first point
515-
elif intersection.geom_type in ['MultiPoint', 'LineString']:
516-
return intersection.centroid
517-
518-
# Fallback: return centroid
519-
return event_location.centroid
520-
521-
522506
def get_ordered_events(events, route):
523-
events = list(events)
524-
event_distances = []
525-
for event in events:
526-
# Get reference point from buffered route
527-
ref_point = get_event_reference_point(event.location, merge_multilinestring(route))
528-
distance = route.project(ref_point)
529-
event_distances.append((distance, event))
507+
"""Sort events by distance along the route (point location, else centroid)."""
508+
route_ls = flatten_route_linestring(route)
509+
if route_ls.empty:
510+
return list(events)
530511

531-
# Sort events by distance along the route
532-
event_distances.sort(key=lambda x: x[0])
533-
ordered_events = [e for _, e in event_distances]
512+
def distance_along_route(event):
513+
loc = event.location
514+
if loc.empty:
515+
return float('inf')
516+
point = loc if loc.geom_type == 'Point' else loc.centroid
517+
if point.empty:
518+
return float('inf')
519+
return route_ls.project(point)
534520

535-
return ordered_events
521+
return sorted(events, key=distance_along_route)
536522

537523

538524
def send_queued_notifications():
@@ -548,7 +534,12 @@ def send_queued_notifications():
548534
queued_notification_ids += queued_notifications.values_list('id', flat=True)
549535

550536
queued_event_ids = queued_notifications.values_list('event_id', flat=True)
551-
events = active_events.filter(id__in=queued_event_ids) # filter out inactive events
537+
buffered_route = merge_multilinestring(saved_route.route)
538+
# Active + still near the route (drops stale queue rows / geometry drift)
539+
events = active_events.filter(
540+
id__in=queued_event_ids,
541+
location__intersects=buffered_route,
542+
)
552543
ordered_events = get_ordered_events(events, saved_route.route)
553544

554545
if not ordered_events:
@@ -578,7 +569,7 @@ def send_queued_notifications():
578569
# image attachments
579570
attach_default_email_images(msg)
580571

581-
file_names = get_unique_image_type_files_names(events)
572+
file_names = get_unique_image_type_files_names(ordered_events)
582573
for fn in file_names:
583574
attach_image_to_email(msg, fn.split('.')[0], fn) # use file name (without extension) as cid
584575

0 commit comments

Comments
 (0)