-
Notifications
You must be signed in to change notification settings - Fork 119
[MBL-19666][S] Eliminate redundant calls to GetContextTabs and GetCourse APIs when viewing New Quiz details screen
#3858
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
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Review Summary
This PR refactors how GetContextTabs handles pagination by moving the exhaust logic from call sites into the use case itself via a custom makeRequest override. While this simplifies call sites, there are several concerns about this approach.
Architecture & Pattern Consistency
Positive:
- Simplifies call sites - callers no longer need to know about pagination details
- Reduces code duplication across multiple files
- Makes the exhaustive pagination behavior more centralized
Concerns:
-
Breaking Pattern Consistency (GetContextTabs.swift:43-48): The override of
makeRequestto useapi.exhaustbreaks the standard UseCase pattern. All otherCollectionUseCaseimplementations use the defaultapi.makeRequest. This inconsistency makes the codebase harder to reason about. -
Loss of Caller Control: Previously, callers could choose between
refresh()(single page) andexhaust()(all pages) based on their needs. Now all callers are forced to exhaust all pages, even when they may only need the first page. -
Async Timing Change (CourseDetailsViewModel.swift:265-269): The continuation now resumes after the first page callback, not after all pages are exhausted. This changes when
await refresh()returns and could cause race conditions.
Potential Bugs
-
Race Condition (CourseDetailsViewModel.swift:192): The
updateTabs()method checks!tabs.hasNextPageto ensure all tabs are loaded. With the new pattern, the first refresh callback fires before pagination completes, sohasNextPagemay still be true, preventing the UI from updating properly. -
Unrelated Change (StudentAssignmentDetailsPresenter.swift:272): Removes
force: truefrom courses refresh. This appears unrelated to the tabs pagination changes. Was this intentional?
Performance Considerations
- Always Exhausting on View Appear (CourseDetailsViewModel.swift:106): Every
viewDidAppear()now triggers exhausting all tab pages (when cache is expired). While the cache mitigates this, it's less visible that this potentially expensive operation happens on every view appearance.
Testing
The existing tests in CourseDetailsViewModelTests mock single-page responses. Consider adding tests that verify multi-page tab responses are handled correctly with the new pattern.
Recommendations
-
Consider Alternative Approach: Instead of overriding
makeRequest, consider adding a property onGetContextTabslikeshouldExhaustPages: Bool = truethat the Store checks, keeping the behavior explicit. -
Fix Async Timing: If exhausting is truly required, the async continuation should wait until all pages complete, not just the first page.
-
Document Behavior: Add inline documentation explaining why
GetContextTabsalways exhausts pages and how this differs from other use cases. -
Verify Unrelated Change: Confirm whether the
courses.refresh()change inStudentAssignmentDetailsPresenterwas intentional.
Code Quality
The code follows Swift and SwiftLint conventions. No security concerns identified. The refactoring is well-structured, but the architectural implications need consideration before merging.
Core/Core/Features/Courses/CourseDetails/ViewModel/CourseDetailsViewModel.swift
Show resolved
Hide resolved
Core/Core/Features/Courses/CourseDetails/ViewModel/CourseDetailsViewModel.swift
Show resolved
Hide resolved
Student/Student/Assignments/AssignmentDetails/StudentAssignmentDetailsPresenter.swift
Show resolved
Hide resolved
BuildsCommit: Fix unit tests (cf6c682) |
refs: MBL-19666 affects: Student builds: Student release note: None.
vargaat
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
causing the call to load all the tabs and banner resources every time a user clicks a next question.
The original ticket mentions that these calls are made each time the user goes to the next question. Did you test that scenario as well? How requesting the next question in a webview triggers a native reload?
Yes, I have tested that, and found no trace of multiple calls when users tap "next question". Moreover, if go back a bit with the analysis they've given, they said:
So, there hasn't been an actual proof that the Mobile is doing so. It seemed like a speculation to me. |
|
@vargaat Here is my full comment about it: |
|
@suhaibabsi-inst Awesome, thanks for the clarification. |
refs: MBL-19666
affects: Student
builds: Student
release note: None.
Analysis
While it turned out this issue is resolvable by removing force refreshing for course in
StudentAssignmentDetailsPresenter.viewIsReady()method:https://github.com/instructure/canvas-ios/pull/3858/changes#diff-d0da11be14d5d7b553db6be2ac15259f85632f0bee5e141560abb9f33bc87d3dR272
Tracking the origin of this change, I came across the original PR where force refreshing was introduced. Apparently it came out as a necessity as the original
Presenterwas contributing to "SubmitAssignment" share extension functions. Currently, it no longer contributes to those, hence we can have it reverted.Other changes:
In order to make the call for context tabs more efficient, following changes were made:
makeRequest()method onGetContextTabsthat doapi.exhaust(..)rather thanapi.request(..).CourseDetailsViewModelby removing custom exhaust logic.CourseNavigationPresenter,GroupNavigationViewController, andStudentAssignmentDetailsPresenterto use the simplified API.Test Plan
For more information, see ticket's description.
Checklist