Progressive Call ResultsΒΆ
Progressive Call Results is a feature from the WAMP Advanced Profile. The specification can be found here.
As a default, a call returns a single result. For some calls it may be desirable to have a series of call results, e.g. a longer user list may be sent in chunks which the caller can already process while the entire transfer of the user list is still in progress.
In WAMP, this is possible via Progressive Call Results. With these, a call can return a series of partial results, with a final result which signals that the series has ended.
For example, call which requests progressive call results in a JavaScript component using Autobahn|JS could be
session.call('com.myapp.longop', [3], {}, {receive_progress: true}).then(
function (res) {
console.log("Final:", res);
connection.close();
},
function (err) {
},
function (progress) {
console.log("Progress:", progress);
}
);
With progressive call results, there is a need for two result handlers: one for the progressive results and one for the final result.
Depending on whether there is any need to handle the two differently, you may pass the same handler.
The same call in a Python component using Autobahn|Python would be
def on_progress(i):
print("Progress: {}".format(i))
res = yield self.call('com.myapp.longop', 3, options=CallOptions(onProgress=on_progress))
print("Final: {}".format(res))
For the above calls, a callee in JavaScript/Autobahn|JS would be
function longop(args, kwargs, details) {
var n = args[0];
var interval_id = null;
if (details.progress) {
var i = 0;
details.progress([i]);
i += 1;
interval_id = setInterval(function () {
if (i < n) {
details.progress([i]);
i += 1;
} else {
clearInterval(interval_id);
}
}, 1000);
}
var d = when.defer();
setTimeout(function () {
d.resolve(n);
}, 1000 * n);
return d.promise;
}
The procedure here uses timers to simulate long operations. It returns a
promise since the timers execute after the body of the procedure has
been executed. The progressive results are sent via the progress
method on the call details
, and the final result is sent by
resolving the promise.
The equivalent Python procedure would be:
@inlineCallbacks
def longop(n, details=None):
if details.progress:
# caller can (and requested to) consume progressive results
for i in range(n):
details.progress(i)
yield sleep(1)
else:
# process like a normal call (not producing progressive results)
yield sleep(1 * n)
returnValue(n)
yield self.register(longop, 'com.myapp.longop', RegisterOptions(details_arg='details'))
You can also take a look at a full working example.