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.
 
 
 
 
 

75 lines
2.4 KiB

"""
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!"