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

Bacpop-163 Error handle + delete sample #60

Merged
merged 17 commits into from
Mar 25, 2024

Conversation

absternator
Copy link
Contributor

This PR contains error handling with the projectStore and also functionality to delete sample files. Elobarted more in detail below:

  1. Basic error handling in project page. This is mostly toast messages in the projectStore.ts
  2. Abiloty to remove file samples from un run projects. Added an endpoint in API and also UI to accompany this.
  3. Unit testing

For testing its best to test the removal of file samples when project is not run. Refresh and ensure that it is persisted.

Copy link

codecov bot commented Mar 18, 2024

Codecov Report

Attention: Patch coverage is 94.44444% with 3 lines in your changes are missing coverage. Please review.

Project coverage is 98.61%. Comparing base (98174eb) to head (c907cdd).
Report is 1 commits behind head on bacpop-148-ui-rewrite.

Files Patch % Lines
app/client-v2/src/stores/projectStore.ts 89.28% 3 Missing ⚠️
Additional details and impacted files
@@                    Coverage Diff                    @@
##           bacpop-148-ui-rewrite      #60      +/-   ##
=========================================================
- Coverage                  98.80%   98.61%   -0.20%     
=========================================================
  Files                         23       24       +1     
  Lines                       1337     1367      +30     
  Branches                     157      162       +5     
=========================================================
+ Hits                        1321     1348      +27     
- Misses                        16       19       +3     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Collaborator

@EmmaLRussell EmmaLRussell left a comment

Choose a reason for hiding this comment

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

Branches are easier to review when they focus on a single bit of functionality so I think it would be have been nicer to keep these two things separate. Or explain why they need to go together. It sometimes seems easier to roll stuff together, but you're also potentially holding up unrelated functionality from being merged if the other bit needs changing...

I don't think toast is sufficient for error reporting. It's too ephemeral, The user needs to see and potentially report to us what the error was, and toast is too easy to miss. I know you're logging to the console, but most users aren't going to be looking there.

Also, by separation of concerns, the store should not have any knowledge of how errors are displayed by the UI, so showErrorToast should move out of projectStore (and not make any reference to toast!). Really errors should become store values and the components should display those.

Could potentially make errors some dictionary in the store, and could have an Error component which takes a dictionary key as a prop (e.g. deleteUploadedFileError) it would display that error from the store if present, and also give user to option to dismiss the error.

(Or maybe could stick with toast if you make it effectively live long enough that it's permanent until the user dismisses it. But then you have the danger of toast proliferation, and that's not really how toast is supposed to be used...)

I notice that you're not including any raw error details in the errors shown on screen. I guess the idea is that these are probably too gross to show a user, but I think it can be really useful for us to debug if user can report those to us, without us having to go round the loop of getting them to run it up again and check the console.. Could potentially go under a 'Details' link as a compromise.

(Unrelated rant: Not your fault, but I really don't like having tests in the __tests__ folder as a reviewer, as it means when you're scrolling through changes you hit the tests before you see (and understand) the src that they're testing. I know it's the standard scaffolding, but I'm not a fan! 😆 I suppose we could change it but it's probably not worth it. I guess the TDD mob would say it's better to see the tests first anyway... What do you think?)

Comment on lines +8 to +10
vitest.mock("primevue/usetoast", () => ({
useToast: vitest.fn()
}));
Copy link
Collaborator

Choose a reason for hiding this comment

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

It won't save that many lines of code, but since this crops up loads of times, could make a little mockToast util. However, see above - I don't actually think toast is the way to go.

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 just tried this and spent time getting it to work but has issues.. so I have left as is

@@ -83,6 +93,10 @@ export const useProjectStore = defineStore("project", {
worker.onmessage = async (event: MessageEvent<WorkerResponse>) => {
this.handleWorkerResponse(file.name, event);
};
worker.onerror = (error) => {
console.error(error);
this.showErrorToast("Ensure uploaded sample file is correct or try again later.");
Copy link
Collaborator

Choose a reason for hiding this comment

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

Trying again later isn't going to make any difference if it's a front end processing error rather than an upload error. I feel like it should be a different message for these two scenarios.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

have removed the try again for this one

@@ -136,6 +153,7 @@ export const useProjectStore = defineStore("project", {
stopPolling = true;
}
} catch (error) {
this.showErrorToast("Error fetching analysis status. Try again later, or create a new project.");
Copy link
Collaborator

Choose a reason for hiding this comment

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

Not sure what "Try again later" would mean in this context, as the user doesn't invoke status fetch themselves.

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 thought if issues with server down or something.. but have changed to try refresh pag instead

Comment on lines +207 to +208
this.project.status = { assign: "submitted", microreact: "submitted", network: "submitted" };
this.pollAnalysisStatus();
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why is this new code? Has it moved from somewhere else?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

nope just shifted up a bit into try catch block

Comment on lines 27 to 29
app.post(`/project/:projectId/sample/:sampleHash/delete`,
authCheck,
controller.deleteSample);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should be a DELETE?

Copy link
Contributor Author

@absternator absternator Mar 20, 2024

Choose a reason for hiding this comment

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

initially i thought that too but we are deleting part of resource and also as comment below changed to patch and can pass in filename in body

@@ -15,7 +15,7 @@ const tableIsHovered = ref(false);
<Button label="Run Analysis" outlined @click="store.runAnalysis" :disabled="!store.isReadyToRun" />
</div>
</template>
<template #content>
<template #empty>
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why this change?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

realised it shows error message if file uploaded is wrong (wrong extension, too big etc)

@@ -98,6 +98,12 @@ export class UserStore {
const amrString = await this._redis.hget(this._projectSampleKey(projectId, sampleId), "amr");
return JSON.parse(amrString);
}
async deleteSample(projectId: string, sampleHash: string) {
const sampleIds = await this._redis.smembers(this._projectSamplesKey(projectId));
const sampleId = sampleIds?.find((id) => id.startsWith(sampleHash));
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't think this quite works. In theory someone might have uploaded the same sample data twice with two different filenames (could happen!) - if they select the second one to delete, it shouldn't delete the first one, which I think is what would happen here. So I think the delete endpoint is going to have to take the filename as well as the sample hash unfortunately.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

reeeeally weird why someone would do that but updated as requested

@absternator
Copy link
Contributor Author

Branches are easier to review when they focus on a single bit of functionality so I think it would be have been nicer to keep these two things separate. Or explain why they need to go together. It sometimes seems easier to roll stuff together, but you're also potentially holding up unrelated functionality from being merged if the other bit needs changing...

I don't think toast is sufficient for error reporting. It's too ephemeral, The user needs to see and potentially report to us what the error was, and toast is too easy to miss. I know you're logging to the console, but most users aren't going to be looking there.

Also, by separation of concerns, the store should not have any knowledge of how errors are displayed by the UI, so showErrorToast should move out of projectStore (and not make any reference to toast!). Really errors should become store values and the components should display those.

Could potentially make errors some dictionary in the store, and could have an Error component which takes a dictionary key as a prop (e.g. deleteUploadedFileError) it would display that error from the store if present, and also give user to option to dismiss the error.

(Or maybe could stick with toast if you make it effectively live long enough that it's permanent until the user dismisses it. But then you have the danger of toast proliferation, and that's not really how toast is supposed to be used...)

I notice that you're not including any raw error details in the errors shown on screen. I guess the idea is that these are probably too gross to show a user, but I think it can be really useful for us to debug if user can report those to us, without us having to go round the loop of getting them to run it up again and check the console.. Could potentially go under a 'Details' link as a compromise.

(Unrelated rant: Not your fault, but I really don't like having tests in the __tests__ folder as a reviewer, as it means when you're scrolling through changes you hit the tests before you see (and understand) the src that they're testing. I know it's the standard scaffolding, but I'm not a fan! 😆 I suppose we could change it but it's probably not worth it. I guess the TDD mob would say it's better to see the tests first anyway... What do you think?)

  1. I have moved toast to comparable. I have also increased toast TTL to 5seconds so sufficient for user

  2. I agree about minimal error and toast but the problem Is we don't have sufficient error messages and most are not useful to the user. Also this is just simple error handling as part of New U, I will create a ticket for updating error states and a more robust one that will include both server/client errors.
    But other errors could ephemeral (random server error or internet issue).... Also toast makes sense as most of them will occur for a long running process...

  3. I think its only necessary to surface the basics.. And yes if they do need help we will look their client error and server logs.

  4. tests for reviewing you can collapse the file if you want haha.. But I'm easy with the layout i don't think it matters much

Base automatically changed from bacpop-161-microreact to bacpop-160-network-tab March 20, 2024 11:44
Base automatically changed from bacpop-160-network-tab to bacpop-148-ui-rewrite March 20, 2024 14:57
@@ -136,6 +144,7 @@ export const useProjectStore = defineStore("project", {
stopPolling = true;
}
} catch (error) {
this.toast.showErrorToast("Error fetching analysis status. Try refresh page, or create a new project.");
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
this.toast.showErrorToast("Error fetching analysis status. Try refresh page, or create a new project.");
this.toast.showErrorToast("Error fetching analysis status. Try refreshing the page, or create a new project.");

Copy link
Collaborator

@EmmaLRussell EmmaLRussell left a comment

Choose a reason for hiding this comment

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

Looks good. Tiny suggeston, up to you if you want to do this.

@@ -24,7 +24,7 @@ export default {
app.post('/project/:projectId/rename',
authCheck,
controller.renameProject);
app.post(`/project/:projectId/sample/:sampleHash/delete`,
app.patch(`/project/:projectId/sample/:sampleHash`,
Copy link
Collaborator

@EmmaLRussell EmmaLRussell Mar 25, 2024

Choose a reason for hiding this comment

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

I wonder if we should still have the delete route, since the fact that it's going to delete a hash/filename combo isn't obvious from the fact that it's a patch..?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

couldnt add body (need to pass file name). left as PATCH but added /delete back in to end

@absternator absternator merged commit 3b516b7 into bacpop-148-ui-rewrite Mar 25, 2024
5 of 6 checks passed
@absternator absternator deleted the bacpop-163-error-handling branch March 25, 2024 13:58
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