-
-
Notifications
You must be signed in to change notification settings - Fork 212
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 954 #956
base: main
Are you sure you want to change the base?
Fix 954 #956
Conversation
I will add few more tests tomorrow |
Thank you for creating this PR. There is a problem. The current implementations ensure consistency. The same dataset will always return the same result, regardless of whether the promises take different amounts of time. But if we abort after the first input validation with an issue, the order may be random. Of course, we could choose performance over consistency in this case, but it would be a breaking change. Your implementation has added a lot of extra code. Let us try to keep it to a minimum. Here is a quick idea I had in mind. Feel free to experiment with it and share your thoughts. const valueDatasets = await Promise.all(
let shouldAbort = false;
const valueDatasets = await Promise.all(
Object.entries(this.entries).map(async ([key, schema]) => {
if (!shouldAbort) {
const value = input[key as keyof typeof input];
const valueDataset = await schema['~run']({ value }, config);
if (config.abortEarly && valueDataset.issues) {
shouldAbort = true;
}
return [key, value, valueDataset] as const;
}
})
); |
This will not work because, once launched, a promise can’t be aborted from the outside. If there are many This can be mitigated by wrapping the But I doubt this will significantly reduce the amount of code…
As with any side-effect check combined with I don’t think this is a breaking change. But even if you think it is, the library is still in its zero version, so it’s not a big deal, in my opinion. |
That may be true, but we can still somehow change what the promise actually does, and e.g. not execute the actual expensive logic, or am I wrong? If I understand your current code correctly it executes the promises in sequential order and I am not sure if this is an option.
I agree, and am willing to investigate this case and favor performance if we find a good and uniform solution that works for any async schema. |
No, a promise is like a black box. Once launched, you can only wait for it to resolve (or reject). Or ignore it. Or maybe I just don’t understand what you’re pointing out 🤔
No, the idea was that I collect promises in an array but do not await them. Later, using But after I added a few tests, I found a critical issue in my approach: after removing a promise from the array, the indexes of the remaining promises became misaligned. So, I rewrote the PoC without using Also, I added logic so that if I encounter synchronous issues while executing validations, it stops right there and doesn’t launch the async validation at all (if it is located below the synchronous one). As for the rest, what I want to try is to add the possibility to abort running promises by passing an AbortController.signal to each one of them. This way, the user can hook into this signal to abort an HTTP request, for example, if validation fails on another field. |
Look at this simple example. Thank you for your research! I really appreciate your efforts and hope we can improve the current implementation. I don't have much time at the moment, but I will try to have a closer look at the end of December or in January. Feel free to share any research you do here, as well as alternative implementations if you find any. I can also share this PR on social media to get additional feedback and ideas from others. |
Yeah, this is almost the same as what I’m doing here — if the validation result is data (not a promise-like object) and has issues, it stops the iteration right there and doesn’t even launch the following promises (already launched ones will be ignored). And yes, this will fail a test with two asynchronous operations of different durations.
Sure, why not 👍 |
I was thinking about how I could add an I'm raising this in the following context: if you add an Maybe I'm shooting from the hip here, as the library's API has been extensively discussed, and it seems no one is concerned about this issue — I haven't found any related discussions or issues. I also haven't found any reasoning behind this design decision. |
On the other hand, maybe this is not a problem in my proposal, because after validation abortion all pending promises results are ignored anyways 🤔 I will investigate this. But I'm still curious about question above in general. |
So far, we expect users to catch errors and return true or false. This makes our code consistent throughout the library. We could add a try/catch block to |
PoC to fix #954