1
0
Fork 0

Improve performance when update LatestTleSet entries

Signed-off-by: Alfredos-Panagiotis Damkalis <fredy@fredy.gr>
spacecruft
Alfredos-Panagiotis Damkalis 2020-09-26 22:55:03 +03:00
parent 5406261482
commit ed0a22503d
3 changed files with 85 additions and 41 deletions

View File

@ -254,16 +254,16 @@ class TleAdmin(admin.ModelAdmin):
def save_model(self, request, obj, form, change):
super().save_model(request, obj, form, change)
update_latest_tle_sets(satellites=[obj.satellite.pk])
update_latest_tle_sets(satellite_ids=[obj.satellite.pk])
def delete_model(self, request, obj):
super().delete_model(request, obj)
update_latest_tle_sets(satellites=[obj.satellite.pk])
update_latest_tle_sets(satellite_ids=[obj.satellite.pk])
def delete_queryset(self, request, queryset):
satellites = [tle.satellite.pk for tle in queryset]
super().delete_queryset(request, queryset)
update_latest_tle_sets(satellites=satellites)
update_latest_tle_sets(satellite_ids=satellites)
@admin.register(LatestTleSet)

View File

@ -15,9 +15,9 @@ LOGGER = logging.getLogger('db')
def _remove_latest_tle_set(sender, instance, **kwargs): # pylint: disable=W0613
"""Updates if needed LatestTle entries"""
if instance.status in ['re-entered', 'future']:
remove_latest_tle_set(instance.pk)
remove_latest_tle_set(satellite_id=instance.pk)
else:
update_latest_tle_sets([instance.pk])
update_latest_tle_sets(satellite_ids=[instance.pk])
def _gen_observer(sender, instance, created, **kwargs): # pylint: disable=W0613

View File

@ -21,49 +21,93 @@ from db.base.models import DemodData, LatestTleSet, Mode, Satellite, Tle, \
LOGGER = logging.getLogger('db')
def remove_latest_tle_set(satellite_pk):
"""Remove LatestTleSet for specific Satellite"""
LatestTleSet.objects.filter(satellite__pk=satellite_pk).delete()
def remove_latest_tle_set(satellite_id):
"""Remove LatestTleSet entry for specific Satellite"""
LatestTleSet.objects.filter(satellite__pk=satellite_id).delete()
def update_latest_tle_sets(satellites=None):
"""Update LatestTleSet for specific or all Satellites"""
if not satellites:
def update_latest_tle_sets(satellite_ids=None):
"""Update LatestTleSet entries for all or specific Satellites"""
# Select satellite models
if satellite_ids:
satellites = Satellite.objects.filter(pk__in=satellite_ids)
else:
satellites = Satellite.objects.exclude(status__in=['re-entered', 'future'])
sub_subquery = Tle.objects.filter(satellite__pk__in=satellites).exclude(
tle_source__in=settings.TLE_SOURCES_IGNORE_FROM_LATEST
).filter(
satellite=OuterRef('satellite'), tle_source=OuterRef('tle_source')
).order_by('-updated')
subquery = Tle.objects.filter(pk=Subquery(sub_subquery.values('pk')[:1])
).filter(satellite=OuterRef('satellite')
).annotate(epoch=Max(Substr('tle1', 19, 14))
).order_by('-epoch')
tle_sets = Tle.objects.filter(pk=Subquery(subquery.values('pk')[:1]))
# Create dictionary with Satellite ids as keys and Tle ids as values
latest_triplets = LatestTleSet.objects.filter(
satellite__in=satellites
).values_list('satellite', 'latest', 'latest_distributable')
latest_dictionary = {
latest_triplet[0]: (latest_triplet[1], latest_triplet[2])
for latest_triplet in latest_triplets
}
sub_subquery = Tle.objects.filter(satellite__pk__in=satellites).exclude(
tle_source__in=settings.TLE_SOURCES_IGNORE_FROM_LATEST
).filter(tle_source__in=settings.TLE_SOURCES_REDISTRIBUTABLE).filter(
satellite=OuterRef('satellite'), tle_source=OuterRef('tle_source')
).order_by('-updated')
subquery = Tle.objects.filter(pk=Subquery(sub_subquery.values('pk')[:1])
).filter(satellite=OuterRef('satellite')
).annotate(epoch=Max(Substr('tle1', 19, 14))
).order_by('-epoch')
distributable_tle_sets = Tle.objects.filter(pk=Subquery(subquery.values('pk')[:1]))
# For each satellite update LatestTleSet
for satellite in satellites:
for tle_set in tle_sets:
latest_tle_set, _ = LatestTleSet.objects.get_or_create(satellite=tle_set.satellite)
latest_tle_set.latest = tle_set
latest_tle_set.save(update_fields=['latest'])
for distributable_tle_set in distributable_tle_sets:
latest_tle_set, _ = LatestTleSet.objects.get_or_create(
satellite=distributable_tle_set.satellite
)
latest_tle_set.latest_distributable = distributable_tle_set
latest_tle_set.save(update_fields=['latest_distributable'])
# Keep the Tle ids of the LatestTleSet to check Tle entries inserted after them
# If there isn't one (new satellite or remove Tle entry) then check all of them
tle_id, tle_id_dist = (0, 0)
if satellite.id in latest_dictionary:
tle_ids = latest_dictionary[satellite.id]
tle_id = tle_ids[0] if tle_ids[0] else 0
tle_id_dist = tle_ids[1] if tle_ids[1] else 0
# Query for the latest Tle set for this satellite
sub_subquery = Tle.objects.filter(
pk__gte=tle_id, satellite=satellite
).exclude(tle_source__in=settings.TLE_SOURCES_IGNORE_FROM_LATEST).filter(
satellite=OuterRef('satellite'), tle_source=OuterRef('tle_source')
).order_by('-updated')
subquery = Tle.objects.filter(
pk__gte=tle_id, satellite=satellite
).exclude(tle_source__in=settings.TLE_SOURCES_IGNORE_FROM_LATEST
).filter(pk=Subquery(sub_subquery.values('pk')[:1])
).filter(satellite=OuterRef('satellite')
).annotate(epoch=Max(Substr('tle1', 19, 14))
).order_by('-epoch')
new_latest = Tle.objects.filter(
pk__gte=tle_id, satellite=satellite
).exclude(tle_source__in=settings.TLE_SOURCES_IGNORE_FROM_LATEST
).filter(pk=Subquery(subquery.values('pk')[:1]))
# Query for the latest Tle set that is distributable for this satellite
sub_subquery = Tle.objects.filter(
pk__gte=tle_id_dist,
satellite=satellite,
tle_source__in=settings.TLE_SOURCES_REDISTRIBUTABLE
).exclude(tle_source__in=settings.TLE_SOURCES_IGNORE_FROM_LATEST).filter(
satellite=OuterRef('satellite'), tle_source=OuterRef('tle_source')
).order_by('-updated')
subquery = Tle.objects.filter(
pk__gte=tle_id_dist,
satellite=satellite,
tle_source__in=settings.TLE_SOURCES_REDISTRIBUTABLE
).exclude(tle_source__in=settings.TLE_SOURCES_IGNORE_FROM_LATEST
).filter(pk=Subquery(sub_subquery.values('pk')[:1])
).filter(satellite=OuterRef('satellite')
).annotate(epoch=Max(Substr('tle1', 19, 14))
).order_by('-epoch')
new_latest_dist = Tle.objects.filter(
pk__gte=tle_id_dist,
satellite=satellite,
tle_source__in=settings.TLE_SOURCES_REDISTRIBUTABLE
).exclude(tle_source__in=settings.TLE_SOURCES_IGNORE_FROM_LATEST
).filter(pk=Subquery(subquery.values('pk')[:1]))
# Add the latest Tle set if there is a LatestTleSet entry, if not create one
if new_latest:
LatestTleSet.objects.update_or_create(
satellite=satellite, defaults={'latest': new_latest[0]}
)
# Add the latest distributable Tle set if there is a LatestTleSet entry, if not create one
if new_latest_dist:
LatestTleSet.objects.update_or_create(
satellite=satellite, defaults={'latest_distributable': new_latest_dist[0]}
)
# Remove any LatestTleSet that hasn't any Tle entry (satellite without Tle entries)
LatestTleSet.objects.filter(latest__isnull=True, latest_distributable__isnull=True).delete()