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

Port crawling #66

Merged
merged 15 commits into from
Jun 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ jobs:
run: npm --prefix electron/ui test

- name: run backend server
run: uvicorn --app-dir backend/app main:app --reload --host 0.0.0.0 --port 8001 & sleep 10
working-directory: backend/app
run: python main.py & sleep 10

- name: run frontend
run: npm --prefix electron/ui start & sleep 30
Expand Down
26 changes: 23 additions & 3 deletions backend/app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from fastapi.middleware.cors import CORSMiddleware
import uvicorn
import multiprocessing
import socket, errno

SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
sys.path.append(os.path.dirname(SCRIPT_DIR))
Expand All @@ -38,18 +39,37 @@

app.include_router(scenarios.router)

def getPort():
port = 50011
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
foundOpenPort = False
while not foundOpenPort:
try:
s.bind(("127.0.0.1", port))
_log.info(f"found open port: {port}")
foundOpenPort = True
except socket.error as e:
if e.errno == errno.EADDRINUSE:
_log.info(f"Port {port} is already in use")
else:
_log.error(f"Error while trying to connect to port {port}: {e}")
port += 1
s.close()
return port

if __name__ == '__main__':
port = getPort()
if('i' in sys.argv or 'install' in sys.argv):
_log.info('running get_extensions()')
if not check_for_idaes_extensions():
get_idaes_extensions()

elif('d' in sys.argv or 'dev' in sys.argv):
_log.info(f"starting app")
_log.info(f"starting app in dev")
multiprocessing.freeze_support()
uvicorn.run("__main__:app", host="127.0.0.1", port=8001, reload=True)
uvicorn.run("__main__:app", host="127.0.0.1", port=port, reload=True)

else:
_log.info(f"starting app")
multiprocessing.freeze_support()
uvicorn.run(app, host="127.0.0.1", port=8001, reload=False)
uvicorn.run(app, host="127.0.0.1", port=port, reload=False)
7 changes: 7 additions & 0 deletions backend/app/routers/scenarios.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@
responses={404: {"description": "Scenario not found"}},
)

@router.get("/get_project_name")
async def get_scenario_list():
"""
Get project name.
"""
return "pareto"

@router.get("/get_scenario_list")
async def get_scenario_list():
"""
Expand Down
2 changes: 1 addition & 1 deletion electron/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"build-frontend-win": "npm --prefix ui run build && npm run move-frontend-build-win || npm run move-frontend-build-win",
"move-frontend-build-win": "move /Y ui/build build",
"start-frontend": "npm --prefix ui run start",
"start-backend": "cd ../backend/app && uvicorn main:app --reload --host 127.0.0.1 --port 8001",
"start-backend": "cd ../backend/app && python main.py -d",
"build-backend": "cd ../backend/app && pyinstaller -y --clean --distpath ../../electron/py_dist main.spec",
"build-replace-backend": "npm run remove-previous-backend-build && npm run build-backend || npm run build-backend",
"build-replace-backend-win": "npm run remove-previous-backend-build-win && npm run build-backend || npm run build-backend",
Expand Down
2 changes: 1 addition & 1 deletion electron/ui/cypress/e2e/ScenarioTests.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ describe('scenario testing', () => {
sc_count+=1
cy.intercept({
method: "POST",
url: "http://localhost:8001/**",
url: "http://localhost:50011/**",
}).as("createScenario");
// cy.findByRole('button', {name: /create scenario/i}).click()
cy.get('button[id="create-scenario-button"]').click()
Expand Down
6 changes: 3 additions & 3 deletions electron/ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@
},
"scripts": {
"start": "react-scripts start",
"app-start": "concurrently -k \"cross-env npm run start-backend\" \"react-scripts start\"",
"app-start": "concurrently -k \"cross-env npm run start-backend\" \"npm start\"",
"electron-start": "concurrently -k \"npm run start-backend\" \"npm run start-nob\" \"wait-on http://127.0.0.1:3000 && npx --prefix ../ electron .\"",
"start-backend": "cd ../../backend/app && uvicorn main:app --reload --host 127.0.0.1 --port 8001",
"start-nob": "cross-env BROWSER=none react-scripts start",
"start-backend": "cd ../../backend/app && python main.py -d",
"start-nob": "cross-env BROWSER=none npm start",
"build": "react-scripts build",
"postbuild": "rm -r ../build && mv build ../ || mv build ../",
"test": "react-scripts test",
Expand Down
2 changes: 1 addition & 1 deletion electron/ui/public/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const { spawn, execFile } = require("child_process")

// Python server parameters
const PY_HOST = "127.0.0.1";
const PY_PORT = 8001;
const PY_PORT = 50011;
const UI_PORT = 3000;
const PY_LOG_LEVEL = "info";
let uiReady = false
Expand Down
35 changes: 17 additions & 18 deletions electron/ui/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,11 @@ import ScenarioList from './views/ScenarioList/ScenarioList';
import ScenarioCompare from './views/ScenarioCompare/ScenarioCompare';
import LandingPage from './views/LandingPage/LandingPage';
import ModelCompletionBar from './components/ModelCompletionBar/ModelCompletionBar';
import { updateScenario, updateExcel, fetchScenarios, checkTasks } from './services/app.service'
import { deleteScenario, copyScenario } from './services/scenariolist.service'
import { runModel } from './services/homepage.service';
import { updateScenario, updateExcel, fetchScenarios, checkTasks, deleteScenario, copyScenario, runModel } from './services/app.service'
import { useApp } from './AppContext';


function App() {

const [ scenarioData, setScenarioData ] = useState(null);
const [ scenarios, setScenarios ] = useState({});
const [ appState, setAppState ] = useState(null)
Expand All @@ -39,6 +37,7 @@ function App() {
const COMPLETED_STATES = ['Optimized','failure', 'Infeasible']
const TIME_BETWEEN_CALLS = 20000
let navigate = useNavigate();
const { port } = useApp()

useEffect(()=>{
/*
Expand All @@ -47,12 +46,12 @@ function App() {
3) if a scenario is a draft, is optimized, or is currently running, leave it as is
4) if a scenario was running when the app was previously quit, reset it to draft
*/
checkTasks()
checkTasks(port)
.then(response => response.json())
.then((data)=>{
let tasks = data.tasks
setBackgroundTasks(tasks)
fetchScenarios()
fetchScenarios(port)
.then(response => response.json())
.then((data)=>{
// console.log('loaded landing page on try #'+loadLandingPage)
Expand All @@ -67,7 +66,7 @@ function App() {
tempScenarios[key] = scenario
if (RUNNING_STATES.includes(scenario.results.status) && !tasks.includes(scenario.id)) {
scenario.results.status = 'Draft'
updateScenario({'updatedScenario': {...scenario}})
updateScenario(port, {'updatedScenario': {...scenario}})
.then(response => response.json())
.then((data) => {
console.log('reset scenario')
Expand Down Expand Up @@ -101,7 +100,7 @@ useEffect(()=> {
make api call to get status of each running task
*/
// console.log('checking model results')
fetchScenarios()
fetchScenarios(port)
.then(response => response.json())
.then((data)=>{
let tempScenarios = data.data
Expand Down Expand Up @@ -152,7 +151,7 @@ useEffect(()=> {
const handleCompletedOptimization = (newScenarios, id) => {
setCheckModelResults(0)
setScenarios(newScenarios)
checkTasks()
checkTasks(port)
.then(response => response.json())
.then((data)=>{
setBackgroundTasks(data.tasks)
Expand Down Expand Up @@ -193,7 +192,7 @@ useEffect(()=> {
setSection(0)
setCategory(null)
setScenarioIndex(null)
fetchScenarios()
fetchScenarios(port)
.then(response => response.json())
.then((data)=>{
console.log('setscenarios: ',data.data)
Expand Down Expand Up @@ -234,7 +233,7 @@ useEffect(()=> {
setScenarioData({...updatedScenario})
// console.log('new scenario: ')
// console.log({...updatedScenario})
updateScenario({'updatedScenario': {...updatedScenario}})
updateScenario(port, {'updatedScenario': {...updatedScenario}})
.then(response => response.json())
.then((data) => {
// console.log('updated scenarios on backend')
Expand Down Expand Up @@ -267,7 +266,7 @@ useEffect(()=> {
if (updateScenarioData) {
setScenarioData(tempScenario)
}
updateScenario({'updatedScenario': tempScenario})
updateScenario(port, {'updatedScenario': tempScenario})
.then(response => response.json())
.then((data) => {
// console.log('updated scenarios on backend')
Expand All @@ -279,7 +278,7 @@ useEffect(()=> {

const handleDeleteScenario = (index) => {
// console.log('deleting scenario: ',index)
deleteScenario({'id': index})
deleteScenario(port, {'id': index})
.then(response => response.json())
.then((data) => {
setScenarios(data.data)
Expand All @@ -294,7 +293,7 @@ useEffect(()=> {
function for updating an input table for excel sheet
*/
const handleUpdateExcel = (id, tableKey, updatedTable) => {
updateExcel({"id": id, "tableKey":tableKey, "updatedTable":updatedTable})
updateExcel(port, {"id": id, "tableKey":tableKey, "updatedTable":updatedTable})
.then(response => response.json())
.then((data)=>{
// console.log('return from update excel: ')
Expand All @@ -313,7 +312,7 @@ useEffect(()=> {
fetch scenarios and update frontend data
*/
const syncScenarioData = () => {
fetchScenarios()
fetchScenarios(port)
.then(response => response.json())
.then((data)=>{
setScenarios(data.data)
Expand Down Expand Up @@ -386,7 +385,7 @@ useEffect(()=> {
*/
const copyAndRunOptimization = (newScenarioName) => {
//copy scenario
copyScenario(scenarioIndex, newScenarioName)
copyScenario(port, scenarioIndex, newScenarioName)
.then(response => response.json())
.then((copy_data) => {
// update data
Expand All @@ -397,14 +396,14 @@ useEffect(()=> {
setScenarioData(copy_data.scenarios[copy_data.new_id])

// run model on new id
runModel({"scenario": copy_data.scenarios[copy_data.new_id]})
runModel(port, {"scenario": copy_data.scenarios[copy_data.new_id]})
.then(r => r.json().then(data => ({status: r.status, body: data})))
.then((response) => {
let responseCode = response.status
let data = response.body
if(responseCode === 200) {
// handleScenarioUpdate(data)
updateScenario({'updatedScenario': {...data}})
updateScenario(port, {'updatedScenario': {...data}})
.then(response => response.json())
.then((updateScenario_data) => {
// console.log('returned from update scenario call')
Expand Down
54 changes: 54 additions & 0 deletions electron/ui/src/AppContext.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import React, { createContext, useContext, useEffect, useState } from 'react';

const AppContext = createContext();

export const useApp = () => {
return useContext(AppContext);
};

export const AppProvider = ({ children }) => {
const [ port, setPort ] = useState(50011);
const [ foundPort, setFoundPort ] = useState(false)

useEffect(() => {
/*
search for backend port
*/
fetch('http://localhost:'+port+'/get_project_name', {
method: 'GET',
mode: 'cors',
})
.then(response => {
if (response.status === 200) {
response.json()
.then((data)=>{
if (data === "pareto") {
// console.log("found pareto on port "+ port)
setFoundPort(true)
}
else {
setPort(port + 1)
}
}).catch((err)=>{
setPort(port + 1)
})
}
else {
setPort(port + 1)
}
}).catch((err) => {
setPort(port + 1)
})
}, [port]);


const value = {
port
};

return (
<AppContext.Provider value={value}>
{foundPort && children}
</AppContext.Provider>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import CloseIcon from '@mui/icons-material/Close';
import Button from '@mui/material/Button';
import { FileUploader } from "react-drag-drop-files";
import { fetchExcelFile } from '../../services/app.service';
import { useApp } from '../../AppContext';



Expand All @@ -25,6 +26,7 @@ export default function FileUploadModal(props) {
// const workshopFileUrl = "https://github.com/project-pareto/project-pareto/raw/0.9_rel/pareto/case_studies/workshop_baseline_all_data.xlsx"
const workshopFileUrl = "https://github.com/project-pareto/project-pareto/raw/main/pareto/case_studies/workshop_baseline_all_data.xlsx"
const workshopFileName = "workshop_baseline_all_data_0.9.0.xlsx"
const { port } = useApp()


useEffect(()=>{
Expand Down Expand Up @@ -82,7 +84,7 @@ export default function FileUploadModal(props) {
}

const handleDownloadWorkshopFile = () => {
fetchExcelFile(workshopFileName).then(response => {
fetchExcelFile(port, workshopFileName).then(response => {
if (response.status === 200) {
response.blob().then((data)=>{
let excelURL = window.URL.createObjectURL(data);
Expand Down
6 changes: 4 additions & 2 deletions electron/ui/src/components/InputSummary/InputSummary.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { fetchExcelTemplate, replaceExcelSheet } from '../../services/app.servic
import NetworkMap from '../NetworkMap/NetworkMap';
import { FileUploader } from "react-drag-drop-files";
import ErrorBar from '../ErrorBar/ErrorBar'
import { useApp } from '../../AppContext';

export default function InputSummary(props) {
const [ tableType, setTableType ] = useState("Input Summary")
Expand All @@ -14,6 +15,7 @@ export default function InputSummary(props) {
const [ disableUpload, setDisableUpload ] = useState(false)
const [ errorMessage, setErrorMessage ] = useState("")
const fileTypes = ["xlsx"];
const { port } = useApp()
const [ sumValues, setSumValues ] = useState([
{statistic: 'Total Completions Demand', value: 0, units: 'bbl'},
{statistic: 'Total Produced Water', value: 0, units: 'bbl'},
Expand Down Expand Up @@ -166,7 +168,7 @@ export default function InputSummary(props) {
}

const handleDownloadExcel = () => {
fetchExcelTemplate(props.scenario.id).then(response => {
fetchExcelTemplate(port, props.scenario.id).then(response => {
if (response.status === 200) {
response.blob().then((data)=>{
let excelURL = window.URL.createObjectURL(data);
Expand All @@ -187,7 +189,7 @@ export default function InputSummary(props) {
const handleReplaceExcel = (file) => {
const formData = new FormData();
formData.append('file', file, file.name);
replaceExcelSheet(formData, props.scenario.id)
replaceExcelSheet(port, formData, props.scenario.id)
.then(response => {
if (response.status === 200) {
response.json()
Expand Down
Loading