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

Fix error handling for getColumn when table does not exist #57883

Merged
merged 1 commit into from Apr 9, 2024

Conversation

cnbrenci
Copy link
Contributor

@cnbrenci cnbrenci commented Apr 8, 2024

There was a recent regression in getColumn where there's an uncaught exception when the table does not exist, which results in the student's program halting execution, and no error appearing that points to the problem line in their code. This makes it difficult for students to diagnose the issue if they forget to import the table they're referencing, and is a common occurrence with remixing projects since data tables do not get copied over into the remixed project (by design, but it's still a common gotcha).

I think we should get this in ASAP to mitigate the impact that the regression is causing AP CSP students. I've scoped it down as much as possible to avoid any side-effects, and added test coverage for the code path.

Warning!!

The AP CSP Create Performance Task is in progress. The most critical dates are from April 3 - April 30, 2024. Please consider any risk introduced by this PR that could affect our students taking AP CSP. Code.org students taking AP CSP primarily use App Lab for their Create Task, however a small percent use Game Lab. Carefully consider whether your change has any risk of alterering, changing, or breaking anything in these two labs. Even small changes, such as a different button color, are considered significant during this time period. Reach out to the Student Learning team or Curriculum team for more details.

Links

We've seen a few zendesk tickets lately where users were complaining about their OnEvent callbacks not working, where the culprit seemed to be that they had a getColumn call stopping execution of the script.

slack discussions with links

Testing story

I added some test coverage that was previously missing and would have caught this regression, and tested the success case and error cases for nonexistent table and nonexistent column.

PR Checklist:

  • Tests provide adequate coverage
  • Privacy and Security impacts have been assessed
  • Code is well-commented
  • New features are translatable or updates will not break translations
  • Relevant documentation has been added or updated
  • User impact is well-understood and desirable
  • Pull Request is labeled appropriately
  • Follow-up work items (including potential tech debt) are tracked and linked

@cnbrenci cnbrenci marked this pull request as ready for review April 9, 2024 00:32
records.forEach(row => columnValues.push(row[columnName]));
onSuccess(columnValues);
if (records === null) {
onSuccess(null);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

null check here avoids exception on null.forEach and passes null back to handleGetColumn here: https://github.com/code-dot-org/code-dot-org/blob/cassi/applab-getcol-onfailure-fix/apps/src/applab/commands.js#L1877-L1878

@cnbrenci cnbrenci requested review from snickell, jmkulwik and a team April 9, 2024 00:52
Comment on lines +1247 to +1248
let columnValues = [];
records.forEach(row => columnValues.push(row[columnName]));
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 this can just be a map.

const columnValues = records.map(row => row[columnName])

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh, also just as another note in case anyone looks to this code again...

even if it's not switched to the map, it should still be const columnValues = []. It doesn't need to be a let.

const only prevents you from re-assigning the variable itself (e.g., columnValues = 'foo' later on wouldn't be allowed), but you can still manipulate the object itself. JavaScript is weird. 🤷

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 really appreciate this comment and will keep it in mind going forward. Because this is in the critical path for the AP CSP Create task though, I want to keep the change as scoped as possible and only touch the "records is null" fork of the code path. So I'll leave it as is for this PR. I would follow-up and change it after Create task next month, but since this file will be deleted in a couple months anyway, I'm going to skip the overhead. BUT I will remember this fact about const, and how much cleaner map is than the forEach push song and dance! Thank you!!

Comment on lines +1178 to +1181
'id,name,age,male\n' +
'4,alice,7,false\n' +
'5,bob,8,true\n' +
'6,charlie,9,true\n';
Copy link
Contributor

Choose a reason for hiding this comment

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

Again, just a non-mandatory suggestion, but string concatenation and especially with embedded newlines is a little twitchy and easy to have errors (e.g., by forgetting the newline).

I'd suggest a set of lists and a join on "\n"

const csvData = [
  'id,name,age,male',
  '4,alice,7,false',
  '5,bob,8,true',
  '6,charlie,9,true'].join("\n");

Reads a little cleaner to me. We could also take this to an extra level and join the subarrays on commas, but that feels like overkill unless we needed to be dynamic about the record delimeter.

Also, as a side note - backtick quotes do allow embedded newlines, but since this is formatted data I'd lean against using them in this case.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Noted, and there are a lot of things I could clean up in this file but am avoiding that rabbit hole since this code will be going away with the rest of firebase. Thank you!!

Copy link
Contributor

@thomasoniii thomasoniii left a comment

Choose a reason for hiding this comment

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

two small suggestions about changing how things are written, but nothing required (though the map would be nice to do so we can get rid of the external mutable var)

otherwise, lgtm 🚀

@cnbrenci cnbrenci merged commit 23a7c9c into staging Apr 9, 2024
2 checks passed
@cnbrenci cnbrenci deleted the cassi/applab-getcol-onfailure-fix branch April 9, 2024 21:17
@jmkulwik
Copy link
Contributor

Nice job on the quick fix! And on the added tests too! This will be a big help to our students working on the create task!

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.

None yet

3 participants