If I have a lot (514+ in Edge, 616+ in Chrome) of Service classes, the browser will show a console error “Uncaught RangeError: Maximum call stack size exceeded” when rendering the Auto UI forms on the /ui routes generated for us.
When this happens, the browser no longer responds as it should (probably rightly so) and so things like authenticating if the route required authentication no longer work.
I’ve made a little repro project and published it on Github : https://github.com/JiwaFinancials/DEV-9177.
(Sorry about the name, DEV-9177 - that’s our company internal tracking number for this issue).
I’m going to split our services into microservices to partition various areas of concern in our API which should allow us to get past this issue, but I thought I’d raise it here in case it was something that could be addressed more simply.
This metadata .js payload is 469KB which the browsers are saying exceeds the the allowable size in a function call.
There’s potential mitigations we can do like using shorter property names or splitting the metadata into multiple chunks, e.g. different APIs to retrieve Types + APIs which wont solve the upper limit but will buy you some space to fit more APIs, but that would break the API contract ServiceStack Studio is relying on so it could only occur after we implement everything from ServiceStack Studio and retire the App.
But yeah in the meantime you should split related APIs in Micro Services to reduce the API count of each.
I’ve done some pruning to remove false properties and empty collections in this commit, this should get your example down from 469KB to ~365KB so something like a 22% savings.
That’s the most we’ll be able to do before retiring Studio so we can break the schema by using shorter names or consolidating props.
This change is now available from the latest v6.0.3 that’s now available on MyGet
When splitting into microservices, as you can’t have multiple AppHosts in the same process I’m assuming I would need to have a separate process for each microservice.
The impact for us and our customers of that would be fairly significant - so I might look at a different approach and see if I can limit the metadata based on subdomain - so I’m thinking something like:
customers.example.com is a configured DNS name which points to the same location as orders.example.com.
Service classes are decorated with an attribute indicating which subdomain they belong to.
The metadata exposed will filter based on the subdomain of the request matching the attribute of the classes. So https://customers.example.com/metadata will only get the metadata for service classes and related responses and requests which have been decorated with that attribute.
It could work if you use AddToAppMetadata(meta => ...) to remove Operations & Types from the returned metadata. You’ll need to be careful not to remove types that are needed in which case I recommend grouping APIs + Types with Tag Groups which your filter inspects to removes all operations/types not in that tag group, so if you run into issues with missing types you can include the Type in that Tag group.
So, thanks to your guidance, I’ve successfully used the AddToAppMetadata to reduce the operations shown in the /ui routes to be only ones where the associated request classes have a Tag attribute matching the subdomain.
However, I’m now trying to make the /metadata page behave consistently and also limit what Operations are shown there based on the current subdomain and the request class associated with operation.
I’ve seen how I can override the default template IndexOperations.html with my own - I can’t see how I can use that to selectively limit the operations shown - I think whatever is using that template needs to be responsible for curating the list of operations - any suggestions on how I achieve this?