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

Introduce createLimitedPromises wrapper for p-limit (#326) #327

Merged
merged 6 commits into from
Feb 14, 2022

Conversation

ssciolla
Copy link
Contributor

@ssciolla ssciolla commented Feb 3, 2022

The PR aims to resolve #326.

(I'm pretty sure this does the trick, and it kinda feels like magic 🪄 .)

Resource(s):

@ssciolla ssciolla added 🐛 bug Something isn't working back end Involves changes to the Express application or other server-related files API labels Feb 3, 2022
@ssciolla ssciolla changed the title Introduce limitPromises wrapper for p-limit (#326) Introduce createLimitedPromises wrapper for p-limit (#326) Feb 3, 2022
@pushyamig
Copy link
Contributor

I will review this some time in late afternoon.

@pushyamig
Copy link
Contributor

pushyamig commented Feb 4, 2022

I did some testing with 400 user enrolling 4 times and in all the time i saw the success. here is the report from that. I might do testing on Monday.
Screen Shot 2022-02-04 at 4 17 42 PM

@pushyamig
Copy link
Contributor

I will review some more by end of day

Comment on lines 87 to 89
const coursesApiPromises = createLimitedPromises<CanvasCourse[] | APIErrorData>(
accountIds.map(a => async () => await this.getAccountCourses(a, queryParams))
)
Copy link
Contributor Author

@ssciolla ssciolla Feb 9, 2022

Choose a reason for hiding this comment

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

We probably don't have to limit here, since we're just making one (albeit potentially rather large paginated request) for each parent account the user has. It can't be that many, even if they're a sub account admin in several accounts. Especially if we're at 20 for a limit, this won't make much of a difference.

Copy link
Contributor

Choose a reason for hiding this comment

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

Good thinking on wrapping the concurrency code to Getting courses from an account, I was bit worried if user search by course name Bio then it might fetch lot of courses and will end up with rate limiting errors, this should take care it

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Just to clarify, this is limiting the number of promises for calls of this.getAccountCourses, so if there were three accounts that someone was a sub-account admin for, that would be three promises. The @kth/canvas-api library is doing the paging, so that may actually involve multiple calls behind the scenes (probably in sequence?), but for us it's just one promise. Does that make sense? That's why I was saying it was minimal improvement here.

Copy link
Contributor

Choose a reason for hiding this comment

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

Got it.

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 elected to remove the limiting here. I think it's highly unlikely that anyone would be an admin in >20 sub-accounts. We can reassess if we ever see an edge case scenario.

Copy link
Contributor

Choose a reason for hiding this comment

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

I agree

Comment on lines +149 to +156
const apiPromises = createLimitedPromises<CanvasCourseSectionBase | APIErrorData>(
sectionIds.map(si => async () => {
const sectionHandler = new SectionApiHandler(requestor, si)
return await sectionHandler.unmergeSection()
})
)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

Why unmerge has to be wrapped with the concurrency call? since we mostly ever going to do 1 section unmerge at a time

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's fine, I can remove it if you want, I was just looking for feedback on which to remove it from.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Theoretically, someone could do up to 250 using the API, but not likely to ever happen.

Copy link
Contributor

Choose a reason for hiding this comment

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

Since UI doesn't support bulk unmerge and only one at a time, I believe we can remove it

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So you're not worried about direct API calls? This is the DTO for both merge and unmerge: https://github.com/tl-its-umich-edu/canvas-course-manager-next/blob/main/ccm_web/server/src/api/dtos/api.section.ids.dto.ts

Copy link
Contributor

Choose a reason for hiding this comment

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

Let me check on it one more time and get back to you.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ok I checked again, even though this is list sectionIds.map but that list will always have 1 section for unmerge section. So the wrapper for p-limit strictly it is not needed since we are queuing one call. But I will leave this up to you

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'm gonna leave it. My thinking is that the backend logic should reflect what we support in the API, since either the frontend could change, or we may want to use the API directly in some strange customer support scenario. In all other cases where we could have >20 calls, we're using this, so it makes sense to be consistent.

Comment on lines +26 to +30
limit: 3,
methods: ['POST', 'GET', 'PUT', 'DELETE'],
statusCodes: got.defaults.options.retry.statusCodes.concat([403]),
calculateDelay: ({ attemptCount, retryOptions, error, computedValue }) => {
const delay = computedValue === 0 ? 0 : 5000
const delay = computedValue === 0 ? 0 : 2000
Copy link
Contributor Author

@ssciolla ssciolla Feb 9, 2022

Choose a reason for hiding this comment

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

I just did this. My thinking is that we initially set these so high as a way to back off from the rate limit, and get all the requests through, but that shouldn't be necessary anymore. We still want retrying behavior for intermittent Canvas errors and such, but lower levels like this should be sufficient.

@ssciolla ssciolla marked this pull request as ready for review February 9, 2022 22:00
@ssciolla
Copy link
Contributor Author

ssciolla commented Feb 9, 2022

@pushyamig and @lsloan, I think this is ready for review. Please let me know if any of the cases where I introduced limiting you think it should be removed (fine doing that, just want your input; I weighed in on the cases where it seemed less useful).

@pushyamig
Copy link
Contributor

The change seems to be straight forward but affects most features. I did some preliminary testing and review, things looks good! I will go one more round tomorrow and will approve.

@pushyamig
Copy link
Contributor

Over all this is a positive change and huge performance improvement and increase customer satisfaction rate. This also means that for Add Non-UM user we could support more that 200 (based on testing).

I have my testing report across features

This is a go from me, I think just need to resolve some merge conflicts and probably remove the concurrency call with un merge sections

Copy link
Contributor

@pushyamig pushyamig left a comment

Choose a reason for hiding this comment

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

Nice Work @ssciolla

@ssciolla
Copy link
Contributor Author

@pushyamig, thanks for the thorough review!

@ssciolla ssciolla merged commit 3b9ca83 into tl-its-umich-edu:main Feb 14, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
API back end Involves changes to the Express application or other server-related files 🐛 bug Something isn't working
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support upload of 400 users for Add UM user
2 participants