Я пытаюсь закодировать бэкэнд в колбе, которая должна выполнить ряд проверок на внешних машинах (check1, check2 и т. Д.).Это последовательный процесс (после проверки n, мы проверяем n + 1), но он требует сохранения «текущего состояния».Например, check1 состоит в опросе ресурса (скручивание каждую секунду) из внешнего API, который возвращает некоторые журналы машины.
Всякий раз, когда бэкэнд находит «некоторую строку» в извлеченных журналах, бэкэнд должен обновитьглобальное состояние бэкэнда, сообщите об этом во внешний интерфейс (чтобы обновить компоненты макета) и перейдите к следующему состоянию.
Опять же, в следующем состоянии бэкэнд проверяет что-то еще, и когда «другая строка»найдено, обновите глобальное состояние, уведомите его, чтобы перейти к новому состоянию и перейти к следующему состоянию.
И так, это основная идея.
У него есть единственный маршрут (/).
Веб-приложение не для производства, оно просто должно работать, и его цель - просто показать, как развивается система (пример мониторинга).Глобальное состояние должно передаваться таким образом, чтобы любой, кто идет по маршруту / видел текущее состояние.
Я новичок в веб-разработке и считаю, что это странное приложение, поэтому оно не так тривиально, как я думал.
Ниже я покажу некоторый код, который представляет:
Состояние 0: сообщает новое состояние (данные) интерфейсу через socketio.Ничего не делает, просто ждет события onClick в кнопке запуска.Когда это происходит, происходит переход в состояние 1.
Состояние 1: сообщает новое состояние (данные) интерфейсу через socketio.Затем выполняет какую-то задачу.Когда задача «успешно» перейдет в следующее состояние 2.
Независимо от состояния, пользователь может изменить параметр (параметр) в веб-интерфейсе пользователя.Я справляюсь с этим через запись socketio внизу.
main.py
from flask import Flask, render_template
from flask_socketio import SocketIO, emit
import time, json
global data
data = {'state': '0', 'param': '50', 'disableStart': 'false', 'disableReset': 'true', 'info': 'Waiting to start'}
def state_1():
print("[Server.state_1]: In state 1...checking service")
data['state'] = '1'
data['disableStart'] = 'true'
data['disableReset'] = 'true'
data['info'] = 'Waiting for service is OK'
socketio.emit('refresh', json.dumps(data), broadcast=True)
# Checking if service is OK...
# Below is just a dummy sustitute
counter = 0
while counter < 100:
print("Checking..." + str(counter) + "%")
time.sleep(1)
counter += 1
# When service is OK jump to state_2()
def state_0():
print("[Server.state_0]: In state 0...waiting to start...")
data['state'] = '0'
data['info'] = 'Waiting to start'
socketio.emit('refresh', json.dumps(data), broadcast=True)
# initialize Flask
app = Flask(__name__)
socketio = SocketIO(app)
@app.route('/')
def index():
print("[Server.index]: " + json.dumps(data))
return render_template('index.html')
@socketio.on('connect')
def on_connect():
print("[Server.on_connect]: A new connection!")
print("[Server.on_connect]: " + json.dumps(data))
# In every new refresh or new tab, we need to display current state
emit('refresh', json.dumps(data), broadcast=True)
# Jump to current state
print("[Server.on_connect]: Jump to state " + data['state'])
f_name = "state_" + data['state']
globals()[f_name]()
@socketio.on('start')
def on_start():
print("[Server.on_start]: Clicked on START button! Jump to state 1")
state_1()
@socketio.on('update_slide_param')
def on_update_slide_param(paramVal):
data['param'] = paramVal
# Setting this param to an external machine...
print("[Server.on_update_slide_param]: A new value has been set! Jump to state " + data['state'])
f_name = "state_" + data['state']
globals()[f_name]()
if __name__ == '__main__':
socketio.run(app, debug=True)
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Flask SocketIO Test</title>
</head>
<body>
<p>Some sample code to make sure Flask-SocketIO works...</p>
<button onclick="onClickStart()" id="startButton">START</button>
<button onclick="onClickReset()" id="resetButton">RESET</button>
<input onchange="onSetSliderVal()" class="slider" type="range" id="idSlider" min="50" max="300" value="50"/>
<p>Value: <span id="idSliderVal"></span></p>
<script type="text/javascript" charset="utf-8">
var slider = document.getElementById("idSlider");
var output = document.getElementById("idSliderVal");
output.innerHTML = slider.value; // Display the default slider value
// Update the current slider value (each time you drag the slider handle)
slider.oninput = function () {
output.innerHTML = this.value;
}
</script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.2.0/socket.io.js"></script>
<script type="text/javascript" charset="utf-8">
var socket = io.connect('http://' + document.domain + ':' + location.port);
// verify our websocket connection is established
socket.on('connect', function () {
console.log('Websocket connected!');
});
// onClickStart - emit a message on the 'start' channel to
// launch a new demo with default parameters
function onClickStart() {
console.log('Starting demo...');
socket.emit('start');
};
// onSetSliderVal - emit a message on the 'update_slide_param' channel to
// perform the action and update global 'data'
function onSetSliderVal() {
var paramVal = document.getElementById('idSlider').value;
console.log('Setting a value of ' + paramVal + '...');
socket.emit('update_slide_param', paramVal);
};
socket.on('refresh', function (data) {
var x = JSON.parse(data); // This is the way we can use our dictionary 'data' as a JSON in JS
console.log('[refresh] Frontend has updated info! Now we are in state ' + x.state);
console.log('[refresh] All variables are:'); console.log(x);
document.getElementById('idSlider').value = x.param;
document.getElementById("idSliderVal").innerHTML = x.param;
document.getElementById('startButton').disabled = JSON.parse(x.disableStart); // This is the cleanest way JS converts a "true"/"false" (string) into true/false (boolean)
document.getElementById('resetButton').disabled = JSON.parse(x.disableReset);
});
</script>
</body>
</html>
Проблема:
Если я обновляюсь в состоянии 0, он работает нормально.Во время этого состояния я могу изменить «параметр», и информация обновляется в каждой открытой вкладке браузера.Если я обновлюсь, обновленный параметр будет сохранен.
Затем я нажимаю кнопку запуска, и все в порядке (состояние внешнего интерфейса обновляется, как я хочу).Однако, если я обновлю вкладку, произойдут две вещи:
a.Из средств разработки браузера информация консоли из сокетов исчезает.
b.Функция state_1 () на сервере выполняется снова, и в журналах сервера вы увидите что-то вроде этого:
Проверка ... 2% Проверка ... 16% Проверка ... 3% Проверка ...17% Проверка ... 4%
...
Конечно, кажется, что новый "экземпляр" функции выполняется.
В целом, это будетбыло бы приятно иметь обратную связь.Вы можете быстро протестировать проблему с помощью предоставленного кода (создать venv, установить колбу pip3 flask-socketio, создать папку шаблонов для index.html, а затем просто «python3 main.py»)