def txn(): task = api.get_task(domain_identifier, task_identifier) if not task: logging.error("Task '%s/%s' does not exist", domain_identifier, task_identifier) return None parent_task = api.get_task(domain_identifier, task.parent_task_identifier()) if parent_task: parent_index = TaskIndex.get_by_key_name( parent_task.identifier(), parent=parent_task.key()) if not parent_index: logging.error("Missing index for parent task '%s/%s'", domain_identifier, parent_identifier) self.error(400) # Retry later return None hierarchy = list(parent_index.hierarchy) hierarchy.append(parent_task.identifier()) level = parent_task.derived_level + 1 else: # root task hierarchy = [] level = 0 index = TaskIndex.get_by_key_name(task_identifier, parent=task) if not index: index = TaskIndex(parent=task, key_name=task_identifier) index.hierarchy = hierarchy index.put() task.derived_level = level task.put() return task
def txn(): task = api.get_task(domain_identifier, task_identifier) if not task: logging.error("Task '%s/%s' does not exist", domain_identifier, task_identifier) return index = TaskIndex.get_by_key_name(task_identifier, parent=task) if not index: index = TaskIndex(parent=task, key_name=task_identifier) # Get all subtasks. The ancestor queries are strongly # consistent, so when propagating upwards through the # hierarchy the changes are reflected. subtasks = list(Task.all().ancestor(domain_key).filter("parent_task =", task.key())) if not subtasks: # atomic task task.derived_completed = task.completed task.derived_size = 1 task.derived_atomic_task_count = 1 task.derived_has_open_tasks = task.open() assignee_identifier = task.assignee_identifier() if assignee_identifier: index.assignees = [assignee_identifier] if not DEV_SERVER: # Uses a multi entity group transaction to get the name # of the assignee. This is cached in the record for # quick descriptions. assignee = api.get_user(assignee_identifier) name = assignee.name if assignee else "<Missing>" else: name = "temp" task.derived_assignees[task.assignee_identifier()] = { "id": task.assignee_identifier(), "name": name, "completed": int(task.is_completed()), "all": 1, } else: # composite task task.derived_completed = all(t.is_completed() for t in subtasks) task.derived_size = 1 + sum(t.derived_size for t in subtasks) task.derived_atomic_task_count = sum(t.atomic_task_count() for t in subtasks) task.derived_has_open_tasks = any(t.has_open_tasks() for t in subtasks) # Compute derived assignees, and sum the total of all # their assigned and completed subtasks. assignees = {} for subtask in subtasks: subtask_assignees = subtask.derived_assignees for id, record in subtask_assignees.iteritems(): if not id in assignees: assignees[id] = {"id": id, "name": record["name"], "completed": 0, "all": 0} assignees[id]["completed"] += record["completed"] assignees[id]["all"] += record["all"] task.derived_assignees = assignees index.assignees = list(assignees.iterkeys()) task.put() index.completed = task.is_completed() index.has_open_tasks = task.has_open_tasks() index.atomic = task.atomic() index.put() # Propagate further upwards if task.parent_task_identifier(): UpdateTaskCompletion.enqueue(domain_identifier, task.parent_task_identifier(), transactional=True)
def txn(): # Returns (task, changed) tuple, where changed is set if # the task index was updated. task = api.get_task(domain_identifier, task_identifier) if not task: logging.error("Task '%s/%s' does not exist", domain_identifier, task_identifier) return None, False index = TaskIndex.get_by_key_name(task_identifier, parent=task) new_index = False if not index: index = TaskIndex(parent=task, key_name=task_identifier, hierarchy=[], level=0) new_index = True parent_identifier = task.parent_task_identifier() parent_hierarchy = [] if parent_identifier: parent_key = task.parent_task_key() parent_index = TaskIndex.get_by_key_name(parent_identifier, parent=parent_key) if not parent_index: logging.error("Missing index for parent task '%s/%s'", domain_identifier, parent_identifier) self.error(500) # Retry return None, False parent_hierarchy = parent_index.hierarchy hierarchy = parent_hierarchy if parent_identifier: hierarchy.append(parent_identifier) if (force_update or new_index or set(index.hierarchy) ^ set(hierarchy)): index.hierarchy = hierarchy index.level = len(hierarchy) index.put() return task, True return task, False
def txn(): task = api.get_task(domain_identifier, task_identifier) if not task: logging.error("Task '%s/%s' does not exist", domain_identifier, task_identifier) return index = TaskIndex.get_by_key_name(task_identifier, parent=task) if not index: index = TaskIndex(parent=task, key_name=task_identifier) # Get all subtasks. The ancestor queries are strongly # consistent, so when propagating upwards through the # hierarchy the changes are reflected. subtasks = list(Task.all().ancestor(domain_key).filter( 'parent_task =', task.key())) if not subtasks: # atomic task task.derived_completed = task.completed task.derived_size = 1 task.derived_atomic_task_count = 1 task.derived_has_open_tasks = task.open() assignee_identifier = task.assignee_identifier() if assignee_identifier: index.assignees = [assignee_identifier] if not DEV_SERVER: # Uses a multi entity group transaction to get the name # of the assignee. This is cached in the record for # quick descriptions. assignee = api.get_user(assignee_identifier) name = assignee.name if assignee else '<Missing>' else: name = 'temp' task.derived_assignees[task.assignee_identifier()] = { 'id': task.assignee_identifier(), 'name': name, 'completed': int(task.is_completed()), 'all': 1 } else: # composite task task.derived_completed = all(t.is_completed() for t in subtasks) task.derived_size = 1 + sum(t.derived_size for t in subtasks) task.derived_atomic_task_count = sum(t.atomic_task_count() for t in subtasks) task.derived_has_open_tasks = any(t.has_open_tasks() for t in subtasks) # Compute derived assignees, and sum the total of all # their assigned and completed subtasks. assignees = {} for subtask in subtasks: subtask_assignees = subtask.derived_assignees for id, record in subtask_assignees.iteritems(): if not id in assignees: assignees[id] = { 'id': id, 'name': record['name'], 'completed': 0, 'all': 0 } assignees[id]['completed'] += record['completed'] assignees[id]['all'] += record['all'] task.derived_assignees = assignees index.assignees = list(assignees.iterkeys()) task.put() index.completed = task.is_completed() index.has_open_tasks = task.has_open_tasks() index.atomic = task.atomic() index.put() # Propagate further upwards if task.parent_task_identifier(): UpdateTaskCompletion.enqueue(domain_identifier, task.parent_task_identifier(), transactional=True)