Skip to content

Commit b87fc1a

Browse files
chore(launchpad): Simplify launchpad upload logic (#97435)
Create the preprod artifact row without file id set. Then pass it to the background task that can set the value post file assembly Also: - No longer poll while the file is being assembled - No longer worry about saving assemble status values (not used anymore) - Return artifact id still
1 parent 87c963d commit b87fc1a

File tree

4 files changed

+249
-138
lines changed

4 files changed

+249
-138
lines changed

src/sentry/preprod/api/endpoints/organization_preprod_artifact_assemble.py

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,8 @@
1313
from sentry.debug_files.upload import find_missing_chunks
1414
from sentry.models.orgauthtoken import is_org_auth_token_auth, update_org_auth_token_last_used
1515
from sentry.preprod.analytics import PreprodArtifactApiAssembleEvent
16-
from sentry.preprod.tasks import assemble_preprod_artifact
17-
from sentry.tasks.assemble import (
18-
AssembleTask,
19-
ChunkFileState,
20-
get_assemble_status,
21-
set_assemble_status,
22-
)
16+
from sentry.preprod.tasks import assemble_preprod_artifact, create_preprod_artifact
17+
from sentry.tasks.assemble import ChunkFileState
2318
from sentry.types.ratelimit import RateLimit, RateLimitCategory
2419

2520

@@ -121,29 +116,39 @@ def post(self, request: Request, project) -> Response:
121116
}
122117
)
123118

124-
# Check current assembly status
125-
state, detail = get_assemble_status(AssembleTask.PREPROD_ARTIFACT, project.id, checksum)
126-
if state is not None:
127-
return Response({"state": state, "detail": detail, "missingChunks": []})
128-
129119
# There is neither a known file nor a cached state, so we will
130120
# have to create a new file. Assure that there are checksums.
131121
# If not, we assume this is a poll and report NOT_FOUND
132122
if not chunks:
133123
return Response({"state": ChunkFileState.NOT_FOUND, "missingChunks": []})
134124

135-
set_assemble_status(
136-
AssembleTask.PREPROD_ARTIFACT, project.id, checksum, ChunkFileState.CREATED
125+
artifact_id = create_preprod_artifact(
126+
org_id=project.organization_id,
127+
project_id=project.id,
128+
checksum=checksum,
129+
build_configuration=data.get("build_configuration"),
137130
)
131+
132+
if artifact_id is None:
133+
return Response(
134+
{
135+
"state": ChunkFileState.ERROR,
136+
"detail": "Failed to create preprod artifact row.",
137+
}
138+
)
139+
138140
assemble_preprod_artifact.apply_async(
139141
kwargs={
140142
"org_id": project.organization_id,
141143
"project_id": project.id,
142144
"checksum": checksum,
143145
"chunks": chunks,
146+
"artifact_id": artifact_id,
144147
}
145148
)
146149
if is_org_auth_token_auth(request.auth):
147150
update_org_auth_token_last_used(request.auth, [project.id])
148151

149-
return Response({"state": ChunkFileState.CREATED, "missingChunks": []})
152+
return Response(
153+
{"state": ChunkFileState.OK, "missingChunks": [], "artifactId": artifact_id}
154+
)

src/sentry/preprod/tasks.py

Lines changed: 59 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ def assemble_preprod_artifact(
5050
project_id,
5151
checksum,
5252
chunks,
53+
artifact_id,
5354
**kwargs,
5455
) -> None:
5556
"""
@@ -70,10 +71,6 @@ def assemble_preprod_artifact(
7071
project = Project.objects.get(id=project_id, organization=organization)
7172
bind_organization_context(organization)
7273

73-
set_assemble_status(
74-
AssembleTask.PREPROD_ARTIFACT, project_id, checksum, ChunkFileState.ASSEMBLING
75-
)
76-
7774
assemble_result = assemble_file(
7875
task=AssembleTask.PREPROD_ARTIFACT,
7976
org_or_project=project,
@@ -84,23 +81,29 @@ def assemble_preprod_artifact(
8481
)
8582

8683
if assemble_result is None:
87-
# Shouldn't we treat this as an error?
88-
logger.warning(
89-
"Assemble result is None, returning early",
90-
extra={
91-
"project_id": project_id,
92-
"organization_id": org_id,
93-
"checksum": checksum,
94-
},
84+
raise RuntimeError(
85+
f"Assemble result is None for preprod artifact assembly (project_id={project_id}, organization_id={org_id}, checksum={checksum}, preprod_artifact_id={artifact_id})"
9586
)
96-
return
9787

98-
create_preprod_artifact(
99-
org_id=org_id,
100-
project_id=project_id,
101-
checksum=checksum,
88+
logger.info(
89+
"Finished preprod artifact assembly",
90+
extra={
91+
"project_id": project_id,
92+
"organization_id": org_id,
93+
"checksum": checksum,
94+
"preprod_artifact_id": artifact_id,
95+
},
96+
)
97+
98+
PreprodArtifact.objects.filter(id=artifact_id).update(
10299
file_id=assemble_result.bundle.id,
103-
build_configuration=kwargs.get("build_configuration"),
100+
state=PreprodArtifact.ArtifactState.UPLOADED,
101+
)
102+
103+
produce_preprod_artifact_to_kafka(
104+
project_id=project_id,
105+
organization_id=org_id,
106+
artifact_id=artifact_id,
104107
)
105108

106109
except Exception as e:
@@ -111,22 +114,18 @@ def assemble_preprod_artifact(
111114
"project_id": project_id,
112115
"organization_id": org_id,
113116
"checksum": checksum,
117+
"preprod_artifact_id": artifact_id,
114118
},
115119
)
116-
set_assemble_status(
117-
AssembleTask.PREPROD_ARTIFACT,
118-
project_id,
119-
checksum,
120-
ChunkFileState.ERROR,
121-
detail=str(e),
120+
PreprodArtifact.objects.filter(id=artifact_id).update(
121+
state=PreprodArtifact.ArtifactState.FAILED
122122
)
123123
return
124124

125-
# Mark assembly as successful since the artifact was created successfully
126-
set_assemble_status(AssembleTask.PREPROD_ARTIFACT, project_id, checksum, ChunkFileState.OK)
127125
logger.info(
128-
"Finished preprod artifact assembly",
126+
"Finished preprod artifact row creation and kafka dispatch",
129127
extra={
128+
"preprod_artifact_id": artifact_id,
130129
"project_id": project_id,
131130
"organization_id": org_id,
132131
"checksum": checksum,
@@ -138,53 +137,50 @@ def create_preprod_artifact(
138137
org_id,
139138
project_id,
140139
checksum,
141-
file_id,
142140
build_configuration=None,
143-
):
144-
organization = Organization.objects.get_from_cache(pk=org_id)
145-
project = Project.objects.get(id=project_id, organization=organization)
146-
bind_organization_context(organization)
141+
) -> str | None:
142+
try:
143+
organization = Organization.objects.get_from_cache(pk=org_id)
144+
project = Project.objects.get(id=project_id, organization=organization)
145+
bind_organization_context(organization)
147146

148-
with transaction.atomic(router.db_for_write(PreprodArtifact)):
149-
build_config = None
150-
if build_configuration:
151-
build_config, _ = PreprodBuildConfiguration.objects.get_or_create(
147+
with transaction.atomic(router.db_for_write(PreprodArtifact)):
148+
build_config = None
149+
if build_configuration:
150+
build_config, _ = PreprodBuildConfiguration.objects.get_or_create(
151+
project=project,
152+
name=build_configuration,
153+
)
154+
155+
preprod_artifact, _ = PreprodArtifact.objects.get_or_create(
152156
project=project,
153-
name=build_configuration,
157+
build_configuration=build_config,
158+
state=PreprodArtifact.ArtifactState.UPLOADING,
154159
)
155160

156-
preprod_artifact, _ = PreprodArtifact.objects.get_or_create(
157-
project=project,
158-
file_id=file_id,
159-
build_configuration=build_config,
160-
state=PreprodArtifact.ArtifactState.UPLOADED,
161-
)
161+
logger.info(
162+
"Created preprod artifact row",
163+
extra={
164+
"preprod_artifact_id": preprod_artifact.id,
165+
"project_id": project_id,
166+
"organization_id": org_id,
167+
"checksum": checksum,
168+
},
169+
)
162170

163-
logger.info(
164-
"Created preprod artifact",
171+
return str(preprod_artifact.id)
172+
173+
except Exception as e:
174+
sentry_sdk.capture_exception(e)
175+
logger.exception(
176+
"Failed to create preprod artifact row",
165177
extra={
166-
"preprod_artifact_id": preprod_artifact.id,
167178
"project_id": project_id,
168179
"organization_id": org_id,
169180
"checksum": checksum,
170181
},
171182
)
172-
173-
produce_preprod_artifact_to_kafka(
174-
project_id=project_id,
175-
organization_id=org_id,
176-
artifact_id=preprod_artifact.id,
177-
)
178-
179-
logger.info(
180-
"Finished preprod artifact row creation and kafka dispatch",
181-
extra={
182-
"preprod_artifact_id": preprod_artifact.id,
183-
"project_id": project_id,
184-
"organization_id": org_id,
185-
"checksum": checksum,
186-
},
187-
)
183+
return None
188184

189185

190186
def _assemble_preprod_artifact_file(
@@ -262,7 +258,7 @@ def _assemble_preprod_artifact_size_analysis(
262258
logger.exception(
263259
"PreprodArtifact not found during size analysis assembly",
264260
extra={
265-
"artifact_id": artifact_id,
261+
"preprod_artifact_id": artifact_id,
266262
"project_id": project.id,
267263
"organization_id": org_id,
268264
},

0 commit comments

Comments
 (0)