Building > Tutorials > Tasks
Writing and testing a simple task
This guide explains the data which results from tasks and how to query it.
The task system running on each user’s device is powered by task documents and those task documents sync to the server and to PostgreSQL just like a contact or a report. Having task documents in PostgreSQL allows system administrators to analyse how users are interacting with tasks.
See Also: Data flows for analytics
Working with the First Assessment task from the Configuring Tasks Tutorial, let’s try to answer the question What percentage of the scheduled first assessment events have been completed?.
Let’s query data from the last three months to see how the first assessment task is behaving in production:
SELECT
date_trunc('month', duedate) AS due_date_month,
task_state,
count(*)
FROM useview_task
WHERE
title = 'assessment-after-registration' and
duedate >= date_trunc('month', now()) - '3 months'::interval and
duedate < date_trunc('month', now()) + '1 months'::interval
GROUP BY 1, 2
ORDER BY 1, 2
;
For convenience, here is the task definition from the First Assessment task in the tutorial:
module.exports = [{
name: 'assessment-after-registration',
title: 'First Assessment',
icon: 'icon-healthcare',
appliesTo: 'contacts',
appliesToType: ['patient'],
appliesIf: c => user.parent && user.parent.contact_type === 'chw_area' && !c.contact.date_of_death && !c.contact.muted,
actions: [{ form: 'assessment' }],
events: [{
start: 7,
days: 7,
end: 0,
}],
}];
What is this code doing?
useview_task
- This is a materialized view of the data from the task document schema.task_state
- The meaning of each task state is explained in the task document schema.WHERE title
- The name attribute in the task.js schema is used exclusively in the task’s backend data. Here we limit the query to task documents resulting from our named task. The title
in postgres maps to the name
in JavaScript not the title
in JavaScript - which is confusing.WHERE duedate
- One task document is created per event and this task has one event per contact which is due 7 days after the contact’s creation date. Here we limit the query to task documents which are due in the last 3 calendar months.Here is a sample output from that query above. The query was executed some day in July (07), 2021.
due_date_month | task_state | count |
---|---|---|
2021-05-01 | Cancelled | 6 |
2021-05-01 | Completed | 749 |
2021-05-01 | Failed | 226 |
2021-06-01 | Cancelled | 3 |
2021-06-01 | Completed | 769 |
2021-06-01 | Draft | 3 |
2021-06-01 | Failed | 177 |
2021-07-01 | Completed | 1135 |
2021-07-01 | Draft | 399 |
2021-07-01 | Failed | 193 |
2021-07-01 | Ready | 13 |
Task docs from May and June are mostly in states Completed
or Failed
. In May, you could say with high confidence that the completion rate for this task was 749/(749+226) or 76%. Task docs in July have end dates in the future still, so they are in state Draft
or Ready
.
Why are tasks Cancelled? - A task document is cancelled when tasks.js
schedules the task event (appliesToType
and appliesIf
both pass), and later does not schedule the task event. So in this first assessment scenario, a likely cause of task cancellation would be that a contact was deleted, muted, or dead. The task document is created when appliesIf
returns true. When the contact is muted, the task disappears from the UI, and the task document is moved to state Cancelled.
How can there be documents in state “Draft” in June? - The state Draft means that the task event is scheduled in the future. How can these documents with due dates in the past (June) be in a state which says they are in the future? Task documents are calculated and updated on the user’s device, so the most likely explanation is that the user hasn’t synced. Other potential explanations are possible.
Performance of CHT Applications is a major factor for many users and partners. The CHT Core is designed and tested to work on low-cost devices, but tasks have the potential to cause performance problems by creating too many task documents or performing excessive computations. Be mindful of the task documents which will be created by your tasks. Monitor the number of task documents being created in production.
A task can “disappear” because appliesIf
returns false or because resolvedIf
returns true. To the user the experience is identical - but the difference is in the data.
resolvedIf
should contain only your programmatic task success criteria. Everything else should be in appliesIf
.
Resultant State | appliesIf | resolvedIf |
---|---|---|
Draft/Ready/Failed | true | false |
Completed | true | true |
Cancelled | false | - |
The medic-conf-test-harness is useful for making assertions about the expected behaviour of tasks in different user scenarios. The countTaskDocsByState interface is relevant for making assertions about task document creation and state.
Writing and testing a simple task
Schema for database objects
An overview of data flows in the CHT for analytics, impact monitoring, and data science
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.