feat(difs): Add Objectstore columns to ProjectDebugFile#117500
Conversation
|
This PR has a migration; here is the generated SQL for for --
-- Alter field file on projectdebugfile
--
SET CONSTRAINTS "sentry_projectdsymfile_file_id_bdf41a41_fk_sentry_file_id" IMMEDIATE; ALTER TABLE "sentry_projectdsymfile" DROP CONSTRAINT "sentry_projectdsymfile_file_id_bdf41a41_fk_sentry_file_id";
ALTER TABLE "sentry_projectdsymfile" ALTER COLUMN "file_id" DROP NOT NULL;
ALTER TABLE "sentry_projectdsymfile" ADD CONSTRAINT "sentry_projectdsymfile_file_id_bdf41a41_fk_sentry_file_id" FOREIGN KEY ("file_id") REFERENCES "sentry_file" ("id") DEFERRABLE INITIALLY DEFERRED NOT VALID;
ALTER TABLE "sentry_projectdsymfile" VALIDATE CONSTRAINT "sentry_projectdsymfile_file_id_bdf41a41_fk_sentry_file_id";
--
-- Add field storage_path to projectdebugfile
--
ALTER TABLE "sentry_projectdsymfile" ADD COLUMN "storage_path" text NULL;
--
-- Add field content_type to projectdebugfile
--
ALTER TABLE "sentry_projectdsymfile" ADD COLUMN "content_type" text NULL;
--
-- Add field file_size to projectdebugfile
--
ALTER TABLE "sentry_projectdsymfile" ADD COLUMN "file_size" bigint NULL;
--
-- Add field date_created to projectdebugfile
--
ALTER TABLE "sentry_projectdsymfile" ADD COLUMN "date_created" timestamp with time zone NULL; |
7c7b0ee to
0b95ff7
Compare
Add new nullable columns (storage_path, content_type, file_size, date_created) and make the File FK nullable in preparation for migrating debug files to Objectstore.
0b95ff7 to
4fe3b25
Compare
|
|
||
| @property | ||
| def file_format(self) -> str: | ||
| assert self.file is not None | ||
| ct = self.file.headers.get("Content-Type", "unknown").lower() | ||
| return KNOWN_DIF_FORMATS.get(ct, "unknown") | ||
|
|
There was a problem hiding this comment.
Bug: Serializing a DebugFile with a None file attribute (for Objectstore-backed DIFs) raises an AssertionError or AttributeError because the serializer does not handle the null case.
Severity: CRITICAL
Suggested Fix
Update DebugFileSerializer to handle cases where obj.file is None. Use obj.content_type and other direct attributes from the DebugFile model for Objectstore-backed DIFs instead of accessing them through the now-nullable file relation. Remove the assert self.file is not None from the file_format property and add logic to handle the None case.
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.
Location: src/sentry/models/debugfile.py#L156-L162
Potential issue: The `DebugFileSerializer` attempts to serialize debug information files
(DIFs) by accessing attributes of `obj.file`, such as `obj.file.headers` and
`obj.file.size`. It also calls the `obj.file_format` property. However, for DIFs backed
by Objectstore, the `file` attribute is `None`. The `file_format` property contains an
`assert self.file is not None`, which will raise an `AssertionError`. Direct access to
`obj.file` attributes will raise an `AttributeError`. This causes any API endpoint that
serializes these DIFs, such as the `DebugFilesEndpoint`, to crash.
Also affects:
src/sentry/models/debugfile.py:130~136
Did we get this right? 👍 / 👎 to inform future reviews.
| uuidmap_seen = False | ||
| il2cpp_seen = False | ||
| for i, dif in enumerate(difs): | ||
| assert dif.file is not None | ||
| mime_type = dif.file.headers.get("Content-Type") | ||
| if mime_type == DIF_MIMETYPES["bcsymbolmap"]: | ||
| if not bcsymbolmap_seen: |
There was a problem hiding this comment.
Bug: The clean_redundant_difs function unconditionally asserts dif.file is not None, which will fail and crash uploads if any existing DIF for the same debug_id is Objectstore-backed.
Severity: HIGH
Suggested Fix
Modify clean_redundant_difs to correctly handle ProjectDebugFile instances where file is None. Instead of asserting dif.file is not None to get the content type, use dif.content_type which is available on the model directly and supports both file-backed and Objectstore-backed DIFs.
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.
Location: src/sentry/models/debugfile.py#L237-L243
Potential issue: The function `clean_redundant_difs` is called after a new debug
information file (DIF) is uploaded. It queries for all existing `ProjectDebugFile`
records with the same `debug_id` and iterates through them. Inside the loop, it
unconditionally runs `assert dif.file is not None`. If a pre-existing DIF for that
`debug_id` is backed by Objectstore, its `file` attribute will be `None`, causing the
assertion to fail. This will crash the upload process for any new DIF that shares a
`debug_id` with an Objectstore-backed DIF.
Did we get this right? 👍 / 👎 to inform future reviews.
|
Is the idea behind making the |
|
Yeah @loewenheim, we could very well split this into 2 separate migrations, would it be preferable to do it that way? The intention was not really to spare a migration, but to make the |
|
If having two separate migrations isn't a concern, I would prefer it if the |
|
Yeah that makes sense, I'll change it. |
Adds new columns to house Objectstore-backed difs.
These will lose the
fileFK and gain thestorage_pathfield.In addition, we also need to add
content_type,file_sizeanddate_created, as those were previously fields ofFile.Naturally, during the migration period, both of these need to be nullable, so we need to assert the invariants we know to be true at runtime.