Subject: [Jmap] Adding optional createdId property to Request/Response object

From: Neil Jenkins <[email-masked]>
Date: Mon, 09 Apr 2018 14:38:28 +1000

I presented this briefly in London, but before merging the pull
request[1] I just wanted to post this to the list to check it's clear
and people agree this is valuable. You can check the diff in the pull
request, but essentially this change adds an optional extra property you
can send with a request which contains an initial map of creation id =>
server-assigned "real" id for records. This is primarily to allow for
easier proxying of JMAP requests.
For example, suppose you had this request, presuming a Foo object with a
name property, and a Bar object with a name property, and a fooId
property that references a Foo:
{ "using": [ ... ], "methodCalls": [ ["Foo/set", { "accountId": "1",
"create": { "k31": { "name": "1st object" } } }, "1"], ["Foo/set", {
"accountId": "2", "create": { "k32": { "name": "2nd object" } } }, "2"],
["Bar/set", { "accountId": "1", "create": { "k31": { "name": "3rd
object", "fooId": "#k31" } } }, "3"], ] }A proxy server may wish to proxy the method calls to different backends
depending on the accountId. In order to do so it needs to split this
into 3 JMAP requests, each with a single method call, make the requests
in order, then combine the results.
However, to do this without the proposed createdId change, the proxy
would have to resolve the "fooId" reference itself. This requires
understanding the structure of the Bar object (knowing that the fooId
property is a reference to a Foo object), making the proxy much harder
to write, when it shouldn't need to know this information.
With the proposed change, the proxy can do this. To server 1:

{ "using": [ ... ], "methodCalls": [ ["Foo/set", { "accountId": "1",
"create": { "k31": { "name": "1st object" } } }, "1"], ],
"createdIds": {} }Response from server 1:

{ "methodResponses": [ ["Foo/set", { "accountId": "1", "created": {
"k31": { "id": "84291" } } ... }, "1"], ], "createdIds": { "k31":
"84291" } }Then request to server 2 just passes the received createdId object on:

{ "using": [ ... ], "methodCalls": [ ["Foo/set", { "accountId": "2",
"create": { "k32": { "name": "2nd object" } } }, "2"], ], "createdIds":
{ "k31": "84291" } }and similarly the object returned from this call is passed on to the
final request to server 1 again:

{ "using": [ ... ], "methodCalls": [ ["Bar/set", { "accountId": "1",
"create": { "k31": { "name": "3rd object", "fooId": "#k31" } } }, "3"],
], "createdIds": { "k31": "84291", "k32": "7333adf1" } }The proxy then just has to concatenate the methodResponses arrays from
the different calls to return to the client. Importantly, you can now
write a very light-weight JMAP proxy that does useful things without
having to understand anything specific about the methods it is proxying.
Any comments/objections/clarifications please let me know, otherwise
I'll merge this next week.
Cheers,
Neil.

Links:

  1. https://github.com/jmapio/jmap/pull/198