Skip to content

Commit

Permalink
remove sqlalchemy and use raw sql querries
Browse files Browse the repository at this point in the history
  • Loading branch information
ryan-lam committed Nov 4, 2023
1 parent d47c750 commit 62b12ad
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 246 deletions.
6 changes: 6 additions & 0 deletions location_service/.env.sample
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
DATABASE_URI="postgresql+psycopg2://user:password@host:port/database"
DB_HOST=""
DB_NAME=""
DB_USER=""
DB_PASSWORD=""
DB_PORT=""
REQUIRE_AUTH=""
AUTH_KEY=""
9 changes: 7 additions & 2 deletions location_service/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
FROM python:3.11.4-buster
RUN pip install --upgrade cython pip

ENV DATABASE_URI=""
ENV DB_HOST=""
ENV DB_NAME=""
ENV DB_USER=""
ENV DB_PASSWORD=""
ENV DB_PORT=""
ENV REQUIRE_AUTH=""
ENV AUTH_KEY=""

WORKDIR /usr/location_service
Expand All @@ -13,4 +18,4 @@ COPY . .


EXPOSE 5000
CMD [ "python", "src/main.py", "--create-table", "true", "--seed-filename", "./uw_sample_gpx.csv" ]
CMD [ "python", "src/main.py" ]
20 changes: 4 additions & 16 deletions location_service/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,22 +1,10 @@
blinker==1.6.2
click==8.1.5
blinker==1.7.0
click==8.1.7
colorama==0.4.6
Flask==2.3.2
Flask-SQLAlchemy==3.0.5
GeoAlchemy2==0.14.0
greenlet==2.0.2
Flask==3.0.0
itsdangerous==2.1.2
Jinja2==3.1.2
MarkupSafe==2.1.3
numpy==1.25.1
packaging==23.1
pandas==2.0.3
psycopg2==2.9.6
python-dateutil==2.8.2
psycopg2==2.9.9
python-dotenv==1.0.0
pytz==2023.3
six==1.16.0
SQLAlchemy==2.0.18
typing_extensions==4.7.1
tzdata==2023.3
Werkzeug==3.0.1
132 changes: 44 additions & 88 deletions location_service/src/main.py
Original file line number Diff line number Diff line change
@@ -1,81 +1,35 @@
import json
import os
from argparse import ArgumentParser

import pandas as pd
from dotenv import load_dotenv
from flask import Flask, request
from flask_sqlalchemy import SQLAlchemy
from geoalchemy2 import Geometry
from geoalchemy2.comparator import Comparator
from sqlalchemy import asc, func
from psycopg2 import pool as psycopg2_pool

load_dotenv()
DATABASE_URI = os.environ.get("DATABASE_URI")
REQUIRE_AUTH = os.getenv("REQUIRE_AUTH", "False").lower() in ("true", "1", "t")
AUTH_KEY = os.environ.get("AUTH_KEY")


parser = ArgumentParser()
parser.add_argument(
"--create-table",
type=bool,
help="If you want a table to be created in the database",
required=False,
)
parser.add_argument(
"--seed-filename",
type=str,
help="String of the filepath of the csv file if you want to seed the database with the csv file contents",
required=False,
)
args = parser.parse_args()
args = vars(args)
DB_HOST = os.environ.get("DB_HOST")
DB_PORT = os.environ.get("DB_PORT")
DB_NAME = os.environ.get("DB_NAME")
DB_USER = os.environ.get("DB_USER")
DB_PASSWORD = os.environ.get("DB_PASSWORD")


app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = DATABASE_URI
app.config["SQLALCHEMY_ECHO"] = False
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db = SQLAlchemy(app)
app.app_context().push()


class Location(db.Model):
__tablename__ = "location_test" # Change table name

id = db.Column(db.Integer, primary_key=True)
lat = db.Column(db.Float)
lon = db.Column(db.Float)
geo = db.Column(Geometry(geometry_type="POINT", srid=4326))

def to_dict(self):
return {
"id": self.id,
"lat": self.lat,
"lon": self.lon,
}

@staticmethod
def create(lat, lon):
geo = "POINT({} {})".format(lon, lat) # Note that postgis is (lon, lat)
location = Location(lat=lat, lon=lon, geo=geo)
db.session.add(location)
db.session.commit()

@staticmethod
def seed_from_csv(filename):
df = pd.read_csv(filename)
db.session.query(Location).delete()
for row in df.itertuples():
geo = "POINT({} {})".format(
row.lon, row.lat
) # Note that postgis is (lon, lat)
location = Location(id=row.Index + 1, lat=row.lat, lon=row.lon, geo=geo)
db.session.add(location)
db.session.commit()
postgres_pool = psycopg2_pool.SimpleConnectionPool(
minconn=1,
maxconn=10,
host=DB_HOST,
port=DB_PORT,
database=DB_NAME,
user=DB_USER,
password=DB_PASSWORD,
)


def authorized(auth_key):
if not REQUIRE_AUTH:
return True
return auth_key == AUTH_KEY


Expand All @@ -84,14 +38,21 @@ def index():
return "location service"


@app.route("/all", methods=["GET"])
@app.route("/all", methods=["GET", "POST"])
def all():
body = json.loads(request.data)
auth_key = body.get("auth_key", None)
if not authorized(auth_key):
return "Not authorized", 401
locations = db.session.query(Location).order_by(asc(Location.id))
return [l.to_dict() for l in locations]

query = "SELECT id, lat, lon FROM location_service;"
conn = postgres_pool.getconn()
cur = conn.cursor()
cur.execute(query)
locations = [dict(zip(("id", "lat", "lon"), values)) for values in cur.fetchall()]
cur.close()
postgres_pool.putconn(conn)
return locations


@app.route("/location", methods=["POST"])
Expand All @@ -104,27 +65,22 @@ def closest_location():
return "Not authorized", 401
if lat is None or lon is None:
return "Invalid request body", 400
location = (
db.session.query(Location)
.order_by(
Comparator.distance_centroid(
Location.geo,
func.Geometry(
func.ST_GeographyFromText(
"POINT({} {})".format(lon, lat)
) # Note that postgis is (lon, lat)
),
)
)
.limit(1)
.first()
)
return location.to_dict()

query = f"""
SELECT *
FROM location_service
ORDER BY location_service.geo <-> ST_SetSRID(ST_MakePoint({lon}, {lat}), 4326)
LIMIT 1;
"""
conn = postgres_pool.getconn()
cur = conn.cursor()
cur.execute(query)
location = dict(zip(("id", "lat", "lon"), cur.fetchone()))
print(location)
cur.close()
postgres_pool.putconn(conn)
return location


if __name__ == "__main__":
if args["create_table"]:
db.create_all()
if args["seed_filename"]:
Location.seed_from_csv(args["seed_filename"])
app.run(debug=False, host="0.0.0.0", port=5000)
app.run(debug=True, host="0.0.0.0", port=5000)
140 changes: 0 additions & 140 deletions location_service/uw_sample_gpx.csv

This file was deleted.

0 comments on commit 62b12ad

Please sign in to comment.