Skip to content

Commit 4518e1e

Browse files
authored
Merge pull request #31 from uf-quantum-computing/dev
Server side messages are emitted per client, not broadcasted
2 parents 919b15a + c3685c2 commit 4518e1e

File tree

6 files changed

+38
-42
lines changed

6 files changed

+38
-42
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ cover/
234234
*.pot
235235

236236
# Django stuff:
237-
*.log
237+
*.log*
238238
local_settings.py
239239
db.sqlite3
240240
db.sqlite3-journal

quantum_app_backend/app.py

Lines changed: 33 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,31 @@
1-
import flask
2-
from flask import Flask, jsonify
1+
from gevent import monkey
2+
monkey.patch_all()
3+
4+
from flask import Flask, jsonify, request
35
from flask_restx import Api
46
from flask_cors import CORS
57
from model_generators.tunneling import Wave_Packet3D as t_wp, Animator3D as t_ani
68
from model_generators.interference import Wave_Packet3D as i_wp, Animator3D as i_ani
79
from model_generators.Qgate1 import Qgate1
810
from model_generators.QuantumFourierTransform import QFTStepByStepODE
9-
from model_generators.bloch import Bloch
1011
import matplotlib.pyplot as plt
11-
import time
1212
import logging
1313
from logging.handlers import RotatingFileHandler
1414
import os
1515
from db import MongoConnector
1616
from flask_socketio import SocketIO, emit
1717
from functools import wraps
1818

19+
sid = None
20+
21+
#set swagger info
22+
api: Api = Api(
23+
title='quantum_modeling',
24+
version='1.0',
25+
description='v1.0',
26+
prefix='/v1'
27+
)
28+
1929
# Set up logging
2030
log_dir = 'logs'
2131
if not os.path.exists(log_dir):
@@ -31,7 +41,7 @@
3141
backupCount=5
3242
)
3343
file_handler.setFormatter(formatter)
34-
file_handler.setLevel(logging.INFO)
44+
file_handler.setLevel(logging.DEBUG)
3545

3646
console_handler = logging.StreamHandler()
3747
console_handler.setFormatter(formatter)
@@ -42,22 +52,19 @@
4252
logger.addHandler(console_handler)
4353
logger.setLevel(logging.DEBUG)
4454

45-
# Add this after the logger setup
4655
class SocketHandler(logging.Handler):
47-
def __init__(self, socketio):
56+
def __init__(self):
4857
super().__init__()
49-
self.socketio = socketio
50-
# No need for formatter since we're only using the message
5158

5259
def emit(self, record):
5360
try:
5461
# Only emit INFO level and above to avoid flooding the client
5562
if record.levelno >= logging.INFO:
56-
self.socketio.emit('status_update', {'message': record.getMessage()})
57-
except Exception:
58-
self.handleError(record)
63+
global sid
64+
emit('status_update', {'message': record.getMessage()}, room=sid, namespace='/')
65+
except Exception as e:
66+
logger.error(f"Socket emission failed: {str(e)}", exc_info=True)
5967

60-
# Error handling decorator
6168
def handle_errors(f):
6269
@wraps(f)
6370
def wrapped(*args, **kwargs):
@@ -69,19 +76,11 @@ def wrapped(*args, **kwargs):
6976
return jsonify({"error": str(e)}), 500
7077
return wrapped
7178

72-
#set swagger info
73-
api: Api = Api(
74-
title='quantum_modeling',
75-
version='1.0',
76-
description='v1.0',
77-
prefix='/v1'
78-
)
79-
8079
app = Flask(__name__)
8180
api.init_app(app)
8281
CORS(app, resources={r"/*": {"origins": "*"}})
83-
socketio = SocketIO(app, cors_allowed_origins="*")
84-
socket_handler = SocketHandler(socketio)
82+
socketio = SocketIO(app, async_mode='gevent', cors_allowed_origins="*", logger=True, engineio_logger=True)
83+
socket_handler = SocketHandler()
8584
socket_handler.setLevel(logging.INFO)
8685
logger.addHandler(socket_handler)
8786
mongo = MongoConnector()
@@ -108,21 +107,18 @@ def Qtunneling(barrier, width, momentum):
108107
try:
109108
tunneling_model = mongo.get(t_collection, parameters)
110109
if not tunneling_model:
111-
emit_status('Generating tunneling model...')
112110
plt.close('all')
113111
plt.switch_backend('Agg')
114112

115-
emit_status('Calculating tunneling model...')
116113
animator = t_ani(t_wp(barrier_height=barrier, barrier_width=width, k0=momentum))
117114

118-
emit_status('Animating tunneling model...')
119115
tunneling_model = animator.animate3D()
120116

121-
# Upload to MongoDB asynchronously after returning response
117+
# Upload to MongoDB asynchronously after emitting response
118+
emit_status(f"Generated new tunneling model with parameters: {parameters}")
122119
socketio.start_background_task(mongo.upload, t_collection, parameters, tunneling_model)
123-
logger.info(f"Generated new tunneling model with parameters: {parameters}")
124120
else:
125-
logger.info(f"Retrieved existing tunneling model with parameters: {parameters}")
121+
emit_status(f"Retrieved existing tunneling model with parameters: {parameters}")
126122
return tunneling_model
127123
except Exception as e:
128124
logger.error(f"Error generating tunneling model: {str(e)}", exc_info=True)
@@ -154,9 +150,9 @@ def Qinterference(spacing, slit_separation, momentum):
154150
interference_model = animator.animate3D()
155151

156152
socketio.start_background_task(mongo.upload, i_collection, parameters, interference_model)
157-
logger.info(f"Generated new interference model with parameters: {parameters}")
153+
emit_status(f"Generated new interference model with parameters: {parameters}")
158154
else:
159-
logger.info(f"Retrieved existing interference model with parameters: {parameters}")
155+
emit_status(f"Retrieved existing interference model with parameters: {parameters}")
160156
return interference_model
161157
except Exception as e:
162158
logger.error(f"Error generating interference model: {str(e)}", exc_info=True)
@@ -193,7 +189,9 @@ def Qfouriertransform():
193189

194190
@socketio.on('connect')
195191
def handle_connect():
196-
logger.info("Client connected")
192+
global sid
193+
sid = request.sid
194+
logger.debug("Client connected")
197195
emit('status_update', {'message': 'Connected to quantum model generator server'})
198196

199197
@socketio.on('disconnect')
@@ -202,9 +200,9 @@ def handle_disconnect():
202200

203201
@socketio.on('message')
204202
def handle_message(data):
205-
logger.info(f"Received message: {data}")
203+
logger.debug(f"Received message: {data}")
206204

207205
if __name__ == '__main__':
208206
app.debug = True
209-
logger.info("Starting quantum modeling server")
210-
socketio.run(app, host="0.0.0.0", port=3001, debug=True)
207+
logger.debug("Starting quantum modeling server")
208+
socketio.run(app, host="0.0.0.0", port=3001, debug=False)

quantum_app_backend/requirements.txt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,4 @@ flask-pymongo
2828
dotenv
2929
flask-socketio
3030
gunicorn==23.0.0
31-
eventlet==0.39.1
32-
greenlet==3.1.1
31+
gevent==24.11.1

src/pages/Interference.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,6 @@ const Interference = () => {
111111
.then((response) => response.text())
112112
.then((text) => {
113113
setAnimationJsHtml(text);
114-
console.log(text);
115114
});
116115
} catch (error) {
117116
console.error("Failed to load default HTML content:", error);

src/pages/SingleQgate.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ const SpinTraceEvolution = () => {
9393
.then((response) => response.text())
9494
.then((text) => {
9595
setAnimationJsHtml(text);
96-
console.log(text)
9796
});
9897
} catch (error) {
9998
console.error('Failed to load default HTML content:', error);

src/pages/Tunneling.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,9 @@ const Tunneling = () => {
5959

6060
// ========= socket connection =========
6161
useEffect(() => {
62-
const socket = io(host);
62+
const socket = io(host, {
63+
transports: ['websocket']
64+
});
6365

6466
socket.on("connect", () => {
6567
console.log("Connected to server");
@@ -113,7 +115,6 @@ const Tunneling = () => {
113115
.then((response) => response.text())
114116
.then((text) => {
115117
setAnimationJsHtml(text);
116-
console.log(text);
117118
});
118119
} catch (error) {
119120
setSnackbarMessage("Failed to load default model.");

0 commit comments

Comments
 (0)