Katkat

Build Task Management Through Records, Search, Assignment, and Completion

CoinbaseSoftware Engineer · Online Assessment

Last updated

Implement an in-memory task management system that tracks task lifecycles, assignments, and deadlines with efficient indexing and querying. Tests data structure design, state management, and multi-field sorting.

Problem Statement

Implement an in-memory task management system, TaskManager, that supports creating tasks, assigning them to users, marking them as completed, and querying pending or overdue tasks.

Each task has the following attributes:

  • task_id (string): Unique identifier for the task.
  • description (string): Short description of the task.
  • priority (integer): Higher integer denotes higher priority.
  • deadline (integer): Unix timestamp representing the task deadline.
  • status (string): Either "PENDING" or "COMPLETED".
  • assignee (string or None): User ID assigned to the task, or None if unassigned.

Implement the TaskManager class with the following methods:

  • create_task(task_id: str, description: str, priority: int, deadline: int) -> bool: Creates a new task with status "PENDING" and no assignee. Returns True if created successfully, or False if a task with task_id already exists.

  • assign_task(task_id: str, user_id: str) -> bool: Assigns the task with task_id to user_id. A task can be reassigned. Returns True if the task exists and is currently "PENDING". Returns False if the task does not exist or is already "COMPLETED".

  • complete_task(task_id: str) -> bool: Marks the task with task_id as "COMPLETED". Returns True if the task exists and was previously "PENDING". Returns False if the task does not exist or is already "COMPLETED".

  • get_user_tasks(user_id: str, sort_by: str) -> list[str]: Returns a list of task_ids currently assigned to user_id with "PENDING" status.

    • If sort_by == "priority", sort descending by priority. If priorities are equal, break ties by deadline ascending, then task_id ascending.
    • If sort_by == "deadline", sort ascending by deadline. If deadlines are equal, break ties by priority descending, then task_id ascending.
    • Returns an empty list if the user has no pending tasks.
  • get_overdue_tasks(current_time: int) -> list[str]: Returns a list of task_ids that are currently "PENDING" and have deadline < current_time, sorted ascending by deadline. If deadlines are equal, break ties by task_id ascending.

Example

tm = TaskManager()
tm.create_task("T1", "Audit logs", priority=2, deadline=100) # Returns True
tm.create_task("T2", "Fix bug", priority=5, deadline=50)     # Returns True
tm.create_task("T3", "Deploy", priority=2, deadline=80)      # Returns True

tm.assign_task("T1", "alice") # Returns True
tm.assign_task("T2", "alice") # Returns True
tm.assign_task("T3", "alice") # Returns True

# Sorted by priority descending: T2 (5), then T3 (2, deadline 80), then T1 (2, deadline 100)
tm.get_user_tasks("alice", "priority") # Returns ["T2", "T3", "T1"]

tm.complete_task("T2") # Returns True

# T2 is now COMPLETED, so it is excluded
tm.get_user_tasks("alice", "priority") # Returns ["T3", "T1"]

# At time 90, pending task T3 has deadline 80 (< 90)
tm.get_overdue_tasks(90) # Returns ["T3"]

Constraints

  • 1 <= len(task_id), len(user_id) <= 32 (alphanumeric strings)
  • 1 <= priority <= 10^5
  • 1 <= deadline, current_time <= 2 * 10^9
  • At most 20,000 total method calls.
  • sort_by is always either "priority" or "deadline".

Hints

Hint 1

Maintain a primary dictionary mapping `task_id` to its record object to support O(1) lookups and status updates.

Hint 2

Secondary indexes such as a map of `user_id -> set of task_id` can help avoid scanning all tasks when querying user tasks.

Hint 3

Be careful to update secondary indexes or filter out completed tasks when completing or reassigning tasks.

Follow-up questions

  • How would you optimize `get_overdue_tasks` if there are millions of tasks and frequent queries for overdue items?
  • How would you handle concurrent task updates in a multi-threaded or distributed environment?
  • If users could be assigned thousands of tasks, how would you support efficient pagination for `get_user_tasks`?