Найти - Пользователи
Полная версия: gevent websocket server + client pagination
Начало » Python для экспертов » gevent websocket server + client pagination
1
remoshka
Есть задача: выбирать данные(пагинация) с вебсокет сервера(gevent + django) и отображать их в google chart'e. Код не коммерческий, просто для себя прорабатываю этот момент.
 class ChartPushData(WebSocketApplication):
    def on_open(self):
        print("Connection opened ChartPushData")
    def on_message(self, msg):
        data = json.loads(msg)
        data1 = [{'data': list(
            Ethereum.objects.values()[data['start']:data['end']]),
            'count': Ethereum.objects.count(),
            'start': data['start'], }]
        self.ws.send(str(json.dumps(data1)))
        print(data)
    def on_close(self, reason):
        print(reason)
Итак, мы можем обращаеться к серверу /chart/start=xxx&end=xxx

Т.е из клиента я могу обращаться к серверу sendMsg(0, 100), sendMsg(100, 200). Сервер возвращает data - массив записей с данными, которые я визуализирую, start - чтобы знать какой “сдвиг” я выбрал(для следующей итерации) и count - кол-во записей в таблице(для того, чтобы не пытаться забрать больше данных, чем имеется в таблице. Итак клиент, который просто в цикле до 10 забирает информацию с сервера с шагом 100. Что нужно? Нужно переделать это так, чтобы учитывалось count(кол-во записей в таблице). Но т.к вебсокеты асинхронные, я не могу устроить типа такого(упрощенная схема). Надо где-то хранить count(кол-во записей в таблице), чтобы можно было итерировать
 function getData(start, end) {
res = recvData() // забираем информацию с вебсокет сервера(def on_message)
for var i = res['start']; i < res['count']; i+=100 {
    getData(i, i + 100)
}
сам код скелетона, который просто выбирает 10 раз информацию с сервера.
       google.charts.load('visualization', '1.1', {
        'packages': ['corechart']
      });
      google.charts.setOnLoadCallback(drawStuff);
      var data;
      var options;
      var chart = null;
      function drawChart() {
        // Instantiate and draw our chart, passing in some options.
        if (chart == null) {
          chart = new google.visualization.AreaChart(document.getElementById('chart_div'));
        }
        chart.draw(data, options);
      }
      function drawStuff() {
        data = new google.visualization.DataTable();
        data.addColumn('string', 'zzz');
        data.addColumn('number', 'Count');
        // Set chart options
        options = {
          'title': 'Ethereum',
          // 'width': 400,
          // 'height': 300,
          vAxis: {
            gridlines: {
              color: 'red',
              direction: '-1'
            }
          },
        };
        var ws = new WebSocket('ws://' + window.location.hostname + ':8001/chart/');
        var wsSend = function(data) {
          if (!ws.readyState) {
            setTimeout(function() {
              wsSend(data);
            }, 100);
          } else {
            ws.send(data);
          }
        };
        // wsSend('{"count": 12, "offset": 0}');
        // обработчик входящих сообщений
        ws.onmessage = function(event) {
          if (event.data) {
            wsRecv(event.data);
          };
        };
        function sleep1(ms) {
          return new Promise(resolve => setTimeout(resolve, ms));
        }
        // get data from srv
        async function getData(start, end) {
          var start = start;
          var end = end;
          for (var i = 0; i < 10; i++) {
            console.log('start: ' + start + " " + 'end: ' + end);
            start += 100;
            end = start + 100;
            wsSend(JSON.stringify({
              "start": start,
              "end": end
            }));
          };
     };
        function wsRecv(msg) {
          var res = JSON.parse(msg);
          for (var i = 0; i < res[0]['data'].length; i++) {
            data.addRow([res[0]['data'][i]['date'], res[0]['data'][i]['cur_usd']]);
            console.log(res[0]['count']);
          };
          drawChart();
        }
        drawChart();
        getData(0, 100);
Но может это не правильный подход. Может есть смысл делать типа chanells, на него подписываться и если есть новые данные - слать клиенту? Если да, то как это сделать? Ссылки, примеры и тд интересуют
remoshka
Вот смотри: мы попадаем на /chart/auth - сервер выдает идентификатор клиенту. Далее какой-то скрипт должен смотреть в таблицу и смотреть есть ли там новые данные? Если да, то он должен их отдать клиенту. Для этого надо где-то хранить 1) id клиента 2) end_client - последние данные которые он выбрал 3) end_srv - сколько вообще данных. А клиент должен с какой-то периодичность ходить на /chart/get/ чтобы потом забирать данные у сервера на основании 1 2 3. Ну примерно так я понимаю всё это

если есть сущность chanell, то эта сущность должна обладать такими данными
1. название канала
2. идентификатор клиента
3. сколько данных клиент взял
4. сколько данных вообще

и дальнейшая реализация двух видов
1. клиент сам забирает информацию
2. сервер сам отдает информацию в chanell

если сущность chanell должна иметь эти данные, то они должны где-то храниться. Или в мемкеше или в редисе

и несколько функций:: основные
1. формирование идентификатора
а) выдача клиенту
б) сохранение в мемкеше
2. обновление данных сколько объектов в таблице
3. выдача информации клиенту сколько всего данных и сколько он взял(в случае если он сам будет забирать) или отдача клиенту инфы в chanell(подбираем с мемкеша данные и выдаем клиенту)

а как правильно чтобы сам клиент забирал данные или чтобы сервер отдавал данные - отдельный вопрос
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB