Skip to content

Commit c16928a

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

File tree

14 files changed

+377
-412
lines changed

14 files changed

+377
-412
lines changed
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
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+
# The primary key on domain is added in SQL to prevent a _like index
22+
migrations.CreateModel(
23+
name="Fame",
24+
fields=[
25+
("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
26+
("domain", models.CharField(max_length=255)),
27+
(
28+
"site_report",
29+
models.ForeignKey(
30+
db_index=False,
31+
null=True,
32+
on_delete=django.db.models.deletion.CASCADE,
33+
to="checks.domaintestreport",
34+
),
35+
),
36+
("site_report_timestamp", models.DateTimeField(null=True)),
37+
(
38+
"mail_report",
39+
models.ForeignKey(
40+
db_index=False,
41+
null=True,
42+
on_delete=django.db.models.deletion.CASCADE,
43+
to="checks.mailtestreport",
44+
),
45+
),
46+
("mail_report_timestamp", models.DateTimeField(null=True)),
47+
],
48+
),
49+
migrations.AddIndex(
50+
model_name="fame",
51+
index=models.Index(
52+
condition=models.Q(site_report_id__isnull=False),
53+
fields=["-site_report_timestamp", "domain", "site_report_id"],
54+
name="checks_fame_sites_idx",
55+
),
56+
),
57+
migrations.AddIndex(
58+
model_name="fame",
59+
index=models.Index(
60+
condition=models.Q(mail_report_id__isnull=False),
61+
fields=["-mail_report_timestamp", "domain", "mail_report_id"],
62+
name="checks_fame_mail_idx",
63+
),
64+
),
65+
migrations.AddIndex(
66+
model_name="fame",
67+
index=models.Index(
68+
models.OrderBy(
69+
Greatest("site_report_timestamp", "mail_report_timestamp"),
70+
descending=True,
71+
),
72+
"domain",
73+
Case(
74+
models.When(
75+
GreaterThan(F("site_report_timestamp"), F("mail_report_timestamp")),
76+
then=Value("s"),
77+
),
78+
default=Value("m"),
79+
output_field=models.CharField(max_length=1),
80+
),
81+
Case(
82+
When(
83+
GreaterThan(F("site_report_timestamp"), F("mail_report_timestamp")),
84+
then="site_report_id",
85+
),
86+
default="mail_report_id",
87+
),
88+
condition=Q(site_report_id__isnull=False) & Q(mail_report_id__isnull=False),
89+
name="checks_fame_champions_idx",
90+
),
91+
),
92+
pgtrigger.migrations.AddTrigger(
93+
model_name="domaintestreport",
94+
trigger=pgtrigger.compiler.Trigger(
95+
name="update_fame_on_site_report",
96+
sql=pgtrigger.compiler.UpsertTriggerSql(
97+
func="""
98+
IF NEW.score IS NULL THEN
99+
-- DO NOTHING
100+
ELSIF NEW.score = 100 THEN
101+
INSERT INTO checks_fame (domain, site_report_id, site_report_timestamp, mail_report_id, mail_report_timestamp)
102+
VALUES (NEW.domain, NEW.id, NEW.timestamp, NULL, NULL)
103+
ON CONFLICT (domain)
104+
DO UPDATE SET site_report_id = NEW.id, site_report_timestamp = NEW.timestamp;
105+
ELSE
106+
MERGE INTO ONLY checks_fame c1
107+
USING checks_fame c2 ON c1.domain = c2.domain AND c1.domain = NEW.domain
108+
WHEN NOT MATCHED THEN
109+
DO NOTHING
110+
WHEN MATCHED AND c1.mail_report_id IS NOT NULL THEN
111+
UPDATE SET site_report_id = NULL, site_report_timestamp = NULL
112+
WHEN MATCHED AND c1.mail_report_id IS NULL THEN
113+
DELETE;
114+
END IF;
115+
RETURN NEW;
116+
""",
117+
hash="b4f792b06123914de71b57669c202a19b04e9e9c",
118+
operation='INSERT OR UPDATE OF "score"',
119+
pgid="pgtrigger_update_fame_on_site_report_e4fdc",
120+
table="checks_domaintestreport",
121+
when="AFTER",
122+
),
123+
),
124+
),
125+
pgtrigger.migrations.AddTrigger(
126+
model_name="mailtestreport",
127+
trigger=pgtrigger.compiler.Trigger(
128+
name="update_fame_on_mail_report",
129+
sql=pgtrigger.compiler.UpsertTriggerSql(
130+
func="""
131+
IF NEW.score IS NULL THEN
132+
-- DO NOTHING
133+
ELSIF NEW.score = 100 THEN
134+
INSERT INTO checks_fame (domain, site_report_id, site_report_timestamp, mail_report_id, mail_report_timestamp)
135+
VALUES (NEW.domain, NULL, NULL, NEW.id, NEW.timestamp)
136+
ON CONFLICT (domain)
137+
DO UPDATE SET mail_report_id = NEW.id, mail_report_timestamp = NEW.timestamp;
138+
ELSE
139+
MERGE INTO ONLY checks_fame c1
140+
USING checks_fame c2 ON c1.domain = c2.domain AND c1.domain = NEW.domain
141+
WHEN NOT MATCHED THEN
142+
DO NOTHING
143+
WHEN MATCHED AND c1.site_report_id IS NOT NULL THEN
144+
UPDATE SET mail_report_id = NULL, mail_report_timestamp = NULL
145+
WHEN MATCHED AND c1.site_report_id IS NULL THEN
146+
DELETE;
147+
END IF;
148+
RETURN NEW;
149+
""",
150+
hash="707aefc7a83dd041dd815511f1d1cf7e8f84f944",
151+
operation='INSERT OR UPDATE OF "score"',
152+
pgid="pgtrigger_update_fame_on_mail_report_b3a27",
153+
table="checks_mailtestreport",
154+
when="AFTER",
155+
),
156+
),
157+
),
158+
migrations.RunSQL(
159+
sql=[
160+
'ALTER TABLE "checks_fame" DROP CONSTRAINT "checks_fame_pkey";',
161+
'ALTER TABLE "checks_fame" ADD PRIMARY KEY ("domain");',
162+
"""
163+
WITH
164+
site_fame AS (
165+
SELECT domain, id AS site_report_id, timestamp AS site_report_timestamp FROM (
166+
SELECT domain, score, id, timestamp, rank() OVER (PARTITION BY domain ORDER BY id DESC) FROM checks_domaintestreport
167+
) alias WHERE rank = 1 AND score = 100),
168+
mail_fame AS (
169+
SELECT domain, id AS mail_report_id, timestamp AS mail_report_timestamp FROM (
170+
SELECT domain, score, id, timestamp, rank() OVER (PARTITION BY domain ORDER BY id DESC) FROM checks_mailtestreport
171+
) alias WHERE rank = 1 AND score = 100)
172+
INSERT INTO checks_fame (domain, site_report_id, site_report_timestamp, mail_report_id, mail_report_timestamp)
173+
SELECT * FROM site_fame FULL OUTER JOIN mail_fame USING (domain);
174+
""",
175+
],
176+
reverse_sql=[
177+
'DELETE FROM "checks_fame";',
178+
'ALTER TABLE "checks_fame" DROP CONSTRAINT "checks_fame_pkey";',
179+
'ALTER TABLE "checks_fame" ADD PRIMARY KEY ("id");',
180+
],
181+
state_operations=[
182+
migrations.AddConstraint("Fame", models.UniqueConstraint(fields=["domain"], name="checks_fame_pkey")),
183+
migrations.AddIndex("Fame", models.Index(fields=["domain"], name="checks_fame_pkey")),
184+
],
185+
),
186+
]

checks/models.py

Lines changed: 110 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,84 @@ 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.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")
1159+
domain = models.CharField(max_length=255)
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+
constraints = [
1172+
models.UniqueConstraint(fields=["domain"], name="checks_fame_pkey"),
1173+
]
1174+
1175+
indexes = [
1176+
models.Index(fields=["domain"], name="checks_fame_pkey"),
1177+
models.Index(
1178+
condition=Q(site_report_id__isnull=False),
1179+
fields=["-site_report_timestamp", "domain", "site_report_id"],
1180+
name="checks_fame_sites_idx",
1181+
),
1182+
models.Index(
1183+
condition=Q(mail_report_id__isnull=False),
1184+
fields=["-mail_report_timestamp", "domain", "mail_report_id"],
1185+
name="checks_fame_mail_idx",
1186+
),
1187+
# TODO: is there a way to alias/annotate the expressions?
1188+
# (so psql `\d checks_fame_champions_idx` looks nice)
1189+
models.Index(
1190+
Greatest("site_report_timestamp", "mail_report_timestamp").desc(),
1191+
"domain",
1192+
Case(
1193+
When(GreaterThan(F("site_report_timestamp"), F("mail_report_timestamp")), then=Value("s")),
1194+
default=Value("m"),
1195+
output_field=models.CharField(max_length=1),
1196+
),
1197+
Case(
1198+
When(GreaterThan(F("site_report_timestamp"), F("mail_report_timestamp")), then="site_report_id"),
1199+
default="mail_report_id",
1200+
),
1201+
condition=Q(site_report_id__isnull=False) & Q(mail_report_id__isnull=False),
1202+
name="checks_fame_champions_idx",
1203+
),
1204+
]
1205+
10961206

10971207
class BatchUser(models.Model):
10981208
"""

0 commit comments

Comments
 (0)