Skip to content
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

Add pagination and search functionality to job collection API #1029

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

cuza
Copy link
Member

@cuza cuza commented Feb 4, 2025

This pull request introduces pagination and search functionality to the tron/api/resource.py module and updates the corresponding tests. These changes are efforts to enhance tronweb responsiveness by having pagination on the main dashboard. The most important changes include adding pagination parameters to the get_data method, modifying the render_GET method to handle pagination, and introducing a new render_SEARCH method to support search queries.

Enhancements to tron/api/resource.py:

  • Added page and page_size parameters to the get_data method to support pagination.
  • Modified the render_GET method to handle pagination logic, including validation and response formatting.
  • Introduced a new [WIP] render_SEARCH method to filter jobs based on a search query.
    • Search was added to address the challenge of finding specific Tron jobs when the main dashboard is paginated. Current implementation is a basic PoC to gather feedback and iterate over it

Updates to tests:

  • Updated the test_render_GET method in tests/api/resource_test.py to include new pagination parameters in the assert_call function.
  • Added a new test_render_SEARCH method to test the search functionality.

Additional imports:

  • Added the math module import in tron/api/resource.py to support pagination calculations.

@cuza cuza requested a review from a team as a code owner February 4, 2025 20:17
Copy link
Member

@nemacysts nemacysts left a comment

Choose a reason for hiding this comment

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

i'm assuming this is related to the hackathon efforts last year to come up with a new tron ui, but adding additional context into the description would be nice (in case i'm wrong or for folks that don't have that knowledge)

and sidenote: how are we envisioning the search function being used? i noticed that it's not currently being paged - is that an oversight or something for future us to handle?

return respond(request=request, response=response)

@AsyncResource.bounded
def render_SEARCH(self, request):
Copy link
Member

Choose a reason for hiding this comment

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

my understanding is that the render_* functions are named after the HTTP request method used for the request that's being handled and that that SEARCH is not standard HTTP method and that we probably want QUERY? that said, not sure if that's still a draft RFC or if it's actually part of the standard

but just to confirm: the intent is that we'll have the troncli/ui use SEARCH/QUERY verbs to hit this new function?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes your understanding is correct and I did added SEARCH as a custom http verb and it is not part of the standard, I don't even think it's part of a draft. It did't felt wrong when I was doing it but also all of this code is from a hackathon project so I was more focus on getting something built fast.

I'm more than happy to take suggestions on what endpoint we can drop the search at or we can have a discussion about if it makes sense to have the custom http verb

Copy link
Member Author

Choose a reason for hiding this comment

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

TIL: HTTP SEARCH verb is a thing

Comment on lines +375 to +386
if page < 1 or page_size < 1:
return respond(
request=request,
response={"error": "page and page_size must be positive integers"},
code=http.BAD_REQUEST,
)
if page > math.ceil(total / page_size):
return respond(
request=request,
response={"error": "page out of range"},
code=http.BAD_REQUEST,
)
Copy link
Member

Choose a reason for hiding this comment

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

might be nice to have a validate function so that we can do something like:

request_ok, request_error = self.job_collection.validate_paging_params(page, page_size)
if not request_ok:
    return respond(
        request=request
        response={"error": request_error},
        code=http.BAD_REQUEST,
    )

Comment on lines +369 to +370
page,
page_size,
Copy link
Member

Choose a reason for hiding this comment

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

we're using page/page_size here before validating them - is that intentional?

Copy link
Member Author

Choose a reason for hiding this comment

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

Great catch!!! this is a good point!!! most of the page validation happens a bit after on the code, handling exceptions here makes more sense.

Comment on lines +317 to +320
jobs = self.job_collection.get_jobs()
if page is not None and page_size is not None:
start = (page - 1) * page_size
jobs = jobs[start : start + page_size]
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
jobs = self.job_collection.get_jobs()
if page is not None and page_size is not None:
start = (page - 1) * page_size
jobs = jobs[start : start + page_size]
if page is not None and page_size is not None:
jobs = self.job_collection.get_jobs_by_page(
page,
page_size,
)
else:
jobs = self.job_collection.get_jobs()

might make testing easier (since then we can test the paging logic without testing the rest of get_data)

assert "jobs" in result

def test_render_SEARCH(self):
request = build_request(query="test")
job1 = MagicMock()
Copy link
Member

Choose a reason for hiding this comment

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

nit: we should probably set the spec on these to whatever the real type of these is so that the tests better match reality (e.g., so that the mocks fail should we ever remove get_name from the actual type, etc)

Comment on lines +387 to +389
response = dict(jobs=jobs, pagination=dict(page=page, page_size=page_size, total=total))
else:
response = dict(jobs=jobs)
Copy link
Member

Choose a reason for hiding this comment

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

imo, inlining the dicts rather than calling the dict constructor would be more modern/easier to read - that said, we have pretty mixed usage of dict/{} in this file already so not a blocker


@AsyncResource.bounded
def render_SEARCH(self, request):
query = requestargs.get_string(request, "query")
Copy link
Member

Choose a reason for hiding this comment

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

do we need to do any validation on the query data?

Copy link
Member Author

Choose a reason for hiding this comment

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

Search is currently very basic we could maybe limit the length of the string 🤷🏽 we also don't use it in a way that could lead to SQL injections

@cuza
Copy link
Member Author

cuza commented Feb 5, 2025

i'm assuming this is related to the hackathon efforts last year to come up with a new tron ui, but adding additional context into the description would be nice (in case i'm wrong or for folks that don't have that knowledge)

and sidenote: how are we envisioning the search function being used? i noticed that it's not currently being paged - is that an oversight or something for future us to handle?

All your assumptions are correct:

  • The pagination is to be able to have a more snappy/faster tron ui.
  • The search was added cuz if we paginate tronweb main dashboard it will be hard to find a tronjob
    • Search does not have pagination since I left it for future me to implement. I also was not very sure if we wanted/needed search so keep it basic as a PoC to see if I liked the idea.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants