You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

70 lines
2.2 KiB

  1. """
  2. Populate api_check.n_pings and api_ping.n fields.
  3. - api_ping.n stores ping's serial number, counted separately for
  4. each check. For example, if a particular check has received 100 pings,
  5. its first ping will have a n=1, and the 100th ping will have a n=100.
  6. - api_check.n_pings stores the last serial number assigned to a ping.
  7. It also is the total number of pings the check has ever received.
  8. This command works by "replaying" stored pings in their primary
  9. key order, and counting up their serial numbers. At the very end,
  10. api_check.n_pings fields are updated as well.
  11. Depending on the size of api_ping table, this command can potentially
  12. take a long time to complete.
  13. Note on ping pruning: when the prunepings command is run, some of the
  14. pings with the lowest serial numbers get removed. This doesn't affect
  15. the "n" field for remaining pings, or the "n_pings" value of checks.
  16. The serial numbers keep going up.
  17. """
  18. import gc
  19. from collections import Counter
  20. from django.core.management.base import BaseCommand
  21. from django.db import connection, transaction
  22. from hc.api.models import Check, Ping
  23. class Command(BaseCommand):
  24. help = 'Fill check.n_pings field and ping.n field'
  25. def handle(self, *args, **options):
  26. connection.use_debug_cursor = False
  27. chunksize = 2000
  28. # Reset all n_pings fields to zero
  29. Check.objects.update(n_pings=0)
  30. counts = Counter()
  31. pk = 0
  32. last_pk = Ping.objects.order_by('-pk')[0].pk
  33. queryset = Ping.objects.order_by('pk')
  34. transaction.set_autocommit(False)
  35. while pk < last_pk:
  36. for ping in queryset.filter(pk__gt=pk)[:chunksize]:
  37. pk = ping.pk
  38. counts[ping.owner_id] += 1
  39. ping.n = counts[ping.owner_id]
  40. ping.save(update_fields=("n", ))
  41. gc.collect()
  42. progress = 100 * pk / last_pk
  43. self.stdout.write("Processed ping id %d (%.2f%%)" % (pk, progress))
  44. transaction.commit()
  45. transaction.set_autocommit(True)
  46. self.stdout.write("Updating check.n_pings")
  47. for check_id, n_pings in counts.items():
  48. Check.objects.filter(pk=check_id).update(n_pings=n_pings)
  49. return "Done!"