Go Deadline Propagation with Context
This challenge focuses on implementing deadline propagation within a Go application using context.Context. You'll build a system where a primary operation can set a deadline, and any subsequent operations initiated by it will inherit and respect this deadline. This is crucial for managing timeouts in distributed systems or complex workflows, ensuring that operations don't run indefinitely.
Problem Description
You are tasked with building a system that simulates a task with sub-tasks. The main task has a configurable deadline. This deadline needs to be propagated to all its sub-tasks. If any sub-task takes longer than the remaining time available from the parent's deadline, it should be canceled gracefully. You will need to implement a mechanism to achieve this deadline propagation and cancellation.
Key Requirements:
- A
Taskstruct that can initiate and manage sub-tasks. - The
Taskshould accept acontext.Contextwith a deadline. - When a
Taskstarts a sub-task, it must create a newcontext.Contextfor the sub-task. This new context should be derived from the parent task's context and have its own deadline set based on the remaining time of the parent's context. - Sub-tasks should be designed to respect their context's cancellation signal.
- The main
Taskshould be able to report whether it was completed successfully or canceled due to a deadline.
Expected Behavior:
- If the main task and all its sub-tasks complete within their respective deadlines, the task should be marked as successful.
- If the main task's deadline is reached before it completes, or if any sub-task's deadline is reached, the entire task (including any ongoing sub-tasks) should be canceled.
- The cancellation should be handled gracefully, allowing sub-tasks to clean up resources if necessary.
Edge Cases:
- A very short deadline for the main task.
- Sub-tasks that take a significant amount of time.
- A scenario where a sub-task finishes just before its deadline.
- Zero duration deadlines.
Examples
Example 1:
Input:
Main Task Duration: 100ms
Sub-Task 1 Duration: 50ms
Sub-Task 2 Duration: 30ms
Main Task Deadline: 200ms
Output:
Task Completed Successfully.
Sub-task 1 finished.
Sub-task 2 finished.
Explanation: The main task has a deadline of 200ms. Sub-task 1 takes 50ms, and Sub-task 2 takes 30ms. Both complete well within the main task's deadline and their propagated deadlines.
Example 2:
Input:
Main Task Duration: 100ms
Sub-Task 1 Duration: 150ms
Sub-Task 2 Duration: 30ms
Main Task Deadline: 200ms
Output:
Task Canceled: context deadline exceeded
Sub-task 1 started...
Sub-task 1 canceled: context deadline exceeded
Sub-task 2 finished.
Explanation: The main task has a deadline of 200ms. Sub-task 1 is set to take 150ms. Even though the main task's deadline is 200ms, Sub-task 1's propagated deadline might be shorter. If Sub-task 1's processing time exceeds its own deadline (derived from the parent's remaining time), it will be canceled. In this specific scenario, if Sub-task 1 begins and its execution time (150ms) plus the time already elapsed for the parent task exceeds the parent's deadline, it will be canceled. The output suggests that Sub-task 1 might have started, but then the parent context was canceled.
Example 3:
Input:
Main Task Duration: 100ms
Sub-Task 1 Duration: 50ms
Sub-Task 2 Duration: 30ms
Main Task Deadline: 70ms
Output:
Task Canceled: context deadline exceeded
Sub-task 1 finished.
Sub-task 2 finished.
Explanation: The main task has a deadline of 70ms. Sub-task 1 finishes in 50ms. Sub-task 2 starts and finishes in 30ms. However, the total time taken by the main task (including its sub-tasks) might exceed 70ms, or the propagation of the deadline might cause a sub-task to be canceled if it cannot complete within the remaining time available from the parent. In this case, the main task itself (or one of its critical paths) exceeds 70ms, leading to cancellation.
Constraints
- The main task and sub-tasks will be simulated using
time.Sleep. - The durations for tasks and deadlines will be in milliseconds.
- The implementation should aim for clear and idiomatic Go code.
- Avoid using external libraries for context management beyond the standard library.
- The total execution time of the solution should be reasonable, avoiding excessive resource consumption.
Notes
- The
context.WithDeadlinefunction is your friend here. Remember to consider how to calculate the new deadline for child contexts. - Error handling for context cancellation is crucial. Look for
context.Canceledorcontext.DeadlineExceeded. - Think about how to pass information back from sub-tasks to the main task, especially regarding their completion status or cancellation.
- The
selectstatement is often useful when waiting on multiple context cancellations or channel operations.