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

Refactor photometry handler #2648

Merged
merged 14 commits into from
Feb 11, 2022
Merged

Conversation

mcoughlin
Copy link
Contributor

This PR refactors the photometry handler to enable posting from a different API (useful for the ATLAS and PS1 PRs).

@mcoughlin
Copy link
Contributor Author

@profjsb It looks crazy pants, but this is just removing the 4 space indent for most of the functions at the start of the photometry handler and calling them directly.

Fix test: test_sources.py::test_sources_include_detection_stats.
Copy link
Collaborator

@profjsb profjsb left a comment

Choose a reason for hiding this comment

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

This looks great but I'm still worried about the LOCKs. Looking at https://stackoverflow.com/a/47256217 it seems to make sense for us to put those LOCK lines inside a try statement then in the except make sure we do a DBSession.rollback() to make sure we release the lock.

Comment on lines +182 to +184
if "altdata" in data and not data["altdata"]:
del data["altdata"]
if "altdata" in data:
Copy link
Collaborator

Choose a reason for hiding this comment

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

I dont see how line 184 ever evaluates to True given the lines above.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

a = []
assert not a

So checks for empty list?

@mcoughlin
Copy link
Contributor Author

@profjsb So basically

DBSession().execute(
    f'LOCK TABLE {Photometry.__tablename__} IN SHARE ROW EXCLUSIVE MODE'
)
try:
    ids, upload_id = insert_new_photometry_data(
        df, instrument_cache, group_ids, stream_ids, user
    )
except ValidationError as e:
    return log(f"Unable to post photometry: {e}")

=>
try:
DBSession().execute(
f'LOCK TABLE {Photometry.tablename} IN SHARE ROW EXCLUSIVE MODE'
)
ids, upload_id = insert_new_photometry_data(
df, instrument_cache, group_ids, stream_ids, user
)
except Exception as e:
DBSession.rollback()
return log(f"Unable to post photometry: {e}")

@stefanv
Copy link
Collaborator

stefanv commented Feb 9, 2022

At minimum, the lock would need to be wrapped in a try: ... finally: ... clause. But if the app gets brought down, the lock could end up hanging around.

I believe we have duplication checks on the DB level, so another option is to just do the check, try the insert, and catch the error if it fails?

@mcoughlin
Copy link
Contributor Author

@stefanv Can you help me understand how your second option is different from above?

@stefanv
Copy link
Collaborator

stefanv commented Feb 10, 2022

@mcoughlin I looked at your snippet again and I think the except catch-all is fine; sorry for any confusion. Just use either DBSession() or DBSession, but not both.

As an aside, we are now able to use the new SQLAlchemy syntax:

with DBSession() as session: ...

@mcoughlin
Copy link
Contributor Author

@stefanv can you see if you are happier with this? I put your try except and with DBSession() as session around the LOCK bits.

Copy link
Collaborator

@stefanv stefanv left a comment

Choose a reason for hiding this comment

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

Thanks @mcoughlin! Looks good. There's just that one docstring left hanging, and a question re: multiple types of session objects.


def add_external_photometry(json, user):
"""
---
Copy link
Collaborator

Choose a reason for hiding this comment

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

This docstring seems to be misplaced

Copy link
Contributor Author

Choose a reason for hiding this comment

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

what does that mean?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah I see, because now we just return the log()

Copy link
Collaborator

Choose a reason for hiding this comment

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

Well, it looks like a handler (GET, POST, PUT, etc.) docstring in YAML, whereas I would expect a standard Python function docstring that describes the two arguments: json and user.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah yes, hopefully more clear now?

@@ -43,6 +45,10 @@
_, cfg = load_env()


log = make_log('api/photometry')
Session = scoped_session(sessionmaker(bind=DBSession.session_factory.kw["bind"]))
Copy link
Collaborator

Choose a reason for hiding this comment

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

Still used? Do we need both DBSession and Session?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have usually seen us using DBSession() in the APIs and Session when called external to the APIs (like when we do the IOSync stuff).

)
except Exception as e:
session.rollback()
return log(f"Unable to post photometry: {e}")
Copy link
Collaborator

Choose a reason for hiding this comment

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

Log does not return anything

skyportal/handlers/api/photometry.py Outdated Show resolved Hide resolved
mcoughlin and others added 2 commits February 10, 2022 16:24
Co-authored-by: Stefan van der Walt <sjvdwalt@gmail.com>
Co-authored-by: Stefan van der Walt <sjvdwalt@gmail.com>
@mcoughlin
Copy link
Contributor Author

@profjsb please merge if comfortable with this now.

Copy link
Collaborator

@profjsb profjsb left a comment

Choose a reason for hiding this comment

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

Looks great. We should make another issue to look into why we get 400 and 500 sometimes (not suppose to happen).

@@ -2258,7 +2263,7 @@ def test_problematic_photometry_1276(
data=payload,
token=super_admin_token,
)
assert status in [401, 500]
assert status in [400, 500]
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why is 400 getting returned anywhere? It's worth understanding this

Copy link
Collaborator

Choose a reason for hiding this comment

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

HTTP 500 is internal server error. BAD.

Copy link
Collaborator

Choose a reason for hiding this comment

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

This is something that should be investigated by scouring those logs.

@profjsb profjsb merged commit c927b44 into skyportal:master Feb 11, 2022
@mcoughlin mcoughlin deleted the photometry_handler branch August 30, 2022 14:18
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.

None yet

3 participants