-
Notifications
You must be signed in to change notification settings - Fork 889
fix: update template with noop returned undefined template #11688
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
Conversation
Create a template, remove everyone group, see if owner can read
The patch response did not include the template. The UI required the template to be returned to form the new page path
// Create a template, remove the group, see if an owner can | ||
// still fetch the template. | ||
t.Run("GetOnEveryoneRemove", func(t *testing.T) { |
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.
Probably worth keeping, it was the original report.
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.
I think the client-side fix makes sense – just had one suggestion for a possible improvement.
I don't think I should be trusted with the Go stuff, though. I hate to delegate that part, but I'm still getting up to speed on the language, and am a little worried that some nuances might be lost on me
// This update has a chance to return a 304 which means nothing was updated. | ||
// In this case, the return payload will be empty and we should use the | ||
// original template data. | ||
if (!data) { | ||
data = template; | ||
} |
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.
I think this change works for our purposes here. I guess there's just two other things that come to mind:
-
At the end of the day, we do need an
undefined
check, but right now, there's nothing surfacing that the data could be undefined at the type level.My worry is that someone will see that we're doing a check for something that appears non-nullable, and not be sure whether the comment still applies. Could you also add an
undefined
union forupdateTemplateMeta
?I know that we're using this API call in two other files, though, so there might be some edge cases with changing it everywhere.
onSuccess
'sdata
argument could also be broadened to includeundefined
as a bandaid solution
export const updateTemplateMeta = async (
templateId: string,
data: TypesGen.UpdateTemplateMeta,
): Promise<TypesGen.Template | undefined> => {
const response = await axios.patch<TypesGen.Template | undefined>(
`/api/v2/templates/${templateId}`,
data,
);
return response.data;
};
- I haven't dived too deeply into our settings stuff, but my gut feeling is that we don't necessarily need to invalidate the queries and go through a refetch if no data has changed. I wonder if something like this might be good:
onSuccess: async (data) => {
if (!data) {
data = template;
} else {
await queryClient.invalidateQueries(
templateByNameKey(orgId, data.name),
);
}
}
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.
This is all good info and I will make these changes. Other places call this, but have to handle the undefined too.
I did attempt to solve this in the backend, but I could not. Golang does not allow writing a body for some status codes: https://github.com/golang/go/blob/master/src/net/http/server.go#L1569-L1574 |
onSuccess: async (data) => { | ||
// This update has a chance to return a 304 which means nothing was updated. | ||
// In this case, the return payload will be empty and we should use the | ||
// original template data. | ||
if (!data) { | ||
data = template; | ||
} | ||
|
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.
This is the fix.
// This update has a chance to return a 304 which means nothing was updated. | ||
// In this case, the return payload will be empty and we should use the | ||
// original template data. | ||
if (!data) { | ||
data = template; | ||
} |
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.
This is all good info and I will make these changes. Other places call this, but have to handle the undefined too.
site/src/api/api.ts
Outdated
): Promise<TypesGen.Template> => { | ||
const response = await axios.patch<TypesGen.Template>( | ||
): Promise<TypesGen.Template | undefined> => { | ||
const response = await axios.patch<TypesGen.Template | undefined>( |
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.
Oh wait, I just realized something – I'm worried the logic isn't quite right. undefined
isn't a valid JSON-serializable value (though null
is), so it shouldn't be able to make it across the API boundary in the first place
Is the condition we should actually be checking for whether data.name
is the string literal "undefined"
? Even in the bug issue, the previous code wasn't breaking when it was trying to access the name
property during the navigation – it was just being fed an incorrect value. That's making me think that technically, data
and its properties would always be defined – it's just that we're simulating "undefined-ness" by setting name
to "undefined"
in certain situations
This is definitely out of scope for the PR, and I haven't explored our type generation logic, so I don't know how complicated this would be, but there is a trick we can use to add the literal "undefined"
to autocomplete without narrowing the overall type unnecessarily:
interface Template {
readonly name: "undefined" | (string | {}); // (string | NonNullable<unknown>) also works
}
With that, "undefined" would show up during autocomplete, but the overall type would still be string
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.
The response is a completely empty payload, 0 bytes.
You are saying that is null
and not undefined
?
null is more explicit, and harder to make occur by mistake.
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.
👍
Fixes #11186
When the UI submits an update to a template, and there has been no change, the response is a 304 (Not modified) with an empty payload. The UI expected a response, and returned
/undefined
as the template name.The unit test added was just testing the reported case, which turned out not to be an issue.