-
-
Notifications
You must be signed in to change notification settings - Fork 147
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add DcJsonrpcInstance class #2479
Conversation
f70c7f5
to
95ea5cd
Compare
why is that needed currently? that would also require core to be compiled with jsonrpc, right? (i see it is a draft, but still :) |
This PR enables It is not needed currently, but there are some ideas to start using JSON-RPC on all platforms. One suggestion is to try using it for QR-code scanning first to get proper errors on failure. Another option is to use it for event reception, so we receive proper JSON events instead of |
To test the changes in this pull request, install this apk: |
07018e0
to
85a84c0
Compare
tbh, i am unsure about getting jsonrpc in that quickly - i have the feeling it is not yet settled and stable - i see quite some breaking changes and and lots of pr in core, maybe it is wise to postpose that a little longer. for qr code scanning, i think it is easily doable to have a "classic" ffi (in fact, we already did that at deltachat/deltachat-core-rust#3489 ) still interesting to test in a pr, however, to see how much apk grows (if it is only a few kb, the decision may be easier to have both for some time) also, i'd like to run the benchmark script of @Hocuri at some point and see how much performance changes by using jsonrpc , eg. for the chatlist (that would need some more refactoring, of course) but again, i do not sth of that as urgent things - but why is that combined with Nix changes then? |
Nix is not related to JSON-RPC, I just use it for my development environment. Previously I used podman but it is not really suitable for development, only for building. |
a yes, i noticed too late that #2483 is actually on master and just shown wrongly as "closed" on github. so, yes, makes sense to try jsonrpc to get some findings and impressions, and once really needed we can merge that to master. i am still sceptical to make changes to the event system on master these days, without real need, however :) |
IMO it makes sense to start being able to use jsonrpc also with Android (and iOS).
it's certainly going to take a longer while until a serious attempt at
porting existing CFFI calls to jsonrpc can/should take place.
But if there is at least a base mechanism it becomes possible to play with it much better,
also from DeltaLab etc.
|
Currently JSON-RPC instance takes over the event channel, it consumes all events and transforms them into JSON-RPC notifications. We could modify the core to have an option to disable it, but I think it is more interesting to start with using JSON-RPC for events, so we can use rich event structures with meaningful variable names rather than EDIT 2023-04-22: JSON-RPC instance consuming events is going to be removed in deltachat/deltachat-core-rust#4341 |
13b3329
to
cff98f6
Compare
cff98f6
to
00fd1a9
Compare
To test the changes in this pull request, install this apk: |
Printing JSON-RPC responses for now.
To test the changes in this pull request, install this apk: |
Current state: spams logcat with
|
To test the changes in this pull request, install this apk: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, but APIs are currently unused, would be nice to use at least one of them in this PR as an example, e.g. addAccount
src/com/b44t/messenger/rpc/Rpc.java
Outdated
} | ||
} | ||
|
||
public int addAccount() throws RpcError { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this new API unused? Maybe use at least addAccount as an example of JSON-RPC usage?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes it is unused, I just add it as example so when adding new API the dev knows how to add them, I could try using addAccount()
To test the changes in this pull request, install this apk: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm wondering if we should do some measurements before merging this (how much bigger does the APK get? How much longer does a native call take now that we have to serialize and deserialize things? How much does stuff like dc_get_http_response
get faster since we can return the result as JSON instead of needing multiple follow-up calls like dc_http_response_get_mimetype
?).
src/com/b44t/messenger/rpc/Rpc.java
Outdated
id = ++requestId; | ||
} | ||
String jsonRequest = gson.toJson(new Request(method, params, id)); | ||
CompletableFuture<JsonElement> future = new CompletableFuture<>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Android Studio complains that CompletableFuture
requires API level 24 (current min is 16; also see apilevels.com).
Did you test this on Android 6 and below yet?
BTW, there is a SettableFuture
implementation in DC, taken from the Signal code, maybe it can be used here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yikes I was using SettableFuture at first, but changed to CompletableFuture because was nicer and in the standard lib, so that is why we had that SettableFuture, will change it back, thanks a lot!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe document this in the SettableFuture
then? It is indeed "Added in API level 24" on https://developer.android.com/reference/java/util/concurrent/CompletableFuture, this page can be linked from there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another question is, why doesn't our CI complain or fail? If Android Studio knows this, it should be possible to detect this automatically from gradle build.
src/com/b44t/messenger/rpc/Rpc.java
Outdated
String jsonResponse = dcJsonrpcInstance.getNextResponse(); | ||
Response response = gson.fromJson(jsonResponse, Response.class); | ||
|
||
if (response.id == 0) { // Got JSON-RPC notification, ignore |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For my understanding, what's a JSON-RPC notification?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
some legacy thing I think, in the past the RPC used to send unsolicited notifications with events so "notifications" here means incoming events that come without the client requesting them to the RPC server, we now have a new api to manually poll for events
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in theory that check should never be true, I guess it was more about catching bugs during the creation of this PR by @link2xt and probably can be removed, maybe there is still a way to enable that notifications/events and that is why this check exist but in practice it should never be enabled
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be nice to either replace notification
with event
or remove this block.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://www.jsonrpc.org/specification#notification says "A Notification is a Request object without an "id" member."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no such thing as "event" in the specification. We previously used notifications to send events from the server to the client, but JSON-RPC 2.0 specification is written in a way assuming that only the client sends requests (including notifications, i.e. requests without an ID).
implementation 'com.fasterxml.jackson.core:jackson-databind:2.11.1' // used as JSON library | ||
implementation 'com.google.code.gson:gson:2.10.1' // used as JSON library |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, so we need one more JSON library? jackson-databind doesn't work? Can we use gson instead of jackson-databind, in order to not increase the number of dependencies?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if you grep for gson, you will find that we already use it in some part of the code, it seems it is a dependency of some of our dependencies already, I had to explicitly add this because it seems the version used by the dependency was old and didn't have a needed method.
in a follow-up PR we should try to only use one of gson, jackson and org.json (the 3 are used at the moment in existing code besides this PR)
src/com/b44t/messenger/rpc/Rpc.java
Outdated
if (response.error != null) { | ||
future.completeExceptionally(new RpcError(response.error.toString())); | ||
} else if (response.result != null) { | ||
future.complete(response.result); | ||
} else { | ||
future.completeExceptionally(new RpcError("Got JSON-RPC response witout result or error: " + jsonResponse)); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a lot of code changing exceptions from one form to another here, what if we replaced this whole block with future.complete(response);
, used CompletableFuture<Response>
instead of CompletableFuture<JsonElement>
, and let the callers (like getResult()
) extract the error on their own.
Also, creating a Throwable is always expensive, since it captures a stack trace. Idk how expensive excactly and if it might be noticeable in our code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
all the callers will want to extract the error/result so it would be too much of a burden and repeated code, they have to do this anyway, and if there is an error they will want to print it in the logs, because it will be a programming error (ex. bad usage of API)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(these are not incoming events that could become a bunch of errors, they are only responses to API calls, so if you call a function and it throws an exception you need to handle it anyway)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But checking for response.result != null is the same amount of code as catching the error
Co-authored-by: Hocuri <hocuri@gmx.de>
To test the changes in this pull request, install this apk: |
To test the changes in this pull request, install this apk: |
yeah, that'd be interesting, however, in general, for non-time-critical things, jsonrpc probably makes sense anyway.
for adding accounts, not sure, i would not touch that for now. also, other than stated at deltachat/deltachat-ios#1847 "the aim is to start by using JSON-RPC for any new API" - i am not sure if that is really the aim for now. eg. if there comes a new method to dc_msg_t, it probably makes sense to add that to ffi still. also, for reading eg. a single record, it has to be proven if that is faster or much easier i'd say. i see this jsonprc more as something that may sneak in, if it turns out that things are easier and faster with that, this is the way automatically. iirc, jsonrpc could also get a bit more mature before being used everywhere, iirc there is no mapping between ffi and jsonrpc, low-level things and documentation are also missing. also from that perspective, there is no need to hurry. |
ok, done ☑️ |
To test the changes in this pull request, install this apk: |
yip for something like a new method to dc_msg_t wouldn't make sense, mean it like for new classes etc. ideally at some point there will be automatic generation of the bindings then we can make more heavy migration |
ftr, as the question of size popped up above: with 1.37, we have some measurements:
|
ftr, there are some measurements at deltachat/deltachat-core-rust#4463 now |
they are replaced by jsonrpc in #2479
they are replaced by jsonrpc in #2479
TODO:
The purpose of this is to make it possible to use JSON-RPC calls when the corresponding CFFI is not ready yet, or skip adding CFFI for new calls completely.
This change enables
jsonrpc
core feature inndk-make.sh
.Since core PR deltachat/deltachat-core-rust#4341 is merged, we don't have to switch event processing to use JSON-RPC when we create a JSON-RPC instance. So we can keep event loop using the C API and use JSON-RPC for something simple at first.
For example, we can try to use it for QR-code scanning first to get proper errors on failure. Another option is to use it for event reception, so we receive proper JSON events instead of data1, data2 etc. Another option is to use it instead of the recently added in #2539
dc_http_response_t
API.Java API for JSON-RPC instance is ready, but we need a way to dispatch . ~
java.util.concurrent.CompletableFuture(UPDATE: not compatible with Android API 16) looks like something similar to the
asyncio.Future
we use in the Python JSON-RPC client.