Factor the models to prepare for new ones related to the radio version
Other notable improvements:
- Define the default values to be able to use the built-in convenience method
`get_or_create`;
- Use the F helper to *atomically* increment the counters; the current method
could run into race conditions and miss increments.
The models remain functionally the same - also, their title is left unchanged to
not break compatibility and avoid a migration.
Change-Id: Iad86302d869705867efadf8cfd2e661dac1ff4f9
diff --git a/crashreport_stats/models.py b/crashreport_stats/models.py
index 04f38ab..7c2a83f 100644
--- a/crashreport_stats/models.py
+++ b/crashreport_stats/models.py
@@ -1,76 +1,74 @@
from django.db import models
from crashreports.models import *
+from django.db.models import F
from django.db.models.signals import post_save
from django.dispatch import receiver
import datetime
-def getVersion(build_fingerprint):
- v= None
- try:
- v = Version.objects.get(build_fingerprint=build_fingerprint)
- except Version.DoesNotExist:
- v =Version(build_fingerprint=build_fingerprint,
- first_seen_on=datetime.date.today(),
- released_on=datetime.date.today(),
- heartbeats=0, prob_crashes=0, smpl=0, other=0)
- v.save()
- return v
-
-def getVersionDaily(version,day):
- try:
- v = VersionDaily.objects.get(version=version, date=day)
- except VersionDaily.DoesNotExist:
- v =VersionDaily(version=version, date=day,
- heartbeats=0, prob_crashes=0, smpl=0, other=0)
- return v
-
@receiver(post_save, sender=Crashreport)
def on_crashreport_create(sender, **kwargs):
crashreport = kwargs.get('instance')
- v= getVersion(crashreport.build_fingerprint)
- vd = getVersionDaily(v, crashreport.date.date())
+ v, _ = Version.objects.get_or_create(build_fingerprint=crashreport.build_fingerprint)
+ vd, _ = VersionDaily.objects.get_or_create(version=v, date=crashreport.date)
+ stats = [v, vd]
+
if crashreport.boot_reason == "RTC alarm":
- v.smpl = v.smpl + 1
- vd.smpl = vd.smpl + 1
+ for element in stats:
+ element.smpl = F('smpl') + 1
elif crashreport.boot_reason in ["UNKNOWN", "keyboard power on"]:
- v.prob_crashes = v.prob_crashes + 1
- vd.prob_crashes = vd.prob_crashes + 1
+ for element in stats:
+ element.prob_crashes = F('prob_crashes') + 1
else:
- v.other = v.other + 1
- vd.other = vd.other + 1
- v.save()
- vd.save()
+ for element in stats:
+ element.other = F('other') + 1
+
+ for element in stats:
+ element.save()
+
@receiver(post_save, sender=HeartBeat)
def on_heartbeat_create(sender, **kwargs):
hb = kwargs.get('instance')
- v = getVersion(hb.build_fingerprint)
- vd = getVersionDaily(v, hb.date)
- v.heartbeats = v.heartbeats + 1
- vd.heartbeats = vd.heartbeats + 1
- v.save()
- vd.save()
+
+ v, _ = Version.objects.get_or_create(build_fingerprint=hb.build_fingerprint)
+ vd, _ = VersionDaily.objects.get_or_create(version=v, date=hb.date)
+
+ for element in [v, vd]:
+ element.heartbeats = F('heartbeats') + 1
+ element.save()
-class Version(models.Model):
- build_fingerprint = models.CharField(max_length=200, unique=True)
+class _VersionStats(models.Model):
is_official_release = models.BooleanField(default=False)
- is_beta_release = models.BooleanField(default=False)
- first_seen_on = models.DateField()
- released_on = models.DateField()
- heartbeats = models.IntegerField()
- prob_crashes = models.IntegerField()
- smpl = models.IntegerField()
- other = models.IntegerField()
+ is_beta_release = models.BooleanField(default=False)
+ first_seen_on = models.DateField(auto_now_add=True)
+ released_on = models.DateField(auto_now_add=True)
+ heartbeats = models.IntegerField(default=0)
+ prob_crashes = models.IntegerField(default=0)
+ smpl = models.IntegerField(default=0)
+ other = models.IntegerField(default=0)
+
+ class Meta:
+ abstract = True
+
+class _DailyVersionStats(models.Model):
+ date = models.DateField(auto_now_add=True)
+ heartbeats = models.IntegerField(default=0)
+ prob_crashes = models.IntegerField(default=0)
+ smpl = models.IntegerField(default=0)
+ other = models.IntegerField(default=0)
+
+ class Meta:
+ abstract = True
+
+
+class Version(_VersionStats):
+ build_fingerprint = models.CharField(max_length=200, unique=True)
+
def __str__(self):
return self.build_fingerprint
-
-
-class VersionDaily(models.Model):
- version = models.ForeignKey(Version, db_index=True, related_name='daily_stats', on_delete=models.CASCADE)
- date = models.DateField()
- heartbeats = models.IntegerField()
- prob_crashes = models.IntegerField()
- smpl = models.IntegerField()
- other = models.IntegerField()
+
+class VersionDaily(_DailyVersionStats):
+ version = models.ForeignKey(Version, db_index=True, related_name='daily_stats',
+ on_delete=models.CASCADE)