Skip to content

Commit eb80d6f

Browse files
committed
Fixes #1246 and #1756 - Removed Hall of Fame task
1 parent cef300d commit eb80d6f

File tree

15 files changed

+365
-415
lines changed

15 files changed

+365
-415
lines changed
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
# Partly generated by Django 4.2.20 on 2025-05-25 15:24 together with manual RunSQL
2+
3+
from django.db import migrations, models
4+
from django.db.models import Case, F, Q, Value, When
5+
from django.db.models.functions import Greatest
6+
from django.db.models.lookups import GreaterThan
7+
import django.db.models.deletion
8+
import pgtrigger.compiler
9+
import pgtrigger.migrations
10+
11+
12+
class Migration(migrations.Migration):
13+
dependencies = [
14+
("checks", "0018_domaintesttls_caa_records"),
15+
]
16+
17+
operations = [
18+
# Note db_index is False on the ForeignKey to prevent extra indices that are not needed
19+
# AutoField has to be primary key in Django, to solve this manually alter SQL this field
20+
# see https://github.com/django/django/blob/787f3130f751283140fe2be8188eb5299552232d/django/db/models/fields/__init__.py#L2801
21+
migrations.CreateModel(
22+
name="Fame",
23+
fields=[
24+
("id", models.IntegerField(serialize=False, verbose_name="ID")),
25+
("domain", models.CharField(max_length=255, primary_key=True, serialize=False)),
26+
(
27+
"site_report",
28+
models.ForeignKey(
29+
db_index=False,
30+
null=True,
31+
on_delete=django.db.models.deletion.CASCADE,
32+
to="checks.domaintestreport",
33+
),
34+
),
35+
("site_report_timestamp", models.DateTimeField(null=True)),
36+
(
37+
"mail_report",
38+
models.ForeignKey(
39+
db_index=False,
40+
null=True,
41+
on_delete=django.db.models.deletion.CASCADE,
42+
to="checks.mailtestreport",
43+
),
44+
),
45+
("mail_report_timestamp", models.DateTimeField(null=True)),
46+
],
47+
),
48+
migrations.AddIndex(
49+
model_name="fame",
50+
index=models.Index(
51+
condition=models.Q(site_report_id__isnull=False),
52+
fields=["-site_report_timestamp", "domain", "site_report_id"],
53+
name="checks_fame_sites_idx",
54+
),
55+
),
56+
migrations.AddIndex(
57+
model_name="fame",
58+
index=models.Index(
59+
condition=models.Q(mail_report_id__isnull=False),
60+
fields=["-mail_report_timestamp", "domain", "mail_report_id"],
61+
name="checks_fame_mail_idx",
62+
),
63+
),
64+
migrations.AddIndex(
65+
model_name="fame",
66+
index=models.Index(
67+
models.OrderBy(
68+
Greatest("site_report_timestamp", "mail_report_timestamp"),
69+
descending=True,
70+
),
71+
"domain",
72+
Case(
73+
models.When(
74+
GreaterThan(F("site_report_timestamp"), F("mail_report_timestamp")),
75+
then=Value("s"),
76+
),
77+
default=Value("m"),
78+
output_field=models.CharField(max_length=1),
79+
),
80+
Case(
81+
When(
82+
GreaterThan(F("site_report_timestamp"), F("mail_report_timestamp")),
83+
then="site_report_id",
84+
),
85+
default="mail_report_id",
86+
),
87+
condition=Q(site_report_id__isnull=False) & Q(mail_report_id__isnull=False),
88+
name="checks_fame_champions_idx",
89+
),
90+
),
91+
pgtrigger.migrations.AddTrigger(
92+
model_name="domaintestreport",
93+
trigger=pgtrigger.compiler.Trigger(
94+
name="update_fame_on_site_report",
95+
sql=pgtrigger.compiler.UpsertTriggerSql(
96+
func="""
97+
IF NEW.score IS NULL THEN
98+
-- DO NOTHING
99+
ELSIF NEW.score = 100 THEN
100+
INSERT INTO checks_fame (domain, site_report_id, site_report_timestamp, mail_report_id, mail_report_timestamp)
101+
VALUES (NEW.domain, NEW.id, NEW.timestamp, NULL, NULL)
102+
ON CONFLICT (domain)
103+
DO UPDATE SET site_report_id = NEW.id, site_report_timestamp = NEW.timestamp;
104+
ELSE
105+
MERGE INTO ONLY checks_fame c1
106+
USING checks_fame c2 ON c1.domain = c2.domain AND c1.domain = NEW.domain
107+
WHEN NOT MATCHED THEN
108+
DO NOTHING
109+
WHEN MATCHED AND c1.mail_report_id IS NOT NULL THEN
110+
UPDATE SET site_report_id = NULL, site_report_timestamp = NULL
111+
WHEN MATCHED AND c1.mail_report_id IS NULL THEN
112+
DELETE;
113+
END IF;
114+
RETURN NEW;
115+
""",
116+
hash="b4f792b06123914de71b57669c202a19b04e9e9c",
117+
operation='INSERT OR UPDATE OF "score"',
118+
pgid="pgtrigger_update_fame_on_site_report_e4fdc",
119+
table="checks_domaintestreport",
120+
when="AFTER",
121+
),
122+
),
123+
),
124+
pgtrigger.migrations.AddTrigger(
125+
model_name="mailtestreport",
126+
trigger=pgtrigger.compiler.Trigger(
127+
name="update_fame_on_mail_report",
128+
sql=pgtrigger.compiler.UpsertTriggerSql(
129+
func="""
130+
IF NEW.score IS NULL THEN
131+
-- DO NOTHING
132+
ELSIF NEW.score = 100 THEN
133+
INSERT INTO checks_fame (domain, site_report_id, site_report_timestamp, mail_report_id, mail_report_timestamp)
134+
VALUES (NEW.domain, NULL, NULL, NEW.id, NEW.timestamp)
135+
ON CONFLICT (domain)
136+
DO UPDATE SET mail_report_id = NEW.id, mail_report_timestamp = NEW.timestamp;
137+
ELSE
138+
MERGE INTO ONLY checks_fame c1
139+
USING checks_fame c2 ON c1.domain = c2.domain AND c1.domain = NEW.domain
140+
WHEN NOT MATCHED THEN
141+
DO NOTHING
142+
WHEN MATCHED AND c1.site_report_id IS NOT NULL THEN
143+
UPDATE SET mail_report_id = NULL, mail_report_timestamp = NULL
144+
WHEN MATCHED AND c1.site_report_id IS NULL THEN
145+
DELETE;
146+
END IF;
147+
RETURN NEW;
148+
""",
149+
hash="707aefc7a83dd041dd815511f1d1cf7e8f84f944",
150+
operation='INSERT OR UPDATE OF "score"',
151+
pgid="pgtrigger_update_fame_on_mail_report_b3a27",
152+
table="checks_mailtestreport",
153+
when="AFTER",
154+
),
155+
),
156+
),
157+
migrations.RunSQL(
158+
sql=[
159+
'ALTER TABLE "checks_fame" ALTER COLUMN "id" ADD GENERATED BY DEFAULT AS IDENTITY;',
160+
"""
161+
WITH
162+
site_fame AS (
163+
SELECT domain, id AS site_report_id, timestamp AS site_report_timestamp FROM (
164+
SELECT domain, score, id, timestamp, rank() OVER (PARTITION BY domain ORDER BY id DESC) FROM checks_domaintestreport
165+
) alias WHERE rank = 1 AND score = 100),
166+
mail_fame AS (
167+
SELECT domain, id AS mail_report_id, timestamp AS mail_report_timestamp FROM (
168+
SELECT domain, score, id, timestamp, rank() OVER (PARTITION BY domain ORDER BY id DESC) FROM checks_mailtestreport
169+
) alias WHERE rank = 1 AND score = 100)
170+
INSERT INTO checks_fame (domain, site_report_id, site_report_timestamp, mail_report_id, mail_report_timestamp)
171+
SELECT * FROM site_fame FULL OUTER JOIN mail_fame USING (domain);
172+
""",
173+
],
174+
reverse_sql=[
175+
'DELETE FROM "checks_fame";',
176+
'ALTER TABLE "checks_fame" ALTER COLUMN "id" DROP IDENTITY;',
177+
],
178+
),
179+
]

checks/models.py

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,13 @@
77

88
from django.core.exceptions import SuspiciousFileOperation
99
from django.db import models, transaction
10+
from django.db.models import Case, F, Q, Value, When
11+
from django.db.models.functions import Greatest
12+
from django.db.models.lookups import GreaterThan
1013
from django.utils import timezone
1114
from enumfields import Enum as LabelEnum
1215
from enumfields import EnumField, EnumIntegerField
16+
import pgtrigger
1317

1418

1519
class ListField(models.TextField):
@@ -947,6 +951,34 @@ def __dir__(self):
947951
class Meta:
948952
app_label = "checks"
949953

954+
triggers = [
955+
pgtrigger.Trigger(
956+
name="update_fame_on_site_report",
957+
when=pgtrigger.After,
958+
operation=pgtrigger.Insert | pgtrigger.UpdateOf("score"),
959+
func="""
960+
IF NEW.score IS NULL THEN
961+
-- DO NOTHING
962+
ELSIF NEW.score = 100 THEN
963+
INSERT INTO checks_fame (domain, site_report_id, site_report_timestamp, mail_report_id, mail_report_timestamp)
964+
VALUES (NEW.domain, NEW.id, NEW.timestamp, NULL, NULL)
965+
ON CONFLICT (domain)
966+
DO UPDATE SET site_report_id = NEW.id, site_report_timestamp = NEW.timestamp;
967+
ELSE
968+
MERGE INTO ONLY checks_fame c1
969+
USING checks_fame c2 ON c1.domain = c2.domain AND c1.domain = NEW.domain
970+
WHEN NOT MATCHED THEN
971+
DO NOTHING
972+
WHEN MATCHED AND c1.mail_report_id IS NOT NULL THEN
973+
UPDATE SET site_report_id = NULL, site_report_timestamp = NULL
974+
WHEN MATCHED AND c1.mail_report_id IS NULL THEN
975+
DELETE;
976+
END IF;
977+
RETURN NEW;
978+
""",
979+
),
980+
]
981+
950982

951983
###
952984
# Mail test
@@ -1093,6 +1125,79 @@ def __dir__(self):
10931125
class Meta:
10941126
app_label = "checks"
10951127

1128+
triggers = [
1129+
pgtrigger.Trigger(
1130+
name="update_fame_on_mail_report",
1131+
when=pgtrigger.After,
1132+
operation=pgtrigger.Insert | pgtrigger.UpdateOf("score"),
1133+
func="""
1134+
IF NEW.score IS NULL THEN
1135+
-- DO NOTHING
1136+
ELSIF NEW.score = 100 THEN
1137+
INSERT INTO checks_fame (domain, site_report_id, site_report_timestamp, mail_report_id, mail_report_timestamp)
1138+
VALUES (NEW.domain, NULL, NULL, NEW.id, NEW.timestamp)
1139+
ON CONFLICT (domain)
1140+
DO UPDATE SET mail_report_id = NEW.id, mail_report_timestamp = NEW.timestamp;
1141+
ELSE
1142+
MERGE INTO ONLY checks_fame c1
1143+
USING checks_fame c2 ON c1.domain = c2.domain AND c1.domain = NEW.domain
1144+
WHEN NOT MATCHED THEN
1145+
DO NOTHING
1146+
WHEN MATCHED AND c1.site_report_id IS NOT NULL THEN
1147+
UPDATE SET mail_report_id = NULL, mail_report_timestamp = NULL
1148+
WHEN MATCHED AND c1.site_report_id IS NULL THEN
1149+
DELETE;
1150+
END IF;
1151+
RETURN NEW;
1152+
""",
1153+
),
1154+
]
1155+
1156+
1157+
class Fame(models.Model):
1158+
id = models.IntegerField(serialize=False, verbose_name="ID")
1159+
domain = models.CharField(max_length=255, primary_key=True, serialize=False)
1160+
site_report = models.ForeignKey(DomainTestReport, null=True, on_delete=models.CASCADE, db_index=False)
1161+
site_report_timestamp = models.DateTimeField(null=True)
1162+
mail_report = models.ForeignKey(MailTestReport, null=True, on_delete=models.CASCADE, db_index=False)
1163+
mail_report_timestamp = models.DateTimeField(null=True)
1164+
1165+
def __dir__(self):
1166+
return ["domain", "site_report", "site_report_timestamp", "mail_report", "mail_report_timestamp"]
1167+
1168+
class Meta:
1169+
app_label = "checks"
1170+
1171+
indexes = [
1172+
models.Index(
1173+
condition=Q(site_report_id__isnull=False),
1174+
fields=["-site_report_timestamp", "domain", "site_report_id"],
1175+
name="checks_fame_sites_idx",
1176+
),
1177+
models.Index(
1178+
condition=Q(mail_report_id__isnull=False),
1179+
fields=["-mail_report_timestamp", "domain", "mail_report_id"],
1180+
name="checks_fame_mail_idx",
1181+
),
1182+
# TODO: is there a way to alias/annotate the expressions?
1183+
# (so psql `\d checks_fame_champions_idx` looks nice)
1184+
models.Index(
1185+
Greatest("site_report_timestamp", "mail_report_timestamp").desc(),
1186+
"domain",
1187+
Case(
1188+
When(GreaterThan(F("site_report_timestamp"), F("mail_report_timestamp")), then=Value("s")),
1189+
default=Value("m"),
1190+
output_field=models.CharField(max_length=1),
1191+
),
1192+
Case(
1193+
When(GreaterThan(F("site_report_timestamp"), F("mail_report_timestamp")), then="site_report_id"),
1194+
default="mail_report_id",
1195+
),
1196+
condition=Q(site_report_id__isnull=False) & Q(mail_report_id__isnull=False),
1197+
name="checks_fame_champions_idx",
1198+
),
1199+
]
1200+
10961201

10971202
class BatchUser(models.Model):
10981203
"""

0 commit comments

Comments
 (0)