Set the timeout value on BABYLON.Texture?

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.

2 Likes

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

2 Likes

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.

1 Like

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.

1 Like

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);
    };
2 Likes

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:

  1. Load external resource
  2. 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.

1 Like

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.