Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Non blocking reads from process output #105

Merged
merged 5 commits into from
Feb 8, 2021
Merged

Non blocking reads from process output #105

merged 5 commits into from
Feb 8, 2021

Conversation

jenhagg
Copy link
Collaborator

@jenhagg jenhagg commented Feb 2, 2021

Purpose

The api call that launches a simulation works by creating a process with Popen and returning a json response that includes stdout/stderr. This content is updated each time the status endpoint is called by reading from the standard streams. Problem is the current way it's done blocks until the process is complete, which is typically a long time and not a good experience.

What it does

Makes it so the http call returns immediately, by moving the blocking call to a separate thread, and using a thread safe queue to buffer output between that and the request thread. This way any call to either launch or check on a simulation will return the stdout/stderr even if the simulation is still running.

Testing

I had to fix the tests after refactoring, which ended up being good since now we are not using any fakes, so the tests are running the actual code. Since concurrency is involved, it's not totally clear how reliable this is, but the tests are simple enough that it seems to be stable.

Time to review

10-30 mins

@jenhagg jenhagg requested review from ahurli and ToddG February 2, 2021 00:15
@jenhagg jenhagg self-assigned this Feb 2, 2021
@jenhagg jenhagg added this to the Hey Joe milestone Feb 2, 2021
Copy link

@ToddG ToddG left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like a great use case. I have just a few minor questions. Feel free to address or not.

pyreisejl/utility/state.py Outdated Show resolved Hide resolved
result = []
try:
while True:
line = self.queue.get_nowait()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From: https://docs.python.org/3/library/queue.html#queue.Queue.get_nowait

"""
exception queue.Empty

Exception raised when non-blocking get() (or get_nowait()) is called on a Queue object which is empty.

"""
Seems to indicate that this call could raise an exception... do you want to catch and ignore here or annotate your docstring to indicate this could be raised?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just making sure, does the except block below already do this?

pyreisejl/utility/state.py Outdated Show resolved Hide resolved

def __init__(self, stream):
self.stream = stream
self.queue = Queue()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unbounded Queue leaves you vulnerable to OOM issues. Would it be better to limit and throw an exception when out of bounds, or shed oldest entries?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, not sure how much of an issue it is but I will make a note to revisit this. For context, the size of the streams is much smaller than the output data, which is most likely to cause OOM issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants