Querying Task Documents

Querying the data which results from an example task. Notes on the performance implications of tasks.

This guide explains the data which results from tasks and how to query it.

  • Write a PostgreSQL query to examine task data
  • Build deeper understanding of task data
  • Present some data considerations of which task authors should remain mindful

Prerequisites

Querying task data

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

First Assessment Completion Rate

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 created automatically by the medic-couch2pg service. It is an intuitive 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.

Understanding the data

Here is a sample output from that query above. The query was executed some day in July (07), 2021.

due_date_monthtask_statecount
2021-05-01Cancelled6
2021-05-01Completed749
2021-05-01Failed226
2021-06-01Cancelled3
2021-06-01Completed769
2021-06-01Draft3
2021-06-01Failed177
2021-07-01Completed1135
2021-07-01Draft399
2021-07-01Failed193
2021-07-01Ready13

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.

Task data considerations

Performance

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.

Completion vs Cancellation

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 StateappliesIfresolvedIf
Draft/Ready/Failedtruefalse
Completedtruetrue
Cancelledfalse-

Testing task document data

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.

Frequently Asked Questions


CHT Applications > Tutorials > Tasks

Writing and testing a simple task

CHT Core Framework > Overview > Database Schema : Tasks

Schema for database objects

CHT Core Framework > Overview > Data Flows

An overview of data flows in the CHT for analytics, impact monitoring, and data science