Skip to content

multipart messages

Fanda Vacek edited this page Feb 12, 2024 · 15 revisions

Multipart messages

New meta key part will be introduced in RpcResponse. RpcResponse without part key is considered to be the final one. This is aligned with single-part messages, which currently have not a part key.

Second possibility is to consider message to be multipart part == true, if rcid key is present in meta-data. When this approach will be used, then rcid must be always used when inner parts will be transferred, what can lead to simpler client implementation because there will not be any need to store rcid received in first response to have opportunity to cancel whole transfer.

RpcMessage body IMap keys will be extended by following keys:

  • chunk - optional, if chunk key is received, then result should be appended to result of previous chunks
    • String, Blob will be concatenated
    • List will be appended
    • Map will be merged
  • progress - optional, IMap with following keys:
    • index - index of current part <0, count)
    • count - part count
    • message

Both sides of multi-part session can cancel it sending a message with part == false.

Also sender can cancel whole transfer, if it will send RpcResponse with error set

What multipart messages can be good for:

  • transfer big file in N chunks with progress
  • keep caller informed about progress of very long time lasting RPC call
  • cancel long lasting RPC call by caller
  • tunneling

Use cases

case msg rcid part method param result error
send large file RQ x setFile file-name, chunk-1
_ RESP x x null
_ CRESP-x x chunk-x
_ CRESP-N chunk-N
get large file RQ getFile file-name
_ RESP-1 x x chunk-1
_ RESP-x x x chunk-x
_ RESP-N x chunk-N
rpc wit progress RQ primeNumber 1E+28
_ RESP-1 x x chunk-1
_ RESP-x x x chunk-x
_ RESP-N x chunk-N
tunnel RQ openTunnel null
_ RESP x x data
_ CRESP-x x data
_ RESP-x x x data
_ RESP-N x data
_ CRESP-N data

Receive large file

  1. client issue getFile() rqId = RQID
  2. File device will split file content to N chunks
  3. N RpcResponses will be sent back to client
    • every response will have rqId == RQID
    • first N-1 responses will be sent with part==true in metadata and chunk == true + result == BLOB_DATA_n in response body
    • N-th response will be sent with part == false in metadata and chunk == true + result == BLOB_DATA_n in response body

Send large file

  1. client issue sendFile() with rqId == RQID + rcid == null + part == true key set in metadata.
  2. device responses with some result and wait for more messages with rqId == RQID, client will take rcid list from response, we will call it RCID
  3. Client will split file content to N chunks
  4. N RpcResponses will be sent back to device
    • every response will have rqId == RQID + cid == RCID
    • first N-1 responses will be sent with part==true in metadata and chunk == true + result == BLOB_DATA_n in response
    • N-th response will be sent with part == false in metadata and chunk == true + result == BLOB_DATA_n in response data

Long lasting computation with progress

  1. client issue heavyComputation() with rqId = RQID
  2. N RpcResponses will be sent back to client
    • every response will have rqId == RQID + rcid set to enable RPC call cancellation
    • first N-1 responses will be sent with part==true in metadata and progress: i{...} + result == null in response body
    • N-th response will be sent with part == false in metadata and result == 42 in response data

Bi-directional tunnel

  1. client calls openTunnel() with rqId == RQID + rcid == null + part == true key set in metadata.
  2. device will save first message cid as CID
  3. Device responses with some result and wait for more messages with rqId == RQID, client will take rcid list from response, we will call it RCID
  4. Client will send any data to its tunnel end as Rpcresponse with rqId == RQID + cid == RCID
  5. Device will send any data to its tunnel end as Rpcresponse with rqId == RQID + cid == CID
  6. Tunnel is closet if
    • Client or device send RpcResponse with part = false