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 #48

Merged
merged 5 commits into from
Sep 3, 2023
Merged

Refactor #48

merged 5 commits into from
Sep 3, 2023

Conversation

WillNilges
Copy link
Collaborator

Thanks Andrew

I got the thing running... It was trying to infinitely start up workers when I used meshdb:wsgi, but it is my understanding that app.run() is not recommended for production, actually.

So, referring to this: https://flask.palletsprojects.com/en/2.3.x/deploying/gunicorn/, I changed the ENTRYPOINT of the Dockerfile. I did have to move the database initialization into create_app, but it is my understanding that it's fine, since it's within the create_app() function? Either way, please scrutinize this because I demonstrably have no idea what I am doing.

Oh, I also got the docker compose working again.

Copy link
Collaborator

@andybaumgar andybaumgar left a comment

Choose a reason for hiding this comment

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

Thanks for bringing this all together! I added some comments (mostly things I remembered from last nights discussion).

image: docker.io/postgres:latest
environment:
POSTGRES_DB: ${DB_NAME}
POSTGRES_USER: ${DB_USER}
POSTGRES_PASSWORD: ${DB_PASSWORD}
start_period: 3s
healthcheck:
Copy link
Collaborator

Choose a reason for hiding this comment

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

Awesome that you got this working! Was it just a syntax thing?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Thanks :) I actually ended up switching to docker-compose 😅

Copy link
Collaborator

Choose a reason for hiding this comment

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

Ugh, I hope this wasn't all caused by trusting ChatGPT that damn old timer!

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Nah I was trying to get act working which required docker, so I installed docker, and then when I came back to this I was like "wait a second why am I suffering" and tried it and it Just Worked. Like it or not, Docker's tooling is way more mature than podman's >:[


from sqlalchemy import create_engine
from ..db.database import create_db_engine


def setup_db():
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should we maybe call this initialize_db or something to signify it normally only needs to happen once?

meshdb/views.py Outdated
Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe we should rename this "routes.py" since we are not serving any interface views?

user_datastore = SQLAlchemyUserDatastore(db, authmodels.User, authmodels.Role)
app.security = Security(app, user_datastore)

# test code to create user
Copy link
Collaborator

Choose a reason for hiding this comment

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

Not caught up on what this is doing, but should we put the testing code in a different file? In normal operation it seems like this step will not be necessary?

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 Question. We could probably break that out into its own test. I think Quincy just left that in there to make it easier to ensure the thing was working properly, for now.

app.config["WTF_CSRF_ENABLED"] = False

# Configure Database
from meshdb.db.setup import setup_db
Copy link
Collaborator

Choose a reason for hiding this comment

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

Was this related to the circular import? Should we move it to the top?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I dunno. We could move it to the top and I doubt anything would change, but that feels clearer to me for whatever reason. If we do, however, then maybe we should also move the security imports?


db.init_app(app)

import meshdb.auth.authmodels as authmodels
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Should this be moved to the top as well?

@WillNilges
Copy link
Collaborator Author

WillNilges commented Sep 2, 2023

This is good, but I don't think that our database structure is quite right yet. It seems odd that we have to create multiple database engines in different places, and I'm also not super solid on what db.init_app() is doing. Then there's also the whole initialize_db() business, which seems "wrong" for lack of a better word. It's Python, and there's a lot of ways to skin a cat in Python, but I'm wondering if we should look into this more.

This answer intrigues me:
https://stackoverflow.com/a/13432373/6095682

Generally this concern is driven by my instinct that there should be one "database" object or whatever that gets passed around or referenced or whatever, and the API should be talking to that object. That, however, raises another issue: What pattern are we going for? Is that Object Oriented™? Is there a better pattern? Am I totally off-base here?

Have we considered using something like this: https://github.com/realpython/flask-boilerplate?
Or maybe this: https://github.com/abstractkitchen/flask-backbone?

@andybaumgar
Copy link
Collaborator

@WillNilges It looks like db.init_app() is not currently defined.

@WillNilges
Copy link
Collaborator Author

@WillNilges It looks like db.init_app() is not currently defined.

I'm pretty sure it's some kind of sqlalchemy thing. Remember Andrew's comments about the overloaded names?

Also, maybe it's like, fine that the API "owns" the db engine, just seems a little odd to me.

@andybaumgar
Copy link
Collaborator

@WillNilges. Those are interesting examples. It seems like it's more common to have all this init.py code in app.py.

@andybaumgar
Copy link
Collaborator

@WillNilges The second example does a weird thing and passes the DB config variables in through app. I don't like that for us since I think we want to separate the DB stuff from app for testing etc. So no change for us on that front.

@quoncc
Copy link
Collaborator

quoncc commented Sep 2, 2023

@andybaumgar the DB settings defined for the app is for auth, and the other one is for member data.

From what I can tell, unless we want to keep the auth tables in the same DB (I have no idea if this is best practice or not, I'll defer to you guys) we need to define two different DBs.

Open to different ways of doing it, just wanted to give background.

@andybaumgar
Copy link
Collaborator

@quoncc From some googling it looks like it's normal to use the same DB for everything.

@andybaumgar
Copy link
Collaborator

@quoncc I think we can split up these two lines:
user_datastore = SQLAlchemyUserDatastore(db, authmodels.User, authmodels.Role)
app.security = Security(app, user_datastore)

The user_datastore could go in the database initialization code, and the security could stay along with the other app code. That way all database setup is separate from app setup.

@quoncc
Copy link
Collaborator

quoncc commented Sep 2, 2023

Alright, if keeping auth data in the same DB is a normal practice, I have an idea.

We can get rid of the non flask-sqlalchemy database engine, and move all of the models into the db engine that auth is using.

This should simplify everything greatly and I probably should've done it from the get-go. Only thing is we need to make sure we're able to call the DB before we initialize the app.

@quoncc
Copy link
Collaborator

quoncc commented Sep 2, 2023

Just did some reading, we can create models before initializing the app, but db.session can't be called without an active application context.

Maybe this limitation is OK, but for unit testing the DB we'd need the app to be active as well. I'll defer to you guys.

@andybaumgar
Copy link
Collaborator

@quoncc Thanks for researching that. I think that's a fine limitation. Creating a user seems like an "app" thing meaning that it requires logic beyond just database reads and writes.

@andybaumgar
Copy link
Collaborator

I'm a little worried about the number of different packages that are required in the Flask ecosystem. I wonder if we can find an example of an app that implements everything we are doing. It seems like our use case is pretty standard.

@quoncc
Copy link
Collaborator

quoncc commented Sep 2, 2023

I mean, this is a pretty standard stack, I feel like we're in a good middle ground with customization vs simplicity. I don't really feel the need to find a more drilled down library.

@quoncc
Copy link
Collaborator

quoncc commented Sep 2, 2023

Anyways, I'm approving this PR. Once this gets merged I can work towards collapsing the DBs to one engine.

Hopefully when that's done we can start actually writing some endpoints

Copy link
Collaborator

@quoncc quoncc 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 good, once this is merged let's combine the DB engines

@andybaumgar
Copy link
Collaborator

andybaumgar commented Sep 2, 2023

@quoncc I agree it could be good to break down this large PR into a smaller one, but I think we should align on some bigger picture Flask ideas before we refactor too much. It seems like the "app factory" pattern is important for a number of libraries. For example it seems like the migrations system relies on that. I think we should try to understand all the best practices before we write too much code.

Does the current PR run? I think we still have the db naming conflict (both a module and an object)?

@WillNilges
Copy link
Collaborator Author

Yeah, it totally runs. The overload is still there, but there's gotta be a way to get rid of that

@WillNilges
Copy link
Collaborator Author

I am tempted to copy pasta one of these standard boiler plate repos because why reinvent the wheel

@WillNilges
Copy link
Collaborator Author

Merging this re: the convo we had at the gym

@WillNilges WillNilges merged commit 294fa69 into main Sep 3, 2023
1 check passed
@Andrew-Dickinson Andrew-Dickinson deleted the refactor branch July 27, 2024 17:11
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.

4 participants