2022-06-30 20:43:04 +00:00
|
|
|
from unittest.mock import MagicMock
|
|
|
|
|
2023-02-01 11:07:00 +00:00
|
|
|
from lightning.app.storage.orchestrator import StorageOrchestrator
|
|
|
|
from lightning.app.storage.requests import _GetRequest, _GetResponse
|
|
|
|
from lightning.app.testing.helpers import _MockQueue
|
|
|
|
from lightning.app.utilities.enum import WorkStageStatus
|
2022-06-30 20:43:04 +00:00
|
|
|
|
|
|
|
|
|
|
|
def test_orchestrator():
|
|
|
|
"""Simulate orchestration when Work B requests a file from Work A."""
|
2022-10-28 13:57:35 +00:00
|
|
|
request_queues = {"work_a": _MockQueue(), "work_b": _MockQueue()}
|
|
|
|
response_queues = {"work_a": _MockQueue(), "work_b": _MockQueue()}
|
|
|
|
copy_request_queues = {"work_a": _MockQueue(), "work_b": _MockQueue()}
|
|
|
|
copy_response_queues = {"work_a": _MockQueue(), "work_b": _MockQueue()}
|
2022-06-30 20:43:04 +00:00
|
|
|
app = MagicMock()
|
|
|
|
work = MagicMock()
|
|
|
|
work.status.stage = WorkStageStatus.RUNNING
|
|
|
|
app.get_component_by_name = MagicMock(return_value=work)
|
|
|
|
|
|
|
|
orchestrator = StorageOrchestrator(
|
|
|
|
app,
|
|
|
|
request_queues=request_queues,
|
|
|
|
response_queues=response_queues,
|
|
|
|
copy_request_queues=copy_request_queues,
|
|
|
|
copy_response_queues=copy_response_queues,
|
|
|
|
)
|
|
|
|
|
|
|
|
# test idle behavior when queues are empty
|
|
|
|
orchestrator.run_once("work_a")
|
|
|
|
orchestrator.run_once("work_b")
|
|
|
|
assert not orchestrator.waiting_for_response
|
|
|
|
|
|
|
|
# simulate Work B sending a request for a file in Work A
|
2022-10-28 13:57:35 +00:00
|
|
|
request = _GetRequest(source="work_a", path="/a/b/c.txt", hash="", destination="", name="")
|
2022-06-30 20:43:04 +00:00
|
|
|
request_queues["work_b"].put(request)
|
|
|
|
orchestrator.run_once("work_a")
|
|
|
|
assert not orchestrator.waiting_for_response
|
|
|
|
orchestrator.run_once("work_b")
|
|
|
|
|
|
|
|
# orchestrator is now waiting for a response for copier in Work A
|
|
|
|
assert "work_b" in orchestrator.waiting_for_response
|
2022-12-19 14:10:58 +00:00
|
|
|
assert len(request_queues["work_a"]) == 0
|
2022-06-30 20:43:04 +00:00
|
|
|
assert request in copy_request_queues["work_a"]
|
|
|
|
assert request.destination == "work_b"
|
|
|
|
|
|
|
|
# simulate loop while waiting for new elements in the queues
|
|
|
|
orchestrator.run_once("work_a")
|
|
|
|
orchestrator.run_once("work_b")
|
|
|
|
|
|
|
|
# simulate copier A confirms that the file is available on the shared volume
|
2022-10-28 13:57:35 +00:00
|
|
|
response = _GetResponse(source="work_a", path="/a/b/c.txt", hash="", destination="work_b", name="")
|
2022-06-30 20:43:04 +00:00
|
|
|
copy_request_queues["work_a"].get()
|
|
|
|
copy_response_queues["work_a"].put(response)
|
|
|
|
|
|
|
|
# orchestrator processes confirmation and confirms to the pending request from Work B
|
|
|
|
orchestrator.run_once("work_a")
|
2022-12-19 14:10:58 +00:00
|
|
|
assert len(copy_response_queues["work_a"]) == 0
|
2022-06-30 20:43:04 +00:00
|
|
|
assert response in response_queues["work_b"]
|
|
|
|
assert not orchestrator.waiting_for_response
|
|
|
|
orchestrator.run_once("work_b")
|
|
|
|
|
|
|
|
# simulate loop while waiting for new elements in the queues
|
|
|
|
orchestrator.run_once("work_a")
|
|
|
|
orchestrator.run_once("work_b")
|
|
|
|
assert not orchestrator.waiting_for_response
|
|
|
|
|
|
|
|
# simulate Work B receiving the confirmation that the file was copied
|
|
|
|
response = response_queues["work_b"].get()
|
|
|
|
assert response.source == "work_a"
|
|
|
|
assert response.destination == "work_b"
|
|
|
|
assert response.exception is None
|
|
|
|
|
|
|
|
# all queues should be empty
|
2022-12-19 14:10:58 +00:00
|
|
|
assert all(len(queue) == 0 for queue in request_queues.values())
|
|
|
|
assert all(len(queue) == 0 for queue in response_queues.values())
|
|
|
|
assert all(len(queue) == 0 for queue in copy_request_queues.values())
|
|
|
|
assert all(len(queue) == 0 for queue in copy_response_queues.values())
|