Skip to content

ref: serialize release and userReport #10921

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 3, 2019
Merged

Conversation

alex-hofsteede
Copy link
Contributor

No description provided.

@alex-hofsteede alex-hofsteede changed the base branch from hoff/event-id-endpoint to master December 5, 2018 00:37
@@ -217,6 +240,9 @@ def serialize(self, obj, attrs, user):
'packages': packages_meta,
'tags': tags_meta,
},
'release': self._get_release_info(user, obj),
'userReport': self._get_user_report(user, obj),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think since this serializer is used for endpoints that return more than a single event (for example ProjectEventsEndpoint) you may want to do these as bulk queries in get_attrs to avoid making a query for each item. So for example, you could do:

def get_attrs(self, item_list, user, is_public=False):
    ...
    user_reports = {ur.event_id: ur and serialize(ur, user) for ur in UserReport.objects.filter(
        event_id__in=[item.event_id for item in item_list],
        project=event.project,
    )}
    ...
    for item in item_list:
        ...
        results[item] = {
            user_report: user_reports.get(item.event_id),
    ...

and then in serialize you could just do 'userReport': attrs['user_report']

And then something similar for release.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@macqueen Do you know if this is ever used to serialize lists of events from different projects? because the expression to query for multiple releases might get a little hairy if it does.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm good question/point. i think right now, it's only from one project, but with all the stuff we're doing that could easily change in the near future.

to do the bulk query, i think you'd have to do something like this:

releases = list(
    Release.objects.filter(
        version__in=[i.get_tag('sentry:release') for i in item_list],
        projects__in=[i.project_id for i in item_list]
        organization_id=item_list[0].project.organization_id, # we could add an assertion that these are from the same org
    )
)

releases_by_version = {
    r['version']: r for r in serialize(releases, user)
}

release_projects_lookup = defaultdict(set)
for rp in ReleaseProject.objects.filter(
    release_id__in=[r.id for r in releases]
).values('release__version', 'project_id'):
    release_projects_lookup[rp['release__version']].add(rp{'project_id'})


for item in item_list:
    release = releases_by_version.get(item.get_tag('sentry:release'))
    if release is not None and item.project_id not in release_projects_lookup[release['version']:
        release = None

which as you said, is pretty gross. the other alternative is just doing something like DetailedEventSerializer which inherits from EventSerializer and you could just add this stuff there and use that in the details endpoints so it's only adding queries to those?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean, I think it would actually be a little grosser than that even, because version__in=..., projects__in=... will grab the product of all the versions and all the projects, eg if we are looking for version A from project 1 and version B from project 2, it will also grab version A from project 2 and version B from project 1.

So really it'd have to be something like:

Release.objects.filter(Q(version=..., project=...) | Q(version=..., project=...) | ...)

So yeah I think I may just do the subclass thing instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Except... I also don't really want 2 serializer classes for 1 class because that kinda breaks the @register() / serialize() system

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we already have this for a few models (see OrganizationSerializer and DetailedOrganizationSerializer) -- there's an optional serializer argument to serialize to override the register system

@alex-hofsteede
Copy link
Contributor Author

alex-hofsteede commented Dec 17, 2018

@macqueen OK I think this is ready now with the serialization done in a separate class.

@alex-hofsteede alex-hofsteede merged commit 6734ece into master Jan 3, 2019
@markstory markstory deleted the hoff/serialize-release branch February 12, 2019 15:54
@github-actions github-actions bot locked and limited conversation to collaborators Dec 20, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants