-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: exit gracefully on SIGTERM, timeout, and cancellation
* Listen for SIGTERM. Trigger `on_terminated` and `on_failure` hooks and exit. * Wait for cancellation signal on Redis and trigger `on_cancelled` and `on_failure` hooks. * Log message and exit (0) when a job ID can't be pulled from Redis in a set timeout. All this early exits allow the workflow to clean-up after itself using hooks. Status updates are pushed for each of the states. This should prevent hanging jobs that have been cancelled by a user or terminated by K8S.
- Loading branch information
Showing
15 changed files
with
268 additions
and
116 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,8 @@ | ||
FROM virtool/workflow-tools:1.0.0 | ||
WORKDIR /test | ||
|
||
RUN pip install poetry | ||
|
||
COPY ./pyproject.toml . | ||
COPY ./poetry.lock . | ||
RUN poetry install --no-root | ||
|
||
COPY . . | ||
|
||
ENTRYPOINT ["poetry", "run", "pytest"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,4 +13,3 @@ services: | |
- ./coverage:/test/coverage | ||
- /var/run/docker.sock:/var/run/docker.sock | ||
network_mode: "host" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import asyncio | ||
|
||
from virtool_workflow import step | ||
|
||
|
||
@step | ||
async def waste_time(): | ||
for _ in range(10): | ||
await asyncio.sleep(1) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
import asyncio | ||
import subprocess | ||
|
||
import aioredis | ||
|
||
|
||
async def test_exit_because_timeout(db, create_job, exec_workflow, job_id): | ||
""" | ||
Test that the runner exits if no job ID can be pulled from Redis before the timeout. | ||
This situation does not involve a status update being sent to the server. | ||
""" | ||
p = subprocess.run( | ||
[ | ||
"poetry", | ||
"run", | ||
"run-workflow", | ||
"--workflow-file", | ||
"tests/files/terminated_workflow.py", | ||
"--redis-list-name", | ||
"jobs_termination", | ||
"--redis-connection-string", | ||
"redis://localhost:6379", | ||
"--timeout", | ||
"5", | ||
], | ||
capture_output=True, | ||
encoding="utf-8", | ||
) | ||
|
||
assert p.returncode == 0 | ||
assert "Waiting for a job for 5 seconds" in p.stderr | ||
assert "Timed out while waiting for job" in p.stderr | ||
|
||
|
||
async def test_exit_because_sigterm(db, create_job, exec_workflow, job_id, jobs_api): | ||
job = await create_job({}) | ||
|
||
redis_list_name = f"jobs_{job['workflow']}" | ||
|
||
redis = await aioredis.create_redis_pool("redis://localhost:6379") | ||
await redis.rpush(redis_list_name, job_id) | ||
redis.close() | ||
await redis.wait_closed() | ||
|
||
p = subprocess.Popen( | ||
[ | ||
"poetry", | ||
"run", | ||
"run-workflow", | ||
"--workflow-file", | ||
"tests/files/terminated_workflow.py", | ||
"--jobs-api-connection-string", | ||
jobs_api, | ||
"--redis-list-name", | ||
redis_list_name, | ||
"--redis-connection-string", | ||
"redis://localhost:6379", | ||
"--timeout", | ||
"5", | ||
] | ||
) | ||
|
||
await asyncio.sleep(10) | ||
|
||
p.terminate() | ||
p.wait() | ||
|
||
assert p.returncode == 124 | ||
|
||
document = await db.jobs.find_one() | ||
|
||
assert [(update["state"], update["progress"]) for update in document["status"]] == [ | ||
("waiting", 0), | ||
("preparing", 3), | ||
("running", 100), | ||
("terminated", 100), | ||
] | ||
|
||
|
||
async def test_exit_because_cancelled(db, create_job, exec_workflow, job_id, jobs_api): | ||
job = await create_job({}) | ||
|
||
redis_list_name = f"jobs_{job['workflow']}" | ||
|
||
redis = await aioredis.create_redis_pool("redis://localhost:6379") | ||
await redis.rpush(redis_list_name, job_id) | ||
|
||
p = subprocess.Popen( | ||
[ | ||
"poetry", | ||
"run", | ||
"run-workflow", | ||
"--workflow-file", | ||
"tests/files/terminated_workflow.py", | ||
"--jobs-api-connection-string", | ||
jobs_api, | ||
"--redis-list-name", | ||
redis_list_name, | ||
"--redis-connection-string", | ||
"redis://localhost:6379", | ||
"--timeout", | ||
"5", | ||
] | ||
) | ||
|
||
await asyncio.sleep(5) | ||
|
||
await redis.publish("channel:cancel", job_id) | ||
|
||
redis.close() | ||
await redis.wait_closed() | ||
|
||
p.wait(timeout=15) | ||
|
||
document = await db.jobs.find_one() | ||
|
||
assert [(update["state"], update["progress"]) for update in document["status"]] == [ | ||
("waiting", 0), | ||
("preparing", 3), | ||
("running", 100), | ||
("cancelled", 100), | ||
] |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.