pollForResponse function
Future<BinaryBlob>
pollForResponse(
- Agent agent,
- Principal canisterId,
- RequestId requestId,
- PollStrategy strategy,
- String method, {
- BinaryBlob? overrideCertificate,
Implementation
Future<BinaryBlob> pollForResponse(
Agent agent,
Principal canisterId,
RequestId requestId,
PollStrategy strategy,
String method, {
BinaryBlob? overrideCertificate,
}) async {
final Principal? caller;
if (agent is HttpAgent) {
caller = agent.identity?.getPrincipal();
} else {
caller = null;
}
final path = [blobFromText('request_status'), requestId];
final Certificate cert;
if (overrideCertificate != null) {
cert = Certificate(
cert: overrideCertificate,
canisterId: canisterId,
rootKey: agent.rootKey,
);
} else {
final state = await agent.readState(
canisterId,
ReadStateOptions(paths: [path]),
null,
);
cert = Certificate(
cert: state.certificate,
canisterId: canisterId,
rootKey: agent.rootKey,
);
}
final verified = await cert.verify();
if (!verified) {
throw UnverifiedCertificateError();
}
final maybeBuf = cert.lookup([...path, blobFromText('status').buffer]);
final RequestStatusResponseStatus status;
if (maybeBuf == null) {
// Missing requestId means we need to wait.
status = RequestStatusResponseStatus.unknown;
} else {
status = RequestStatusResponseStatus.fromName(maybeBuf.u8aToString());
}
switch (status) {
case RequestStatusResponseStatus.replied:
return cert.lookup([...path, blobFromText('reply')]) as BinaryBlob;
case RequestStatusResponseStatus.received:
case RequestStatusResponseStatus.unknown:
case RequestStatusResponseStatus.processing:
// Execute the polling strategy, then retry.
await strategy(canisterId, requestId, status);
// Passing the override certificate will cause infinite stacks.
return pollForResponse(agent, canisterId, requestId, strategy, method);
case RequestStatusResponseStatus.rejected:
final rejectCode = cert.lookup(
[...path, blobFromText('reject_code')],
)!.toBn();
final rejectMessage = cert.lookup(
[...path, blobFromText('reject_message')],
)!.u8aToString();
throw PollingResponseRejectedException(
canisterId: canisterId,
requestId: requestIdToHex(requestId),
status: status,
method: method,
rejectCode: rejectCode,
rejectMessage: rejectMessage,
caller: caller,
);
case RequestStatusResponseStatus.done:
// This is _technically_ not an error, but we still didn't see the
// `Replied` status so we don't know the result and cannot decode it.
throw PollingResponseNoReplyException(
canisterId: canisterId,
requestId: requestIdToHex(requestId),
status: status,
method: method,
caller: caller,
);
}
}