LINUX.ORG.RU

Сообщения hell_wood

 

Вопрос по архитектуре приложения

Форум — Development

Добрый день.

Есть приложение, которое состоит из, по сути, 3-ех основных частей: 1. Пользователи 2. Устройства 3. Очередь команд

Допустим, сущности «пользователи» и «устройства» общаются с ПО по TCP. Сущность «Очередь команд» некий объект, который хранит в себе команды полученные от «пользователя», которые потом передаются в «устройство», «устройство» выполняет команду и результат помещает обратно в «Очередь» из которой потом «пользователь» забирает результат.

Попробовал изобразить это в виду UML диаграммы: https://ibb.co/rxGwdGj

Возможно что-то изобразил не правильно, поэтому вот краткое описание:

class ServerUser : public IServerUser
{
private:
	IUser usersList;
	IQueue *queue;		// при создании объекта ServerUser передает указатель на объект Queue
public:
	void newUser()
	{
		user = new User(this); // в объект User передаем ссылку на объект сервера
		userList.append(user);
	}
	void sendCommand(int deviceId, string cmd)
	{
		queue->sendCommand(deviceId, cmd);
	}
	void gotAnswer(int userId, int string answer)
	{
		userList[userId]->gotAnswer(answer);
	}
}

class User : public IUser
{
private:
	IServerUser *server;
public:
	void gotAnswer(answer)
	{
		// ...
	}
	void eventSendCommand()
	{
		// получено событие от пользователя, что нужно отправить команду
		server->sendCommand(deviceId, cmd);
	}
}

class Queue : public IQueue
{
private:
	IServerUser *serverUser;
	IServerDevice *serverDevice;
public:
	void sendCommand(int deviceId, string cmd)
	{
		serverDevice->sendCOmmand(deviceId, cmd);
	}
	// аналогично для получения ответа
}

// классы ServerDevice и Device реализованы по подобию реализации ServerUser и User

Сейчас для того чтобы отправить команду, ответ на команду нужно вызывать метод сервера, который в свою очередь будет вызывать метод Queue. Если объект Queue в объекты User, Device, то тогда будет получаться меньше писанины, но так, по идее, нарушается слабая связанность классов User, Device и Queue. Какой вариант более предпочтителен?

 

hell_wood
()

Локализация web приложения

Форум — Development

Добрый день, вопрос скорее по «архитектуре» приложения. В общем, есть некое приложение фронт ReactJS, бэк Aiohttp (хотя какой именно стек, скорее всего, не важно). Aiohttp используется только для REST ессно. Где лучше размещать переведенный текст? Львиная доля текста есть только но фронте, но есть всякие сообщения об ошибках, которые приходят от бэка (ошибка сервера, ошибки валидации форм и т.п). Натыкался на совет, что на сервер вообще не должен выдавать «человеческие» строки, а выдавать только их коды, что-то типа «E_ERROR_MESSAGE_VALIDATE_FORM_NAME», а фронт уже сам у себя все разбирает. Как принято сейчас это делать?

 

hell_wood
()

Docker для разработки и деплоя компилируемого приложения

Форум — Development

Добрый день, прошу совета как организовать процесс разработки, некоего компилируемого приложения, например на плюсах. У приложения есть зависимости, которые нужно сохранить как для develop версии так и для production. Develop версия должна еще содержать разные утилиты, такие как valgrind, dbg и т.п

1. Создаем общий образ:

FROM ubuntu
# установка gcc как пример некой зависимости для приложения
# в реальном проекте там будут библиотеки и т.п
RUN apt install gcc

билдим его:

docker build -t common_image .

2. Дальше нам нужен develop образ:

FROM common_image
# ставим утилиты для разработки
RUN apt install valgrind

В develop версии нам надо править исходный код, для этого нужно подключать тома, тут как я понял удобно использовать будет docker-compose:

# docker-compose.develop.yml
version: "3"
services:
  develop:
    build: ./develop
    volumes:
    - ./src:/src

Для разработки выполняем команду:

docker-compose -f docker-compose.develop.yml run -it develop bash

Попадаем в контейнер в котором можем пересобирать приложение и использовать отладочные утилиты.

3. Для релиза создаем production образ:

FROM common_image
# с хост машины копируем исходники в новый контейнер
COPY ./src ./src
# собираем приложение из исходников 
# опускам моменты с созданием WORKDIR и прочего
RUN make

так же билдим этот контейнер:

docker build -t release_image .

Отправляем его на боевой сервер (или через push/pull) и там запускам с помощью docker-compose:

version: "3"
services:
  develop:
    image: release-image
    command: ./run_app
    volumes:
	# тома для настроек
    - ./settings:/settings
    restart:
      always

Оправдан ли такой способ? Сам с докером только начал разбираться поэтому прошу совета у опытных людей, заранее благодарен.

 

hell_wood
()

Помогите разобраться в Asyncio.

Форум — Development

Добрый день, решил попробовать поюзать aiohttp для вэбсокетов. Нашел примеры реализации простого сервера, с этим все более менее понятно. Но есть потребность работы в связке с RabbitMQ. Нашел aiopika. Запуск тестовых примеров, подключение, примем, отправка сообщений - все работает. Но как теперь подружить их вместе?

Как я вижу подобную реализацию: 1. До начала работы сервера нужно создать подключение к RabbitMQ, чтобы потом этот коннектор можно было передавать в другие таски. 2. Пример работы с вэбсокетами: https://github.com/samael500/aiochat/blob/master/aiochat/chat/views.py Класс (WebSocket) Тут в методе Get обрабатывается новое подключение клиента, один экземпляр этого класса - один клиент. 3. В этом же методе Get мне надо создать очередь и подписаться на нее (для каждого клиента создается отдельная очередь). 4. Слушать сообщения из очереди в этом методе не получится, т.к он слушает входящие данные по вэб сокетам, поэтому создаем таск, в котором будем слушать сообщения из очереди.

    #########
    if self.room.id not in app.wslist:
        app.wslist[self.room.id] = {}

    # генерируем имя очереди
    queue_name = uuid.uuid()
    asyncio.create_task(create_queue(queue_name))

    message = await app.objects.create(
        Message, room=self.room, user=None, text=f'@{user.username} join chat room')
    #######

И сам таск create_queue:

async create_queue(queue_name):
# Creating channel
    channel = await connection.channel()    # type: aio_pika.Channel

    # Declaring queue
    queue = await channel.declare_queue(
        queue_name,
        auto_delete=True
    )   # type: aio_pika.Queue

    async for message in queue:
        with message.process():
            print(message.body)

И столкнулся со следующими вопросами: 1. По идее нам нужен один коннект к RabbitMQ на весь сервер, поэтому до запуска сервера мы должны подключиться к RabbitMQ и потом этот коннектор передавать в таск create_queue. Верно? Но сам метод библиотеки aiopika должен вызываться в сопрограмме, например метод из либы aiohttp для получения сессии можно вызвать с помощью async with, тогда мы получаем коннектор, который спокойно можем передавать в другие сопрограммы, но вот как быть с aiopika? 2. Передача сообщения полученного в RabbitMQ в объект вэб сокета (класс WebSocket). В методе get мы просто создали и запустили таск, который будет слушать сообщения, но как он может оповещать клиента о получении сообщения? Коллбек? Но в asyncio подходе на сколько я понял коллбки это моветон.

С asyncio начал разбираться совсем не давно, учебные примеры, который встречаются в инете направленны, по сути, только на асинхронное получение данных с разных сайтов, в общем, рассматривают только одинаковые задачи, запущенные в разных сопрограммах.

 ,

hell_wood
()

Django валидация объекта

Форум — Development

Добрый вечер. Банальная ситуация. 2 модели:

  • 1. товар (имя, наличие на складе и т.п)
  • 2. продажа

При «продаже» «товар» должен быть в наличии иначе выкидывается ошибка. Вопрос где эту валидацию проводить? Как я понял с использованием Django-Rest-Framework всю логику работы с данными (валидация, корректировка данных) проводится в Serializer классе модели? Но если мы захотим не использовать Rest-Framework, а пользоваться обычной формой, то нам уже в классе формы надо прописывать валидацию? Но это уже дублирование кода.

В модели, как описано тут: https://docs.djangoproject.com/en/2.1/ref/validators/#writing-validators

Тут мы получаем только значение поля, но нет информации, о самом объекте.

Прошу совета, кто и как справляется с подобными вещами?

 

hell_wood
()

Django managment commands

Форум — Development

Добрый вечер. Пример ситуации. Есть проект на Django и есть некий сторонний сервис, который, должен отправлять некие данные в Django проект через, например, RabbitMQ. Чтобы получать данные из Rabbit'а пишем скрипт, который потом нужно интегрировать в Django проект. Ну и соответственно он (скрипт) должен иметь доступ к окружению django-проекта, для доступа к моделям, настройкам и т.п Как сейчас это сделано: 1. скрипт, который получает данные из RabbitMQ выполняется как managment command (python manage.py run_script) 2. чтобы скрипт работал в фоновом режиме использую супервизор runit.

Так-то все это крутится, работает. Но возник интерес, как кто-то реализует подобные вещи? Запуск скрипта через manage.py дает доступ к окружению проекта, общие модели, настройки и т.п - удобно. Но оправдано ли такое решение? В общем, прошу совета. Заранее спасибо.

 

hell_wood
()

Связь классов из разных потоков

Форум — Development

Добрый день. Есть проект на Qt. Некий сервер со сбором информации, грубо говоря, подключился к нашему серверу клиент, мы эту информацию должны записать куда-то в БД. Сам объект QTcpServer работает в отдельном потоке (назовем его ObjServer), объект для записи информации о клиентах работает, соответственно, в другом потоке (пусть будет ObjInfo). Как сейчас реализовано взаимодействие этих двух классов:

1. В объект ObjServer передается указатель на объект ObjInfo.

2. Когда нужно записать какую-то информацию о клиенте, то в методе объекта ObjServer вызывает публичный метод объекта ObjInfo.

3. В ранее вызванном методе ObjInfo вызывается InvokeMethod слота объекта ObjInfo, чтобы сама фактическая запись происходила уже в отдельном потоке.

Такой принцип работает, но получается слишком много дублирующего кода. Например, у нас может быть несколько видов информации о клиенте, с разными параметрами и для каждого подобного «чиха» нужно будет городить и публичный метод и слот. Можно, например, вызывать InvokeMethod из объекта ObjServer, но такое решение мне кажется не сильно красивым, что ли. В общем, как-то так, буду благодарен, за любой совет/пинок в нужную сторону. Спасибо.

 ,

hell_wood
()

Общий объект для нескольких потоков

Форум — Development

Добрый день, например, в приложении используются 2 класса(worker1 и worker2), которые работают в разных тредах и есть некий объект(store), доступ к которому должны иметь оба эти класса. Если нужно передать, что-то в этот объект (store), то можно просто воспользоваться слотами-сигналами, а если нужно что-то из этого store получить? Вариант, который приходит на ум: 1. передаем указатель на store каждому воркеру. 2. в методах store при получении каких либо данных юзаем мютекс.

Может есть другие варианты, как более правильно делать подобные вещи?

 

hell_wood
()

Несколько QTcpServer'ов

Форум — Development

Добрый день, есть приложение написанное на Qt для работы с Tcp подключениями по разным портам. В одном треде для каждого порта создается объект типа QTcpServer, кол-во слушаемых портов может от 10-15 шт. Не будет ли лишним оверхедом создавать в одном треде кучу объектов серверов? На сколько знаю один объект сервера может слушать только один порт. Как лучше подступиться к этому? Один тред - несколько объектов сервера или один тред - один объект сервера?

 

hell_wood
()

Повторение выполнения блока кода

Форум — Development

Добрый день, прошу совета, как можно реализовать подобную штуку: Есть некое устройство, с которым общается программа, скажем по COM порту. На это устройство в разный момент времени, в зависимости от текущего состояния, должны быть отправлены разные команды, устройство их получает и должно ответить на них. Есть некоторые состояния, когда последовательно можно отправить сразу несколько команд. Так же, нужно предусмотреть повторную отправку команд для текущего состояния, если ответа не было или был не корректный. 1. Для каждого состояния есть свой метод, в котором отправляются команды (если для конкретного состояния ожидается сразу последовательно несколько команд, то в этом методе сразу же и отправляем последовательно эти команды). 2. Дальше если пришел ответ на команду/команды и он корректный, то переходим в следующее состояние, если ответа нет, то повторяем текущий шаг. Вот и вопрос в том как лучше реализовать повторный вызов метода для текущего состояния? Пока сделал таким образом: Если был таймаут ожидания (время ожидания ответа истекло) или некорректный ответ, то с помощью switch/case в зависимости от текущего состояния дергаем соответствующий ему метод. Но решение с этими switch/case кажется каким-то громоздким, кто как реализовывал подобные решения?

 ,

hell_wood
()

Наследование от QTcpSocket

Форум — Development

Добрый день. Решил попробовать написать TCP сервер на Qt. За пример взял данную статью: https://habrahabr.ru/post/131472/

Там создается мапник со списком подключенных клиентов, указатели на объекты QTcpSocket. Но я хочу в этом мапнике хранить еще индивидуальную инфу по каждому клиенту, например, его айпи адрес, в общем, некие данные уникальные для каждого клиента. Наследоваться от QTcpSocket нельзя, потому что вызов методов nextPendingConnection() и sender() - в слоте получения данных по сокету возвращают QTcpSocket, а привезти этот тип к наследованному нельзя. Думал, определить свой класс свойством которого был бы объект типа QTcpSocket и при новом коннекте создавать этот объект, в его свойство прописывать уже объект QTcpSocket и уже этот (свой) класс добавлять в мапник. Но как-то уже сильно громозко вроде как получается. Кто что может посоветовать?

 

hell_wood
()

Python3 html to pdf

Форум — Development

Добрый день, кто какие либы использует для перевода html в pdf На python3? Вроде как, самая распространеная, xhtml2pdf на 3-ем python не работает, выдает ошибку еще при импорте:

import xhtml2pdf.pisa as pisa

Traceback (most recent call last): File «<stdin>», line 1, in <module> File «/home/hound/test/python/test_env/lib/python3.4/site-packages/xhtml2pdf/__init__.py», line 41, in <module> from xhtml2pdf.util import REPORTLAB22 File «/home/hound/test/python/test_env/lib/python3.4/site-packages/xhtml2pdf/util.py», line 302 raise Exception, «box not defined right way» ^ SyntaxError: invalid syntax

 

hell_wood
()

RabbitMQ «подписки»

Форум — Development

Добрый день, есть сервер, который делает публикации в Rabbit в определенные очереди. Есть клиент на Python , который эти очереди должен слушать. Во всех примерах для Python+RabbitMQ генерации подписки на очереди происходит до запуска «прослушки», но в какой-то момент времени нужно будет «подписаться» на еще какую-нибудь очередь, возможно ли это? http://pika.readthedocs.io/en/latest/examples/asynchronous_consumer_example.html

Вот например этот пример, но как мне добавить новую очередь не закрывая старую? Если, например, для Redis есть модуль tornadoredis в котором все это делается довольно тривиально, то с RabbitMQ не могу найти ничего аналогичного...

 ,

hell_wood
()

Qt и дизайн приложения

Форум — Development

Добрый вечер, есть потребность в написании графического приложения, в котором должны использоваться всякие красивые штуки, вроде блюра, прозрачности, затемления и т.п. В доке Qt написано, что он (Qt) поддерживает только HTML4. Значит Qt не подойдет для этой цели? Да и вообще как обычно «верстаются» оконные приложения?

 

hell_wood
()

Контроль версий и Qt

Форум — Development

Добрый день, кто как автоматизирует версии своего приложения? Возможно ли вообще с помощью git'а сделать так чтобы с новым комитом делался инркемент версии приложения (в самом .pro файле)?

 , ,

hell_wood
()

Bash regexp

Форум — Development

Добрый день, прошу помощи с bash'ем. В общем, пишу скрипт, который запускает некую программу и потом должен обработать, то что эта прога вывела на экран. Выводит она строку, что-то в духе: result: 0.1 Time: 9.0

Как можно выделить именно 2 этих числа?

 ,

hell_wood
()

Парсер Qt

Форум — Development

Добрый день, есть класс для работы с обработкой инфы от некоего устройства. Ему передается массив бинарных данных и он их парсит и потом выдает в зависимости от типа пакета соотвествующую структуру. Вопрос в том как красивее сделать передачу распарсенных данных от этого класса другим классам. 2 варианта: 1. Для каждого типа пакета делать свой сигнал, и в классе «приемщике» делать каждый слот под каждый сигнал. Каждый сигнал будет передавать соотвествующую структуру, а слот в свою очередь ее принимать. 2. Сделать один общий сигнал, в котором бы передавался тип пакета и указатель на данные, а в классе приемщики switch'ем делать преобразование указателя в зависимости от типа полученного пакета.

 

hell_wood
()

Опыт по git

Форум — Development

Добрый вечер, в общем есть гит репозиторий с проектом, но у этого проекта в один момент появилось «ответвление», по сути из одного приложения получилось 2, которые по своему развиваются и т.п Как лучше поддерживать подобный репозиторий? Сейчас я просто сделал отдельную ветку для ответвления, а прежную версию развиваю в master ветку, кто как делает в подобных ситуациях?

 

hell_wood
()

Qt динамическая связка сигналов-слотов

Форум — Development

Добрый вечер, есть массив из n-го кол-ва QTimer каждый из них запускается в разное время. Чтобы не плодить повторяющийся код хочу чтобы слот для приема этих таймеров был один. Как мне в слоте узнать для какого именно таймера он был вызван?

UPD: есть некая структура, которая содержит таймер, так вот таких структур может быть n-ое кол-во и в слоте нужно узнать для какой именно структуры был вызван слот таймаута.

 

hell_wood
()

rsync и несколько машин

Форум — Admin

Доброго вечера, нужно делать синхронизацию некой директории с помощью rsync для нескольких серверов. Все эти сервера забиты в config файле с в директории .ssh юзера под которым будет запускать rsync.

rsync -azvP ~/test_dir server1:~/some_projects

запускает синхронизацию для server1, а если таких серверов несколько штук, как проще автоматизировать?

 

hell_wood
()

RSS подписка на новые темы