Skip to content

Commit 5fcb5ea

Browse files
committed
Bulk insert at an importer level in ImporterRunner
Signed-off-by: Shivam Sandbhor <shivam.sandbhor@gmail.com>
1 parent bfda9af commit 5fcb5ea

1 file changed

Lines changed: 40 additions & 27 deletions

File tree

vulnerabilities/import_runner.py

Lines changed: 40 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
from typing import List
3030
from typing import Set
3131
from typing import Tuple
32+
from typing import Optional
3233

3334
import packageurl
3435
from django.db import DataError
@@ -41,6 +42,21 @@
4142

4243
logger = logging.getLogger(__name__)
4344

45+
@dataclasses.dataclass(frozen=True)
46+
class VulnerabilityReference_inserter :
47+
vulnerability : models.Vulnerability
48+
reference_id : Optional[str] = ''
49+
url : Optional[str] = ''
50+
51+
def __post_init__(self):
52+
if not any([self.reference_id,self.url]) :
53+
raise TypeError("VulnerabilityReference_inserter expects either reference_id or url")
54+
55+
@dataclasses.dataclass(frozen=True)
56+
class Vulnerability_Package_inserter :
57+
vulnerability : models.Vulnerability
58+
is_vulnerable : bool
59+
package : models.Package
4460

4561
class ImportRunner:
4662
"""
@@ -89,23 +105,22 @@ def _process_updated_advisories(data_source: DataSource) -> None:
89105
"""
90106
TODO: Break this method into smaller functions
91107
"""
108+
bulk_create_vuln_refs = set()
109+
bulk_create_vuln_pkg_refs = set()
110+
bulk_update_vuln_pkg_refs = set()
92111
for batch in data_source.updated_advisories():
93112
for advisory in batch:
94-
95-
bulk_create_vuln_refs = []
96-
bulk_update_vuln_pkg_refs = []
97-
bulk_create_vuln_pkg_refs = []
98-
99113
vuln, vuln_created = _get_or_create_vulnerability(advisory)
100114

101115
if vuln_created:
102116
# This means vulnerability didn't previously exist in the db, so bulk create
103117
# is used without any hesitation
104118
for id_ in set(advisory.reference_ids):
105-
bulk_create_vuln_refs.append(models.VulnerabilityReference(vulnerability=vuln, reference_id=id_))
119+
# bulk_create_vuln_refs.append(models.VulnerabilityReference(vulnerability=vuln, reference_id=id_))
120+
bulk_create_vuln_refs.add(VulnerabilityReference_inserter(vulnerability=vuln, reference_id=id_))
106121

107122
for url in set(advisory.reference_urls):
108-
bulk_create_vuln_refs.append(models.VulnerabilityReference(vulnerability=vuln, url=url))
123+
bulk_create_vuln_refs.add(VulnerabilityReference_inserter(vulnerability=vuln, url=url))
109124

110125
else:
111126
vuln_refs_qs = models.VulnerabilityReference.objects.filter(vulnerability=vuln)
@@ -115,60 +130,58 @@ def _process_updated_advisories(data_source: DataSource) -> None:
115130
vuln_urls = {ref.url for ref in vuln_refs_qs}
116131

117132
for id_ in advisory.reference_ids:
118-
if id_ not in vuln_ids :
119-
# Delete the item because it will allow the duplicates pass to through if they are not
120-
# present in vuln_ids
133+
# Add the item preventing duplicates pass to through.
134+
if id_ not in vuln_ids :
121135
vuln_ids.add(id_)
122-
bulk_create_vuln_refs.append(models.VulnerabilityReference(vulnerability=vuln, reference_id=id_))
136+
bulk_create_vuln_refs.add(VulnerabilityReference_inserter(vulnerability=vuln, reference_id=id_))
123137

124138
for url in advisory.reference_urls:
125-
# Delete the item because it will allow the duplicates pass to through if they are not
126-
# present in vuln_urls
139+
# Add the item preventing duplicates pass to through.
127140
if url not in vuln_urls:
128141
vuln_urls.add(url)
129-
bulk_create_vuln_refs.append(models.VulnerabilityReference(vulnerability=vuln, url=url))
130-
131-
models.VulnerabilityReference.objects.bulk_create(bulk_create_vuln_refs)
142+
bulk_create_vuln_refs.add(VulnerabilityReference_inserter(vulnerability=vuln, url=url))
143+
132144

133145
for ipurl in advisory.impacted_package_urls :
134146
pkg, pkg_created = _get_or_create_package(ipurl)
135-
vuln_pkgs_ref = models.Vulnerability_Package_Relation(package=pkg,vulnerability=vuln,is_vulnerable=True)
147+
vuln_pkgs_ref = Vulnerability_Package_inserter(package=pkg,vulnerability=vuln,is_vulnerable=True)
136148

137149
if pkg_created or vuln_created :
138-
bulk_create_vuln_pkg_refs.append(vuln_pkgs_ref)
150+
bulk_create_vuln_pkg_refs.add(vuln_pkgs_ref)
139151

140152
else:
141153
qs = models.Vulnerability_Package_Relation.objects.filter(package=pkg,vulnerability=vuln)
142154
if qs:
143155
if not qs[0].is_vulnerable:
144156
qs[0].is_vulnerable = True
145-
bulk_update_vuln_pkg_refs.append(qs[0])
157+
bulk_update_vuln_pkg_refs.add(qs[0])
146158

147159
else:
148-
bulk_create_vuln_pkg_refs.append(vuln_pkgs_ref)
160+
bulk_create_vuln_pkg_refs.add(vuln_pkgs_ref)
149161

150162
for rpurl in advisory.resolved_package_urls :
151163
pkg, pkg_created = _get_or_create_package(rpurl)
152-
vuln_pkgs_ref = models.Vulnerability_Package_Relation(package=pkg,vulnerability=vuln,is_vulnerable=False)
164+
vuln_pkgs_ref = Vulnerability_Package_inserter(package=pkg,vulnerability=vuln,is_vulnerable=True)
153165

154166
if pkg_created or vuln_created :
155167
# For a `Vulnerability_Package_Relation` tp exist it needs both, the package and
156168
# vulnerability to already exist in the db.
157-
bulk_create_vuln_pkg_refs.append(vuln_pkgs_ref)
169+
bulk_create_vuln_pkg_refs.add(vuln_pkgs_ref)
158170

159171
else:
160172
qs = models.Vulnerability_Package_Relation.objects.filter(package=pkg,vulnerability=vuln)
161173
if qs:
162174
if qs[0].is_vulnerable :
163175
qs[0].is_vulnerable = False
164-
bulk_update_vuln_pkg_refs.append(qs[0])
176+
bulk_update_vuln_pkg_refs.add(qs[0])
165177

166178
else:
167-
bulk_create_vuln_pkg_refs.append(vuln_pkgs_ref)
179+
bulk_create_vuln_pkg_refs.add(vuln_pkgs_ref)
180+
181+
models.Vulnerability_Package_Relation.objects.bulk_update(bulk_update_vuln_pkg_refs, ['is_vulnerable'])
182+
models.Vulnerability_Package_Relation.objects.bulk_create([models.Vulnerability_Package_Relation(**dataclasses.asdict(i)) for i in bulk_create_vuln_pkg_refs])
183+
models.VulnerabilityReference.objects.bulk_create([models.VulnerabilityReference(**dataclasses.asdict(i)) for i in bulk_create_vuln_refs])
168184

169-
models.Vulnerability_Package_Relation.objects.bulk_update(bulk_update_vuln_pkg_refs, ['is_vulnerable'])
170-
models.Vulnerability_Package_Relation.objects.bulk_create(bulk_create_vuln_pkg_refs)
171-
172185
def _process_added_advisories(data_source: DataSource) -> None:
173186
for batch in data_source.added_advisories():
174187
try:

0 commit comments

Comments
 (0)