Skip to content

I17 add listener#18

Open
eyvorchuk wants to merge 26 commits intomasterfrom
i17-add-listener
Open

I17 add listener#18
eyvorchuk wants to merge 26 commits intomasterfrom
i17-add-listener

Conversation

@eyvorchuk
Copy link
Copy Markdown

This PR resolves #17. At the start of the convolution process, a thread is created to instantiate a Listener that sends the timestamp being read during the process to connecting clients. This thread is terminated after all the timestamps have been read. This functionality is primarily for assisting with the progress bar for the osprey-flask-app.

Copy link
Copy Markdown

@jameshiebert jameshiebert left a comment

Choose a reason for hiding this comment

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

Looks pretty straightforward and easy to understand which is good! I'm glad that the solution didn't turn out to be much more complicated than this. I have a few minor concerns and bigger concerns about the blocking I/O, but I also don't want that to derail us for too long. If you can try to do it with async, that'd be good, but if it takes took long to figure it out, I'm willing to accept this way.

Comment thread rvic/core/read_forcing.py
listener._listener._socket.settimeout(0.5) # Ensure that listener is not always waiting for connection in case there is no Client
while not event.is_set():
try:
with listener.accept() as conn:
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I believe that this uses blocking I/O which is non-ideal. Most of the time, it's going to be sitting there doing nothing, blocking execution of anything else. Now, maybe that doesn't matter if it's running in a thread? I'm not sure. But if it's possible to write this using cooperative multitasking (like with Python's await keyword), that might be better. See: https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.run_in_executor

Comment thread rvic/core/read_forcing.py Outdated
# -------------------------------------------------------------------- #
# create Listener to send timestamp information to connecting Client
def send_timestamp(timestamp, event):
address = ("0.0.0.0", 5005)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Would we have any concerns about potential DOS attacks on this?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Would a possible way to account for this be to create a docker network with just the osprey and osprey-flask-app containers? Or check that the address returned in listener.accept() is the IP address of the osprey-flask-app container?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Yes, having the two containers on their own network would mitigate the risk of a DOS attack. Aside from that, it's generally a good practice to make the listening address and port to be run time parameters (probably with address defaulting to localhost/127.0.0.1), so that admins have some flexibility in how they deploy the service.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I put the two containers in their own network.

Comment thread setup.py Outdated
"matplotlib >= 1.3.1",
"pandas >= 1.0",
],
install_requires=[req.strip() for req in open("requirements.txt")],
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

We're trying to move away from using setup.py in favour of pyproject.toml. A precondition of that is not having dynamic content in setup.py (ask @rod-glover about his most recent work in pycds). As such, it would be better to not add any dynamic content here.

Comment thread rvic/convolution.py Outdated
Comment on lines +69 to +70
event.set()
listener_thread.join()
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Should these be executed in the finally block? I.e. I think that we want them to run always, and as written here, they won't if some exception is raised by convolution_run. Speaking of which... why is there no except block corresponding to the try. Will this code will silently fail?

Copy link
Copy Markdown

@jameshiebert jameshiebert left a comment

Choose a reason for hiding this comment

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

Looks much better. Just a couple of things to tidy up :)

Comment thread rvic/convert.py
Comment thread rvic/convolution.py Outdated
# ---------------------------------------------------------------- #

except BaseException as e:
log.error(e, exc_info=True)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

You could probably use log.exception here.

Comment thread rvic/convolution.py
log.error(e, exc_info=True)
raise(e)
finally:
if event:
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Much better.

Comment thread rvic/parameters.py
gen_uh_final(outlets, dom_data, config_dict, directories)
# ---------------------------------------------------------------- #

except BaseException as e:
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Again, I think that this is essentially a no-op. Can you explain the value-add here?

@eyvorchuk
Copy link
Copy Markdown
Author

This PR has been updated to get the listener port as a configuration option instead of an environment variable. This is because osprey-flask-app passes the next available port not used by a job as a parameter to osprey to here. This also updates the Python versions in the CI and updates package versions accordingly.

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.

Add Listener to send timestamp to Client

2 participants