From ac0a86e0dfb312fd96770ed10b8fb62db337d586 Mon Sep 17 00:00:00 2001 From: Zebreu Date: Sun, 14 Apr 2024 23:31:37 -0400 Subject: [PATCH] Add the concept of session ids to isolate user requests as an optional query parameter --- dkroutingtool/src/py/main_application.py | 11 +++++----- dkroutingtool/src/py/server.py | 28 +++++++++++++----------- dkroutingtool/src/py/ui/dashboard.py | 20 +++++++++++------ 3 files changed, 33 insertions(+), 26 deletions(-) diff --git a/dkroutingtool/src/py/main_application.py b/dkroutingtool/src/py/main_application.py index b74c682..e1fa67d 100644 --- a/dkroutingtool/src/py/main_application.py +++ b/dkroutingtool/src/py/main_application.py @@ -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)") @@ -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) diff --git a/dkroutingtool/src/py/server.py b/dkroutingtool/src/py/server.py index d5c187e..38239ad 100644 --- a/dkroutingtool/src/py/server.py +++ b/dkroutingtool/src/py/server.py @@ -12,39 +12,41 @@ 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() @@ -52,13 +54,13 @@ def get_solution(files: List[UploadFile] = File(...)): 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) diff --git a/dkroutingtool/src/py/ui/dashboard.py b/dkroutingtool/src/py/ui/dashboard.py index 456211c..a233e00 100644 --- a/dkroutingtool/src/py/ui/dashboard.py +++ b/dkroutingtool/src/py/ui/dashboard.py @@ -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 @@ -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 @@ -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] @@ -75,7 +79,7 @@ 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: @@ -83,7 +87,7 @@ def upload_data(files_from_streamlit): 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.') @@ -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'Download solution files', unsafe_allow_html=True) components.html(map, height = 800) st.write(solution)