Skip to content

Commit

Permalink
Merge pull request #57 from datakind/userisolation
Browse files Browse the repository at this point in the history
Add the concept of session ids to isolate user requests as an optional query parameter
  • Loading branch information
Zebreu authored Apr 15, 2024
2 parents 36ff36a + ac0a86e commit aa7789d
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 26 deletions.
11 changes: 5 additions & 6 deletions dkroutingtool/src/py/main_application.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,12 @@
parser.add_argument('--manual_input_path', dest='manual_input_path', default=None)
args = parser.parse_args()

OUTPUT_DATA_DIR = 'WORKING_DATA_DIR/output_data/'
INPUT_DATA_DIR = 'WORKING_DATA_DIR/input_data/'
LOCAL_TEST_INPUT_DATA_DIR = 'data/'

gpx_output = True

def main():
def main(user_directory='data'):
OUTPUT_DATA_DIR = f'WORKING_DATA_DIR/{user_directory}/output_data/'
INPUT_DATA_DIR = f'WORKING_DATA_DIR/{user_directory}/input_data/' # should test cloud setting eventually

timestamp = time.strftime("%Y_%m_%d_%H_%M")
logging.info(f"Model Run Initiated {timestamp} (UTC)")

Expand All @@ -65,7 +64,7 @@ def main():
cloud_client, local_input_dir, args.manual_mapping_mode
)
else:
local_input_dir = LOCAL_TEST_INPUT_DATA_DIR
local_input_dir = user_directory+'/'
logging.info(f"Loading input from local {local_input_dir}")
config_manager = ConfigManager.load_from_local(
local_input_dir, args.manual_mapping_mode, args.manual_input_path)
Expand Down
28 changes: 15 additions & 13 deletions dkroutingtool/src/py/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,53 +12,55 @@

app = fastapi.FastAPI()

def find_most_recent_output():
most_recent = sorted(glob.glob('/WORKING_DATA_DIR/output_data/*'))[-1]
def find_most_recent_output(session_id):
most_recent = sorted(glob.glob(f'/WORKING_DATA_DIR/data{session_id}/output_data/*'))[-1]
return most_recent

@app.post('/provide_files')
def provide_files(files: List[UploadFile] = File(...)):
def provide_files(files: List[UploadFile] = File(...), session_id: str=''):
for file in files:
contents = file.file.read()
print(contents)
with open(f'/data/{file.filename}', 'wb') as f:
#print(contents)
provided = f'/data{session_id}/{file.filename}'
os.makedirs(os.path.dirname(provided), exist_ok=True)
with open(provided, 'wb') as f:
f.write(contents)
file.file.close()
return {'message': 'Uploaded'}


@app.get('/get_solution')
def get_solution():
def get_solution(session_id: str=''):
main_application.args.cloud = False
main_application.args.manual_mapping_mode = False
main_application.args.manual_input_path = None

main_application.main()
main_application.main(user_directory=f'data{session_id}')
return {'message': 'Done'}


@app.post('/adjust_solution')
def get_solution(files: List[UploadFile] = File(...)):
most_recent = find_most_recent_output()
def get_solution(files: List[UploadFile] = File(...), session_id: str=''):
most_recent = find_most_recent_output(session_id)
print(most_recent)

for file in files:
contents = file.file.read()
print(contents)
#print(contents)
with open(f'{most_recent}/manual_edits/{file.filename}', 'wb') as f:
f.write(contents)
file.file.close()

main_application.args.cloud = False
main_application.args.manual_mapping_mode = True
main_application.args.manual_input_path = f'{most_recent}/manual_edits'
main_application.main()
main_application.main(user_directory=f'data{session_id}')
return {'message': 'Manual solution updated, please download again'}


@app.get('/download')
def download():
most_recent = find_most_recent_output()
def download(session_id: str=''):
most_recent = find_most_recent_output(session_id)
print(most_recent)
name= 'server_output'
shutil.make_archive(name, 'zip', most_recent)
Expand Down
20 changes: 13 additions & 7 deletions dkroutingtool/src/py/ui/dashboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,18 @@
from streamlit_folium import st_folium
import folium
import os
from streamlit.runtime import get_instance
from streamlit.runtime.scriptrunner import get_script_run_ctx

st.set_page_config(page_title='Container-based Action Routing Tool (CART)', layout="wide")

runtime = get_instance()
session_id = get_script_run_ctx().session_id
host_url = 'http://{}:5001'.format(os.environ['SERVER_HOST'])

def download_solution(solution_path, map_path):
timestamp = datetime.datetime.now().strftime(format='%Y%m%d-%H-%M-%S')
response = requests.get(f'{host_url}/download')
response = requests.get(f'{host_url}/download/?session_id={session_id}')

solution_zip = response.content

Expand All @@ -34,7 +38,7 @@ def download_solution(solution_path, map_path):
return solution, map, solution_zip

def request_solution():
response = requests.get(f'{host_url}/get_solution')
response = requests.get(f'{host_url}/get_solution/?session_id={session_id}')
solution, map, solution_zip = download_solution(solution_path='solution.txt', map_path='/maps/route_map.html')

return solution, map, solution_zip
Expand All @@ -52,14 +56,14 @@ def adjust(adjusted_file):
}

files = {'files': adjusted_file[0]} # We only expect one
response = requests.post(f'{host_url}/adjust_solution', headers=headers, files=files)
response = requests.post(f'{host_url}/adjust_solution/?session_id={session_id}', headers=headers, files=files)
if response.ok:
message = "Adjusted routes successfully uploaded"
else:
message = 'Error, verify the adjusted routes file or raise an issue'

solution, map, solution_zip = download_solution(solution_path='manual_edits/manual_solution.txt', map_path='maps/trip_data.html')
return message, solution, map
return message, solution, map, solution_zip

def upload_data(files_from_streamlit):
files = [('files', file) for file in files_from_streamlit]
Expand All @@ -75,15 +79,15 @@ def upload_data(files_from_streamlit):
# ('files', open('local_data/extra_points.csv', 'rb')),
# ('files', open('local_data/customer_data.xlsx', 'rb'))]

response = requests.post(f'{host_url}/provide_files', headers=headers, files=files)
response = requests.post(f'{host_url}/provide_files/?session_id={session_id}', headers=headers, files=files)
if response.ok:
return 'All files uploaded successfully'
else:
return 'Error, please verify your files or raise an issue'

def main():
st.header('Container-based Action Routing Tool (CART)')

st.write('Available vehicle profiles: '+ requests.get(f'{host_url}/available_vehicles').json()['message'])

st.write('If required, draw a rectangle over the area you want to use for routing. Download it again only if you updated the OpenStreetMap data. Please select an area as small as possible.')
Expand Down Expand Up @@ -130,8 +134,10 @@ def main():
uploaded_files = st.file_uploader('If adjustments are made in the manual_edits spreadsheet, upload it here to get adjusted solutions', accept_multiple_files=True)
if len(uploaded_files) > 0:
with st.spinner('Adjusting routes, please wait...'):
response, solution, map = adjust(uploaded_files)
response, solution, map, solution_zip = adjust(uploaded_files)
st.write(response)
b64 = base64.b64encode(solution_zip).decode()
st.markdown(f'<a href="data:application/octet-stream;base64,{b64}" download="solution.zip">Download solution files</a>', unsafe_allow_html=True)
components.html(map, height = 800)
st.write(solution)

Expand Down

0 comments on commit aa7789d

Please sign in to comment.