Hi,
I'd like to reach out with a few questions and observations regarding the 2.0 version:
1. "params: null"
Some implementations send `params: null` when the method no parameters - this is against (my read of) the spec but practically must be accepted for compatibility with languages where `null` vs empty is difficult to express (golang was mentioned in our issue tracker).
Perhaps it should would make sense to acknowledge this practical reality, making `params: null` equivalent to "no parameters" or "empty list".
2. Out-of-order responses to single requests
From reading the spec text, it feels implied (in examples and protocol structure) that the order of responses corresponds to the order of requests. There's also the batching feature which states that responses within a batch may be returned unordered - this again implies that outside of a batch, responses are ordered.
However, practical reality is that responses can and do arrive out of order and should / must be matched by `id` - this is of course less interesting in "one-shot" transports like http but it happens practically with websockets and other long-lived connections.
One could argue that the presence of an `id` field to begin with implies that out-of-order responses are expected.
The implication of allowing out-of-order responses is that error handling becomes difficult - for example, the idea of setting `id` to `null` doesn't help - in a world of unordered responses, there's no way to match a particular request to a particular response for this purpose - how do implementations typically handle this? Dropping the connection seems like a strict and correct implementation - best-effort could also be used but this perhaps is overkill since we're after all dealing with protocol failures rather than "application errors". What are common strategies that work well here?
I think it would be good for the spec to be explicit about this point, whichever way it was meant to work.
3. Batches are messy
Batches are offered as an explicit way to deal with multiple requests in one go, but the chosen format has several limitations in that respect:
* The possibility of out-of-order responses are explicitly stated but strictly, processing cannot start until the full batch has been read since we must take into account things like the end-of-array marker
* This point is also related to error reporting: if a single request within a batch cannot be decoded (for example it lacks a required field), the whole batch is faulty and there's no way to return an error about the individual request, since responses might be out of order within the batch - the only recourse at this point is to close the connection or heuristics
* Implementations that want to "stream" request and response processing therefore have to make a tradeoff between correctness and efficiency: wait for the full batch or accept "partial" batches (before the end-of-array marker arrives) and risk breaking the protocol.
Given the above observation about single-request responses arriving out of order, it feels like batching could simply be removed without any practical downsides - is it common in libraries that it is implemented or would it make sense to deprecate it in anticipation of a json-rpc 3.0 release some time in the future?
One potential use case for batches that I can think of would be if the transport itself inefficiently delimits messages and it's therefore better to send a json-rpc batch and accept the parsing overhead and in-memory profile the JSON array - are there examples in the wild where this matters?
Cheers,
Jacek