Repository: PrefectHQ/prefect

Issue:
duration parameter is not taken into account from task_pause
## Description
<!-- A clear description of the bug -->
`duration` parameter in `prefect.utilities.tasks.pause_task` seems to be ignored. Based on documentation, if `duration` is specified, then, the task should be resumed after a period of time



## Expected Behavior
<!-- What did you expect to happen instead? -->
Resume task run after specified period of time.



## Reproduction
<!-- A minimal example that exhibits the behavior. -->
```
import datetime

from prefect import Flow, task
from prefect.utilities.tasks import pause_task


@task
def say_hello():
    pause_task("wait or approve..", datetime.timedelta(seconds=10))
    print('hello')


with Flow("My Flow") as f:
    say_hello()
```

When I executed this flow from the UI, I noticed that the task stays paused for ever (well, for 10 years :P )

![image](https://user-images.githubusercontent.com/8322266/105976777-42170600-6099-11eb-8cff-b4bcab172657.png)

**NOTE**: Every time the duration time is reached, the task's state changes like: Paused -> Resumed -> Paused.

## Environment
<!-- Any additional information about your environment

Optionally run `prefect diagnostics` from the command line and paste the information here. -->
```
{
  "config_overrides": {},
  "env_vars": [
    "PREFECT__CONTEXT__SECRETS__XXxx",
    "PREFECT__CONTEXT__SECRETS__XXxx"
  ],
  "system_information": {
    "platform": "Linux-5.8.0-7630-generic-x86_64-with-debian-bullseye-sid",
    "prefect_backend": "server",
    "prefect_version": "0.14.4",
    "python_version": "3.7.9"
  }
}
```



Discussion:
I think this may be a bug in the Server scheduler ignoring Paused states - perhaps we should move the issue to that repo
@jlowin Is there any way to move it automatically or I should close this and open a new one?
All set @sp1thas :) Sorry should have specified the maintainers need to do that.
@sp1thas can you clarify: does the task run stay in a `Paused` state for forever, or does it cycle `Paused` -> `Resume` -> `Paused` each time the duration has passed?
@cicdw it cycle. Task run remains in `Resume` state for less than a second.
Thanks for the clarification - this sounds like a Core issue not a Server issue; one final question @sp1thas : does the task run specifically ever enter a `Submitted` state, or some other state in between `Resume` -> `Paused`?
@cicdw well I just noticed that the task run is cycle like: `Paused` -> `Submitted` -> `Running` -> `Paused`. I'm sorry for the initial misleading comment :( 

![image](https://user-images.githubusercontent.com/8322266/106099896-1866e900-6144-11eb-8734-da9103ade753.png)

No worries this is very helpful!  I know what's going on now, I'm going to transfer this issue back to the Core repo

Resolving patch:
diff --git a/src/prefect/engine/task_runner.py b/src/prefect/engine/task_runner.py
--- a/src/prefect/engine/task_runner.py
+++ b/src/prefect/engine/task_runner.py
@@ -25,6 +25,7 @@
     Failed,
     Looped,
     Mapped,
+    Paused,
     Pending,
     Resume,
     Retrying,
@@ -141,7 +142,13 @@ def initialize_run(  # type: ignore
         else:
             run_count = state.context.get("task_run_count", 1)
 
-        if isinstance(state, Resume):
+        # detect if currently Paused with a recent start_time
+        should_resume = (
+            isinstance(state, Paused)
+            and state.start_time
+            and state.start_time <= pendulum.now("utc")  # type: ignore
+        )
+        if isinstance(state, Resume) or should_resume:
             context.update(resume=True)
 
         if "_loop_count" in state.context:


Test patch:
diff --git a/tests/engine/test_task_runner.py b/tests/engine/test_task_runner.py
--- a/tests/engine/test_task_runner.py
+++ b/tests/engine/test_task_runner.py
@@ -429,6 +429,23 @@ def test_task_runner_puts_resume_in_context_if_state_is_resume(self):
             result = TaskRunner(Task()).initialize_run(state=Resume(), context=ctx)
             assert result.context.resume is True
 
+    def test_task_runner_puts_resume_in_context_if_paused_start_time_elapsed(self):
+        with prefect.context() as ctx:
+            assert "resume" not in ctx
+            result = TaskRunner(Task()).initialize_run(
+                state=Paused(start_time=pendulum.now("utc")), context=ctx
+            )
+            assert result.context.resume is True
+
+    def test_task_runner_ignores_resume_in_context_if_paused_start_time_in_future(self):
+        with prefect.context() as ctx:
+            assert "resume" not in ctx
+            result = TaskRunner(Task()).initialize_run(
+                state=Paused(start_time=pendulum.now("utc").add(seconds=10)),
+                context=ctx,
+            )
+            assert "resume" not in ctx
+
     def test_task_runner_puts_checkpointing_in_context(self):
         with prefect.context() as ctx:
             assert "checkpointing" not in ctx