You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Migrate from GRPC to JSON RPC (with binary variant for higher performance) #495
Due to various issues with GRPC, and a combined effort to replace both the networking in #234 and transport agnostic RPC #249, this epic covers all the problems we have with GRPC and changes we will need to do to the RPC handling architecture.
We want to go with JSON RPC because it is going to be the most suitable for third party integration.
We can have a binary protocol format for increased performance when this is detected. Candidates are:
BSON
CBOR
Protobuf
MessagePack
We need to choose one based on benchmarks, and UI/UX of converting to our internal datasets, reliability of third party libraries, portability of parsing and generating libraries and wide-deployment.
Because we have pre-existing experience with protobuf. And we have a large corpus of protobuf definitions already. (Even though we will be reworking those with respect to JSON RPC) Then protobuf is probably a good choice for our binary alternative encoding.
However the choice of protobuf library is important too.
Our existing stack is pretty complex involving protoc, the protoc plugin for generating TS code, the google-protobufruntime library... etc.
Firstly if we were to use the params, then the params should always be an array in order to match our JS functions take parameters. Meaning f({a, b}, c) would be called with params: [{a, b}, c].
Secondly the error structure doesn't quite match our serialiation atm. We can stuff our entire error serialisation into the data property, but then copy the first level message to the message (prefixed by the exception name), and also set a generic application-error code for the code. Unless it's one of the reserved errors.
Furthermore, we have to consider what usage is the notifications, and batching and request objects in relation to our streaming usage as we are currently doing.
The request object is an open spec. We could add additional properties to a request object, in order to cover the usage of metadata we have in GRPC. In GRPC there's leading and trailing metadata: #249 (comment)
But if we do with the request object, we could actually add metadata to every single request object.
Protobuf vs JSON muxing/demuxing, should these be separated per-stream? If so, how does one identify whether it is JSON or Protobuf in the first place, how to disambiguate?
The addition of the meta property to all request objects and response objects for JSON RPC to enable passing meta, but this also means there's no such thing as "leading" or "trailing" metadata, every request/response can have metadata.
The removal of "id" from requests/response objects thus everything is just a notification. The entire stream itself can have an ID though, and we do have stream IDs as well connection IDs. 1 connection ID - multiple stream IDs... and we end up not following the JSON RPC spec to the letter.
Basically web streams doesn't have a native "duplex" stream. The only closest is the ReadableWritablePair.
So the first order of business is to develop a function that maps;
ReadableWritablePair<Uint8Array, Uint8Array>
To
ReadableWritablePair<JSON, JSON>
Where JSON is the JSON RPC message format. Although we have some requirements regarding leading headers and trailing headers discussed in #249 (#249 (comment)).
@tegefaulkes start prototyping this implementation with an new PR targetting this epic. I think having a new rpc directory as opposed to the grpc directory can be useful.
Activity
CMCDragonkai commentedon Nov 25, 2022
This now takes priority over all GRPC problems.
CMCDragonkai commentedon Dec 5, 2022
Because we have pre-existing experience with protobuf. And we have a large corpus of protobuf definitions already. (Even though we will be reworking those with respect to JSON RPC) Then protobuf is probably a good choice for our binary alternative encoding.
However the choice of protobuf library is important too.
Our existing stack is pretty complex involving
protoc, theprotocplugin for generating TS code, thegoogle-protobufruntime library... etc.This all seemingly can be replaced with 1 library: https://github.com/bufbuild/protobuf-es.
CMCDragonkai commentedon Dec 5, 2022
There are some things we need further specify above the JSON RPC spec: https://www.jsonrpc.org/specification. Because this is light on the details.
Firstly if we were to use the
params, then theparamsshould always be an array in order to match our JS functions take parameters. Meaningf({a, b}, c)would be called withparams: [{a, b}, c].Secondly the error structure doesn't quite match our serialiation atm. We can stuff our entire error serialisation into the
dataproperty, but then copy the first level message to themessage(prefixed by the exception name), and also set a generic application-error code for thecode. Unless it's one of the reserved errors.Furthermore, we have to consider what usage is the
notifications, and batching and request objects in relation to our streaming usage as we are currently doing.CMCDragonkai commentedon Dec 5, 2022
The request object is an open spec. We could add additional properties to a request object, in order to cover the usage of metadata we have in GRPC. In GRPC there's leading and trailing metadata: #249 (comment)
But if we do with the request object, we could actually add metadata to every single request object.
CMCDragonkai commentedon Dec 5, 2022
The response object can also be extended with
meta.CMCDragonkai commentedon Dec 6, 2022
Solving this problem should also involve bringing in rxjs properly.
CMCDragonkai commentedon Dec 6, 2022
Still to spec out:
metaproperty to all request objects and response objects for JSON RPC to enable passing meta, but this also means there's no such thing as "leading" or "trailing" metadata, every request/response can have metadata.CMCDragonkai commentedon Jan 3, 2023
I've recently created a WIP
QUICStreamin js-quic, details in this comment: MatrixAI/js-quic#1 (comment).Basically web streams doesn't have a native "duplex" stream. The only closest is the
ReadableWritablePair.So the first order of business is to develop a function that maps;
To
Where JSON is the JSON RPC message format. Although we have some requirements regarding leading headers and trailing headers discussed in #249 (#249 (comment)).
CMCDragonkai commentedon Jan 3, 2023
@tegefaulkes start prototyping this implementation with an new PR targetting this epic. I think having a new
rpcdirectory as opposed to thegrpcdirectory can be useful.CMCDragonkai commentedon Feb 17, 2023
For collection handlers see #237.
For most handlers see #450.
CMCDragonkai commentedon Mar 21, 2023
@tegefaulkes is this the larger epic? Please link all new issues created involving RPC migration here including the recent issues you created.
tegefaulkes commentedon Mar 24, 2023
I linked the new RPC issues to this epic.
38 remaining items
CMCDragonkai commentedon Oct 11, 2023
This is done with rpc and ws integrated. No more GRPC is in PK.
CMCDragonkai commentedon Oct 11, 2023
Note I removed the pagination issue out of this. Those are usability issues to be applied separately.
READYtoIDLEtransition #332GRPCClientderived classes andNodeConnectiontoStartStoppattern #333connectionInfoGetterfunctionality #355TLSconfigforWebSocketServer#511rpchandlers abstract arrow function properties. js-rpc#5