Is there a way to control how long a call to new BABYLON.Texture()
waits before calling the error function and timing out? We’d like it to fail faster.
I think you are asking if you pass an invalid url to the texture constructor, can we control the url request’s timeout. Currently, no. We don’t have a way to control the timeout of the request. It should be too difficult to add a global control for this. Would that suit your needs?
EDIT: On second look, it looks like the timeout defaults to 0 which means there is no timeout, so it’s probably not that. Maybe you are seeing the retry strategy which defaults to an exponential backoff with 3 retries and 500ms base interval. You can modify this behavior by updating BABYLON.Tools.DefaultRetryStrategy and updating it with your custom retry strategy that fails faster.
The scenario is slightly different here. It’s not that the url is a genuine 404 response, it’s that there’s a load balancer in the middle that is sometimes throttling the response, in which case the texture doesn’t retry (we’re already doing a custom retry strategy that skips retries completely) but instead, it just hangs there until the caller of the update times out. This can hang for as long as 90-120 seconds, unfortunately, so we’d like to set up a short circuit to free up the application to make a different request.
Hmmm one possibility could be loading the image data yourself then passing it to the Texture instead of the URL, as Texture can accept data urls too.
These are KTX files. Do you have an example of how to do this?
Let me see if I can make one
It sounds like this might be a browser/server behavior. We use XMLHttpRequest to load URLs. We don’t do anything special to do any load balancing that I’m aware of.
It’s definitely due to a load balancer on our end. What’s apparently happening is that the ALB that fronts our KTX source is throttling requests. When this happens, instead of returning a 404 it just hangs. What we need is to use something like Axios to control the timeout for these requests so that if it takes longer than X seconds, we just cancel the request and move on. I tried using something like Promise.race
but this seemed to cause issues since eventually the textures still return (the requests aren’t actually canceled) so this just causes weird race conditions.
Then maybe the timeout setting for XHR will help? By default, this value is 0 which doesn’t timeout. If we set this to something small, it should abort the request if it takes too long.
One wrinkle is that we’re currently version-locked with BJS, so Carol’s approach above would be ideal for now…
Our XHR is wrapped in a class BABYLON.WebRequest
. You should be able to override the prototype to set the timeout.
Would you mind showing me an example of what you mean there?
Something like this:
var openFunc = BABYLON.WebRequest.prototype.open;
BABYLON.WebRequest.prototype.open = function (method, url) {
this.timeout = 200;
openFunc.call(this, method, url);
};
Ok, that worked! However, it now falls back to the PNG
version which uses fileTools.ts
Is there a way to completely skip the fallback behavior so it fails as soon as the KTX
file fails?
I think this is the way we need to go, since this will give us more observability going forward. I haven’t been able to get this to work, though, because Chrome seems to block these Blob urls.
axios
.get(originalFileUrl, {
responseType: 'arraybuffer',
})
.then(response => {
const textureBlob = new Blob([response.data]);
const textureUrl = URL.createObjectURL(textureBlob);
let tex = {};
tex = new Texture(
textureUrl,
scene,
true, // no mipmaps
true, // flip Y
Texture.TRILINEAR_SAMPLINGMODE, // Sampling mode
() => {
// Success callback
callback(tex);
},
error => {
// Error callback
debugger;
const err = new Error(
`An error occurred while loading ${texturePathFile}.`,
);
logger.simpleError('Texture Loading', err);
errorHandler?.(err);
},
null,
true, // Delete the buffer after load
undefined,
);
});
I think you are talking about this? EngineStore | Babylon.js Documentation
Yes, I can try that. I’m still hoping to maybe load this via Axios so I can break up the flow into:
- Load external resource
- Apply resource to texture object
So we can isolate this bottleneck. Right now it’s tough to determine because it’s swallowed up in Babylon internals.
@carolhmj is working on giving you an example.
Thank you! As an aside, this might be broken?
EngineStore.UseFallbackTexture = false;
EngineStore.FallbackTexture = '';
const openFunc = WebRequest.prototype.open;
WebRequest.prototype.open = function(method, url) {
(this as any).timeout = 2;
openFunc.call(this, method, url);
};
I still see fallback attempts for the PNG versions.