- """
-
- Populate api_check.n_pings and api_ping.n fields.
-
- - api_ping.n stores ping's serial number, counted separately for
- each check. For example, if a particular check has received 100 pings,
- its first ping will have a n=1, and the 100th ping will have a n=100.
-
- - api_check.n_pings stores the last serial number assigned to a ping.
- It also is the total number of pings the check has ever received.
-
- This command works by "replaying" stored pings in their primary
- key order, and counting up their serial numbers. At the very end,
- api_check.n_pings fields are updated as well.
-
- Depending on the size of api_ping table, this command can potentially
- take a long time to complete.
-
- Note on ping pruning: when the prunepings command is run, some of the
- pings with the lowest serial numbers get removed. This doesn't affect
- the "n" field for remaining pings, or the "n_pings" value of checks.
- The serial numbers keep going up.
-
- """
-
- import gc
- from collections import Counter
-
- from django.core.management.base import BaseCommand
- from django.db import connection, transaction
- from hc.api.models import Check, Ping
-
-
- class Command(BaseCommand):
- help = 'Fill check.n_pings field and ping.n field'
-
- def handle(self, *args, **options):
- connection.use_debug_cursor = False
- chunksize = 2000
-
- # Reset all n_pings fields to zero
- Check.objects.update(n_pings=0)
-
- counts = Counter()
-
- pk = 0
- last_pk = Ping.objects.order_by('-pk')[0].pk
- queryset = Ping.objects.order_by('pk')
-
- while pk < last_pk:
- transaction.set_autocommit(False)
- while pk < last_pk:
- for ping in queryset.filter(pk__gt=pk)[:chunksize]:
- pk = ping.pk
- counts[ping.owner_id] += 1
-
- ping.n = counts[ping.owner_id]
- ping.save(update_fields=("n", ))
-
- gc.collect()
- progress = 100 * pk / last_pk
- self.stdout.write(
- "Processed ping id %d (%.2f%%)" % (pk, progress))
-
- transaction.commit()
-
- transaction.set_autocommit(True)
- # last_pk might have increased because of influx of new pings:
- last_pk = Ping.objects.order_by('-pk')[0].pk
-
- self.stdout.write("Updating check.n_pings")
- for check_id, n_pings in counts.items():
- Check.objects.filter(pk=check_id).update(n_pings=n_pings)
-
- return "Done!"
|