I want to attach signatures, documents, or photos to an email or pdf, and I am using CloudCode to process my data. How can I ensure that the attachment has been uploaded before the CloudCode task is triggered?
See the example below:
Say your model has a field, customer_signature
of type: signature
. You want to ensure that before the ready
webhook is fired to CC, the signature is uploaded. This is accomplished by adding the field
attribute to the webhook, and setting the state to uploaded
. The valid options for state are uploaded
and present
. If you only want to check that it has been captured for a given task, present
is sufficient.
<webhook type="ready" receiver="cloudcode" action="mytask" >
<field name="customer_signature" state="uploaded" required="true" embed="true" />
</webhook>
@jason’s answer is perfect if you are only waiting on attachment fields on the object that is supposed to trigger your webhook.
In some scenarios you may not be able to use this mechanism, or maybe not exclusively, because you may have multiple attachments spread across multiple different objects that need to be combined into your report, or because you may be using a separate dedicated report_generation object, linked to the main object, which holds the webhook trigger but does not have the attachments itself.
In these scenario’s you are best placed to check if the attachments have been uploaded in your CC task before attempting to use them in your report.
Below is a basic example that implements a basic check if attachment is uploaded, wait and reschedule report generation if necessary. It works with a direct webhook but also as a rescheduled task
const delay = ms => new Promise(res => setTimeout(res, ms));
export async function run(params) {
// get the Report Request object from the webhook or the reschedule Params
let reportRequestObject = await DB.report_request.first(params.object.id);
// get the related parent object - this is the object that has all the report data
let parentObject = await reportRequestObject.parentObject();
// check if the attachment(s) on the parent object is available
if (parentObject.attachment_field && !parentObject.attachment_field.present()) {
console.log('Attachment captured but not yet uploaded. Waiting 10 seconds');
await delay(10000);
console.log('Checking if signature is now available');
await parentObject.reload();
if (!parentObject.attachment_field.present()) {
// optionally you can track and limit the number of retries that you allow
// you can also consider an exponential backup strategy, increasing the time between each subsequent rescheduling event for the same request.
console.log('Attachment still not available, rescheduling CC task');
let rescheduleParams = { object: { id: reportRequestObject.id } };
try {
await CloudCode.scheduleTask({ task: this.name, parameters: rescheduleParams });
} catch (er) {
try {
console.log('Initial rescheduling failed, trying again');
await CloudCode.scheduleTask({ task: this.name, parameters: rescheduleParams });
} catch (er) {
console.log('FAILED');
throwError(er)
}
}
}
// the rest of the report generation code happens here
...
}