Skip to content

Proxito: better way to pass current version/project down to the middleware #10456

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

Open
stsewd opened this issue Jun 21, 2023 · 3 comments
Open
Labels
Improvement Minor improvement to code

Comments

@stsewd
Copy link
Member

stsewd commented Jun 21, 2023

What's the problem this feature will solve?

Right now we are passing only the slug of the version/project, if the middleware needs to have access to the object itself, it needs to re-fetch it from the database.

For example in

if project_slug:
project = Project.objects.get(slug=project_slug)
# Check for the feature flag
if project.has_feature(Feature.HOSTING_INTEGRATIONS):
addons = True
else:
# Check if the version forces injecting the addons (e.g. using `build.commands`)
version = (
project.versions.filter(slug=version_slug).only("addons").first()
)

Describe the solution you'd like

Pass the object that we already have from using the unresolver / doc serving views

Alternative solutions

None

Additional context

We have several TODOs around this

# TODO: find a better way to pass this to the middleware.
request.path_project_slug = project.slug

We can't fully implement this untill we have migrated all projects to use the new proxito implementation, since the old one doesn't always have access to the object itself

request.path_project_slug = final_project.slug
request.path_version_slug = version_slug

This is also somewhat related to #10124, and any other things that make use of those attributes from the middleware.

@stsewd stsewd added the Improvement Minor improvement to code label Jun 21, 2023
@humitos
Copy link
Member

humitos commented Jun 22, 2023

Pass the object that we already have from using the unresolver / doc serving views

What's the object you mean here? The Project itself? If that's what you are thinking, I'd like to talk about this a little more because I'd prefer to avoid having "multiple variables" injected in the request. Instead, I'd like to have one readthedocs object that we control and where we can add as much data as we need. This way, we always know what we are inject and where to look for it. I mentioned this before in some of the refactor PRs you worked on.

Having one and only one object will help us to when parsing the code to find out where we are injecting things. Right now, it's hard to answer that question with a simple grep or similar tools.

As an example,

request.readthedocs = RequestData(
  initial=request.readthedocs, 
  project=self.project,   # may not be needed if we pass the `unresolved_url`, tho
  unresolved_url=unresolved_url,
)

The initial allows us to initialize with data we already have in the request and override/add only the new fields we want. What do you think of an approach similar to this?

@github-project-automation github-project-automation bot moved this to Planned in 📍Roadmap Jun 22, 2023
humitos added a commit that referenced this issue Jun 22, 2023
We don't need the `Project` instance. We were using to check for a Feature flag,
but now we are only adding the header when the project is using
`build.commands`.

If we ever require the `Project` instance again, we can do a `.select_related`
from the `Version` object. That way, we still keep doing 1 query only.

Closes #10458
Related #10456
@stsewd
Copy link
Member Author

stsewd commented Jun 22, 2023

Scoping it is fine, not sure we need initial, we can just override the attribute we need, we can probably start by injecting the project and version, we don't always have the unresolved URL available.

humitos added a commit that referenced this issue Jun 22, 2023
)

We don't need the `Project` instance. We were using to check for a Feature flag,
but now we are only adding the header when the project is using
`build.commands`.

If we ever require the `Project` instance again, we can do a `.select_related`
from the `Version` object. That way, we still keep doing 1 query only.

Closes #10458
Related #10456
humitos added a commit that referenced this issue Apr 4, 2024
A better way of resolving this issue will be done in
#10456
@humitos
Copy link
Member

humitos commented Apr 9, 2024

I just want to note here that I found myself (while working on #11205) wanting to share the Resolver() instance all across the request. This is because checking the canonical domain and other stuffs could be cached that way.

humitos added a commit that referenced this issue Apr 16, 2024
* APIv3: add more generic fields

Add `aliases` field to the `VersionSerializer` that's used to serialize
`Version` objects. This field is a list of versions the current version "points
to". Example `latest` version "points to" `origin/main`, and `stable` version
"points to" `v3.12`.

This is known in the code as "original stable/latest version".

Besides, this PR adds `versions.stable` and `versions.latest` fields to the
addons API which will be useful to solve front-end issues in a more generic way.

* Update test cases to match changes

* Update documentation to mention the `aliases`

* Expose generic fields (`projects.translations`, `versions.active`)

This is the pattern I want to have here, serializing the full object instead of
a few small set of fields. This is a lot more generic, simplifies the
interaction between the API and JS Addons.

Besides, it exposes the same objects as the regular APIv3 which won't change
over time.

* Optimizations

* Cache more method on `Resolver`

* Simplification of API response

* Use a shared `Resolver` instance to resolve version URLs

* ToDo comment for future optimization

* Adapt num queries from tests

* Update tests to match changes

* Update addons tests to match changes

* Update tests to not share the resolver instance

* Typo

* Add `urls.donwloads` to Project serializer

* Share a `Resolver()` between different serializers

A better way of resolving this issue will be done in
#10456

* Pass `version_slug` to be able to build URLs that point to a version

* Test updates

* Update test JSON responses for `urls.downloads` field

* Update JSON responses

* Increase `api_version` on JSON responses

* Remove old comment

We are sorting the translations in the front end

* Fix proxito dummy URLs

* Updates from review
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Improvement Minor improvement to code
Projects
Status: Planned
Development

No branches or pull requests

2 participants