Mostly a thread for @Accipiter, I guess, someone else might still find it helpful.
Got a couple questions after staring at the code for too long.
Does making a request not guarantee that there will be a response?
The C# code seems to drop the ResRpc on the floor if WS connection is lost. JS code doesn’t seem to clean up this.requests at any point other than receiving a response. What exactly the client does if there is a request in flight and the connection dropped? To me it looks like the callback will never be called.
How does a model or collection transition into an error and back?
When parsing the models/collections/errors there’s a strict type checking so in the JS code if some model errored it’s stored as an error in the cache. How does it unerror given the server side doesn’t seem to have any knowledge of whether the client has the error cached and the client won’t accept the legit model/collection as long as the error is in the cache?
Is that error mechanism used at all? I can’t see any reference to it in the C# code.
Excellent questions, and impressive analysis of the code
Question 1
All pending requests should instantly complete with a system.disconnect error code if the WebSocket connection is disconnected. Admittedly, neither the C# library, nor the Javascript does this! I need to fix that! Thanks for pointing it out!
But yes, a response should be guaranteed, usually within the default timeout duration of 3 seconds. However, a response may exceed this timeout duration by having the service extend it, or if the response contains nested data/resources that requires more time to fetch.
Question 2
The protocol currently does not support transitioning of resources into different types, including transitioning an error to a model/collection, or the other way around.
This is usually a non-issue, but the most common case when it can cause trouble is during service restarts. The scenario could looke like this:
Service A shuts down for restart
Client fetches collection from service B. Collection contains references to resources on service A.
Resgate fetches collection from B, but when following references to service A, it gets no response and generates notFound errors.
Resgate returns collection to client, including notFound errors.
Service A is restarted.
In the above steps, the client would end up with errored resources, and would need to reload in order to fetch them. Reload is possible since Resgate, unlike the client, does not cache errors.
As said, this has never been much of an issue; if it would become one, it could be solved by updating Resgate and the RES protocol with one additional event. But this would also add to client complexity.
Or did you see some other scenario where transitioning from errors might be needed?
By reload there-- what exactly do you mean? There’s no specific mechanism I found to purge an object from cache so any call to server that returns a non-errored response won’t update it.
It’s a bit of a theoretical issue for now, I haven’t stumbled on any errored resources yet and I couldn’t find any specific handling of those in the mucklet’s source code.
Oh!! You are perfectly right. I will update the docs!
Thanks for pointing it out!
The character ping is no keepalive for the WebSocket, but for keeping characters awake.
However, the RES protocol relies on the underlying protocols (WebSocket/TCP) to keep the connection alive.
Yeah no, can’t quite trust that. My reasoning is that TCP is at most a keepalive to the LB and WS’s ping is at most reaching the gateway. I guess keeping the characters awake is a reasonable side-effect for what I want to have (i.e. I want to hear from that specific backend).
Actually the ping doesn’t seem to prevent idling. What’s the best thing to counter that? I guess I can make the bot go “hmm” every once in a while but other than that?
This works perfectly fine and has no overhead to speak of.
But I guess we should have something to set active and idle state as well.
Maybe just a single setActiveState command?
I’d help me a lot if you could provide me with a schema (fields, their types and optionality) for the out event, it looks like I’m missing a couple fields here and there and I’d prefer to deserialize it proper instead of guesstimating.
The test server is a replicate of Wolfery, and it is restored from Wolfery’s backups every 24 hours; anything not on Wolfery will be wiped, including any puppet I create. Instead, you can go to Miranda (Miranda’s Café), and type:
register puppet Miranda
Once I’ve accepted that request, you will have a puppet to control.
To try out the controlRequest, you could register Miranda twice using two different characters of yours. Then you can try take control between them.
Once done registering puppets, you have to wait for the backup restore (00:15 UTC time… I think. Or was it CET?).
Sometimes core.tooActive returns {seconds: xx} but other times there are no seconds in the data. What’s in there? Every time it failed on that side I had the traffic tracing off
If core.tooActive contains no seconds, it is <= 1 second.
The data property returned in error messages is meant only for text formatting and localization purpose, so it isn’t really intended to be used as a reliable source of info.
The flood detection feature determines if a player is allowed to issue a command right away, of if they will get the core.tooActive error.
Which commands are you interested in knowing the cost of?