Good point. I probably should have cut to the chase and sent my response as
a PR. I'll do that as soon as I'm back at a non-phone keyboard.

On Wed, Jul 19, 2017, 3:56 PM Daniel Sank <[email protected]> wrote:

> Allow me to state the obvious: whatever comes out of this discussion
> should probably result in an update of the spec file. Searching mailing
> list history is great but... oh wait never mind searching mailing list
> history is terrible :-)
>
> On Wed, Jul 19, 2017 at 2:57 PM, Ross Light <[email protected]> wrote:
>
>> Replies inline (with the disclaimer that I'm not Kenton, my only
>> credentials are that I have stared at this file for a long time):
>>
>> On Wed, Jul 19, 2017 at 1:46 PM Thomas Leonard <[email protected]> wrote:
>>
>>> Hi,
>>>
>>> I'm trying to write an implementation of the RPC spec (level 1, in
>>> OCaml). I found a few parts of the spec unclear - could someone clarify
>>> them for me?
>>>
>>> It says:
>>>
>>> [ExportId]
>>> > The exporter chooses an ID before sending a capability over the wire.
>>> If
>>> > the capability is already in the table, the exporter should reuse the
>>> same ID.
>>>
>>> But later:
>>>
>>> [CapDescriptor]
>>> > senderHosted @1 :ExportId;
>>> > A capability newly exported by the sender.  This is the ID of the new
>>> capability in the
>>> > sender's export table (receiver's import table).
>>>
>>> How can the exporter reuse the same ID, if it has to be newly exported?
>>>
>>
>> That seems like a doc/spec typo.  You can always specify an existing
>> capability.  I think the wording should be something like: "A capability
>> exported by the sender.  This may or may not be a new ID in the sender's
>> export table (receiver's import table)."
>>
>>
>>> [Message]
>>> > This could be e.g.  because the sender received an invalid or
>>> nonsensical
>>> > message (`isCallersFault` is true) or because the sender had an
>>> internal error
>>> > (`isCallersFault` is false).
>>>
>>> isCallersFault appears to be deprecated (`obsoleteIsCallersFault`
>>> appears much later).
>>>
>>
>> Yup, Exception has changed (IMO for the better).  Instead of placing
>> blame on sender or receiver (such distinctions are hard to draw in
>> general), exceptions are now about what action that caller is advised to
>> take based on the failure.
>>
>> [Call.sendResultsTo]
>>> > When `yourself` is used, the receiver must still send a `Return` for
>>> the call, but sets the
>>> > field `resultsSentElsewhere` in that `Return` rather than including
>>> the results.
>>>
>>> When should `resultsSentElsewhere` be returned? Once the result is
>>> known? Or
>>> once the first takeFromOtherQuestion collects it?
>>>
>>
>> (I haven't implemented this for Go yet, but want to.) AFAICT
>> resultsSentElsewhere should be sent once the result is known.
>>
>>
>>> Can takeFromOtherQuestion be used more than once for a single source
>>> question?
>>>
>>
>> I would assume that it could be used until Finish message is sent for
>> that question, much like other question-based data.  In practice, every
>> call's result is held in the answers table until Finish is received.
>>
>>
>>> > The `Call` for bar'() has `sendResultsTo` set to `yourself`, with the
>>> value being the
>>> > question ID originally assigned to the bar() call.
>>>
>>> What does "the value" refer to here? `yourself` has type `Void`.
>>>
>>
>>> > Vat B receives the `Return` for bar'() and sends a `Return` for bar(),
>>> with
>>> > `receivedFromYourself` set in place of the results.
>>>
>>> `receivedFromYourself` does not appear anywhere else in the spec.
>>>
>>
>> I think this whole example is stale and probably needs another draft.
>>
>>
>>> [Return.releaseParamCaps]
>>> > If true, all capabilities that were in the params should be considered
>>> released.
>>>
>>> Just to be sure: as if the sender had sent a release message for each
>>> one with `count=1`?
>>>
>>
>> (I might be wrong on this point, it's been a while since I've looked.
>> The docs should probably spell this out.)  Usually.  The list of
>> CapDescriptors in a Payload could point to the same capability multiple
>> times.  A release message of count=1 per CapDescriptor is a more accurate
>> way of phrasing this.
>>
>>
>>> [Payload]
>>> Why is it not possible to send exceptions in payloads? Should I export
>>> each
>>> broken capability as an export and then immediately send a Resolve for
>>> each
>>> one, resolving it to an exception?
>>>
>>
>> Payload is only used for parameters and results.  It doesn't make sense
>> for parameters to be an exception, and results is inside a union where you
>> could specify an exception that is an alternative.  I'm not sure I
>> understand the use-case where you are sending a broken capability.
>>
>>
>>> [Resolve]
>>> > When an export ID sent over the wire (e.g. in a `CapDescriptor`) is
>>> indicated to be a promise,
>>> > this indicates that the sender will follow up at some point with a
>>> `Resolve` message.  If the
>>> > same `promiseId` is sent again before `Resolve`, still only one
>>> `Resolve` is sent.  If the
>>> > same ID is sent again later _after_ a `Resolve`, it can only be
>>> because the export's
>>> > reference count hit zero in the meantime and the ID was re-assigned to
>>> a new export, therefore
>>> > this later promise does _not_ correspond to the earlier `Resolve`.
>>>
>>> It's not clear to me why it is useful for the receiver to know this.
>>> Presumably the sender can't reuse an export ID until the receiver
>>> explicitly releases it anyway.
>>> Should an implementation keep track of whether a resolve has arrived yet
>>> and behave differently based on this when it sees an export ID?
>>>
>>
>> It's more specifying that the receiver should not resolve the promise
>> more than once.  I believe in this case that it would be a protocol
>> violation, in which case the correct behavior would be for the receiver to
>> send an abort.
>>
>> > The sender promises that from this point forth, until `promiseId` is
>>> released, it shall
>>> > simply forward all messages to the capability designated by `cap`.
>>>
>>> Does something similar apply to Return messages? Might be worth
>>> mentioning it there too.
>>>
>>
>> I believe so, but I don't know/remember. :(
>>
>>
>>> [Disembargo]
>>> > Embargos are used to enforce E-order in the presence of promise
>>> resolution.  That is, if an
>>> > application makes two calls foo() and bar() on the same capability
>>> reference, in that order,
>>> > the calls should be delivered in the order in which they were made.
>>> But if foo() is called
>>> > on a promise, and that promise happens to resolve before bar() is
>>> called, then the two calls
>>> > may travel different paths over the network, and thus could arrive in
>>> the wrong order.  In
>>> > this case, the call to `bar()` must be embargoed, and a `Disembargo`
>>> message must be sent along
>>> > the same path as `foo()` to ensure that the `Disembargo` arrives after
>>> `foo()`.
>>>
>>> What does "this case" refer to? When exactly is an embargo needed, and
>>> when not?
>>>
>>
>> If you're implementing level 1 (two-party), then really the only place
>> where this applies is when you receive a capability that the receiver hosts
>> as part of a return or resolve after you have made calls on the promised
>> capability.  This implies that the RPC system needs to keep track of which
>> parts of the answer have had calls made on them.  When this occurs, the
>> receiver gives the application code an embargoed client, and then sends a
>> Disembargo with senderLoopback set.  It releases the embargo once the same
>> disembargo ID is returned with receiverLoopback set.
>>
>> For me, this was the hardest part of the spec to understand.  I
>> understand why it's needed, but it's really hard to grok the implications.
>>
>> > There are two particular cases where embargos are important.  Consider
>>> object Alice, in Vat A,
>>> > who holds a promise P, pointing towards Vat B, that eventually
>>> resolves to Carol.
>>>
>>> Could Carol be another promise here? Should Alice wait until the target
>>> is fully resolved before doing a disembargo, or do a disembargo for each
>>> step?
>>>
>>
>> See above explanation.  But no, Carol cannot be a promise, since the only
>> time that an embargo is triggered is once you get back a locally hosted
>> capability.
>>
>>
>>> [Accept]
>>> > This message is also used to pick up a redirected return -- see
>>> `Return.redirect`.
>>>
>>> `redirect` doesn't appear anyway else in this spec. I guess it's
>>> `Return.sendResultsTo.thirdParty`.
>>>
>>
>> Probably.  It's Level 3, so it's invisible to me. :D
>>
>>
>>>
>>> [ Network-specific Parameters]
>>> > For interaction over the global internet between parties with no other
>>> prior arrangement, a
>>> > particular set of bindings for these types is defined elsewhere.
>>> (TODO(someday): Specify where
>>> > these common definitions live.)
>>>
>>> Do these definitions exist now?
>>>
>>
>> ¯\_(ツ)_/¯
>>
>>
>>>
>>> Thanks!
>>>
>>> --
>>> You received this message because you are subscribed to the Google
>>> Groups "Cap'n Proto" group.
>>> To unsubscribe from this group and stop receiving emails from it, send
>>> an email to [email protected].
>>> Visit this group at https://groups.google.com/group/capnproto.
>>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "Cap'n Proto" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to [email protected].
>> Visit this group at https://groups.google.com/group/capnproto.
>>
>
>
>
> --
> Daniel Sank
>
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"Cap'n Proto" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
Visit this group at https://groups.google.com/group/capnproto.

Reply via email to