A7 Data Server: управление данными онлайн

Привет, Хабр!

Все записи митапа доступны здесь: https://youtu.be/kJS5rfCWmPI

Мы пилотируем публикации с расшифровками докладов, прозвучавших на PiterJS.
Так как это первый опыт, будем рады услышать конструктивную критику и предложения по улучшению.

Смотрите видео и слайды, а за расшифровкой — добро пожаловать под кат.

Доклад и расшифровку подготовил Андрей Логинов, технический директор в «A7 Systems».

Начнем

Fast Big Data Server — cервер для больших быстрых данных. Изначально A7 DS предназначен для Digital Twin, управления ролями и паттернами данных. Но это не всё, что он умеет.

Что внутри.

Давайте посмотрим:

  • Объектная база данных
  • Темпоральная (хронологическая) база данных
  • Виртуальная машина JavaScript (если быть честным, то js-like языка)
  • Система уровня доступа
  • Cервер приложения

Объектная база данных помимо типизации и наследования идеревьевмеет несколько особенностей:

  • поддержка деревьев
  • поддержка графов
  • монтирование и ссылки
  • Spaces (пространства)
  • поддержка биндинга (реактивность)

Space

Самое необычное здесь — это Space (пространство).
Space — это экземпляр типовой рабочей области.

Space включает:

  • data (данные)
  • shared-data (общие данные для нескольких пространств. Например, погода или курс валюты)
  • roles (owner, users, groups)
    То есть, Space является достаточно изолированным от сервера A7 DS и других Spaces пространством.

Как пользоваться

Теперь вопрос: как этим пользоваться. Это наверное самый главный вопрос.
Создадим небольшое мобильное приложение на ECMAScript.

Нам потребуется:

  • Минимальное знание С++. (возможно в рамках школьной программы)
  • Знание ECMAScript и QML (Qt)
  • Android NDK (просто чтобы скомпилировать это)

По моему ощущению, лучшие примеры всегда связаны с деньгами, поэтому попробуем создать онлайн семейный кошелёк)).

Создадим объекты в объектной базе данных. Точнее мы создадим типы. Для описания объектов удобнее использовать редактор, но мы “не такие”, и создадим описание объектов в JSON.

Сначала создадим объект деньги, в котором у нас есть есть наличные, кредитка, и итоговая сумма:

{   "name": "Money",   "fields": [     {"name": "card","fieldtype": "value","datatype": "double", "def": 0},     {"name": "cash","fieldtype": "value","datatype": "double","def": 0},     {"name": "sum","fieldtype": "formula","datatype": "double",       "def": "card+credit"}   ] }

Поля card и cash это простые значения (по умолчанию равные 0), можно записать немного короче:

{"name": "card","value": 0.0}, {"name": "cash","value": 0.0}

Поле sum это формула (привет реактивность!), тоже можно записать немного короче:

{"name": "sum","formula":"card+credit"}

Теперь мы создадим пару из юноши и девушки.

{   "name": "Pair",   "fields": [     {"name": "boyfriend","fieldtype": "value","datatype": "Money", "def": "Money"},     {"name": "girlfriend","fieldtype": "value","datatype": "Money","def": "Money"},     {"name": "sum","fieldtype": "formula","datatype": "double",       "def": "boyfriend.sum+girlfriend.sum"}   ] }

Поле sum (снова привет реактивность!), стало включать ссылки на подобъекты:

{"name": "sum","formula":"boyfriend.sum+girlfriend.sum"}

Теперь, при каждом изменении любой цифры мы автоматически будем получать пересчет текущего баланса.

Но нам полезно добавить немного истории.

{"name": "history","fieldtype": "list", "list":{"datatype": "History"}}

В короткой записи

{"name": "history", "list":{"datatype": "History"}}

Ну и сам объект истории. Кто, что, и сколько изменил.

{   "name": "History",   "fields": [     {"name": "who","fieldtype": "value","datatype": "string", "def": “”},     {"name": "which","fieldtype": "value","datatype": "string","def": “”},     {"name": "delta","fieldtype": "value","datatype": "double","def": 0}   ] }

Добавим триггеров к Pair:

"functions": [{"functiontype": "before",       "arguments": [boyfriend.cash],       "code": "..."    } ]

И сам код триггера:

{   var historyItem= history.add(new History());   historyItem.who=”boyfriend”;   historyItem.which=”cash”;   history.delta=value-boyfriend.cash;   return true; }

По аналогии добавим триггеры для boyfriend.card, girlfriend.card, girlfriend.cash.

Поскольку мы хотим сделать наше приложение большому количеству пар, то создаем типовое пространство SpacePair, и делаем его корневым элементом Pair.
Добавляем двух пользователей по умолчанию
Girl
Boy

Собственно все, генератор пространств для контроля кошельков готов.

Добавим несколько пространств. При добавлении пространства автоматически создается область данных (и сами данные со значениями по умолчанию). Также создаются предустановленные пользователи и группы (для пространства).
Каждое пространство имеет своих пользователей и свои группы.

Начинаем делать клиент:

Добавим в проект библиотеки

android {     debug{         LIBS+= ../A7DS/Libs/android/libA17EDboClientBaseBind.a         LIBS+= ../A7DS/Libs/android/libA17ClientLibBind.a     }     release{         LIBS+= ../A7DS/Libs/android/libA17EDboClientBaseBin.a         LIBS+= ../A7DS/Libs/android/libA17ClientLibBin.a     } }

Немного поправим файл main.cpp

#include <QApplication> #include <QQmlApplicationEngine> #include <QVariant> #include <QQmlEngine>  // Добавим ссылку на *.h файлы #include "../A7DS/A17EBase/A17EDboClientBaseBin/a17edboclientbasebin.h"  int main(int argc, char *argv[]) {    QApplication app(argc, argv);    QQmlApplicationEngine engine;     // Создаем клиент для A7DS    A17EDboClientBaseBin*client=new A17EDboClientBaseBin(engine,&app);     // Инициализируем клиент для A7DS    client->init(engine);     // Дальше стандартный код     engine.load(QUrl(QLatin1String(QString("qrc:/main.qml").toLatin1())));    return app.exec(); }

На этом C++ часть закончена, и мы можем переходить к QML.

Сначала создадим пару компонентов.

Добавим компонент для отображения данных

MyLabelView.qml

import QtQuick 2.7 import Astra.Dbo 17.0  Item {id: viewItem    property alias field: field    property string label: "что и кто"    width: parent.width    height: 100     DboField{        id: field    }    Text {        id: labelItem        text: viewItem.label        anchors.left: parent.left        anchors.right: parent.horizontalCenter        anchors.top: parent.top        anchors.bottom: parent.bottom    }     Text {        id: valueItem        text: field.value        anchors.right: parent.right        anchors.left: parent.horizontalCenter        anchors.top: parent.top        anchors.bottom: parent.bottom    } }

MyLabelEdit.qml

import QtQuick 2.7 import Astra.Dbo 17.0  Item {id: viewItem    property alias field: field    property string label: "что и кто"    width: parent.width    height: 100     DboField{        id: field    }    Text {        id: labelItem        text: viewItem.label        anchors.left: parent.left        anchors.right: parent.horizontalCenter        anchors.top: parent.top        anchors.bottom: parent.bottom    }     TextInput {        id: valueItem        text: field.value        anchors.right: parent.right        anchors.left: parent.horizontalCenter        anchors.top: parent.top        anchors.bottom: parent.bottom        onEditingFinished:{            field.value=text;        }    } }

Теперь соберем главное окно
MyLabelEdit.qml

import QtQuick 2.7 import Astra.Dbo 17.0 import QtQuick.Controls 1.5  {id:appWindow     visible: true     width: 640     height: 480     property var component;     property var sprite;  ApplicationWindow {id: viewItem property alias field: field property string label: "что и кто" property string host: "127.0.0.1" //// адрес A7 DS property int port: 8989 // порт A7 DS property string isBoy: (dboconnection.login=="Boy") property var myselfMoney: (isBoy)?boyfriend:girlfriend property var myfriendMoney: (!isBoy)?boyfriend:girlfriend  /*  Данные, которые начнут автоматическую синхронизацию с сервером после соединения */  DboObject{id:boyfriend parentObject: rootData         parentFieldName:  "boyfriend" } DboObject{id:girlfriend        parentObject: rootData         parentFieldName:  "girlfriend" } DboModel{id:history        parentObject: rootData         parentFieldName:  "history" }  /* То, что мы отображаем, если нет соединения с сервером A7 DS */ Column{       z: 10      visible: (! dboconnection.isConnect)      anchors.fill: parent      TextInput{id:login width: parent.width             height: 100      }      TextInput{id:password width: parent.width height: 100      }      Button{id:btn width: parent.width height: 100 text: ”Подключиться” onClicked: dboconnection.connectToDbo( login.text, password..text,            viewItem.host,            viewItem.port); }    }     SwipeView{         anchors.fill: parent         currentIndex: 1         /// Здесь таблица отражающая историю изменений         Page{                   ListView{         model: history         delegate: Text{         text: model.who+” ”+model.which+” ”+model.delta }       }                 }      /// Здесь список дающий текущую картину             Page{                 Column{             anchors.fill: parent                     MyLabelEdit{id:myCash; label: “мои наличные”                 field.name: “cash”; field.parentObject: myselfMoney         }                     MyLabelEdit{id:myCard; label: “моя карта”                 field.name: “card”; field.parentObject: myselfMoney         }                    MyLabelView{id:mySum; label: “все мои деньги”                 field.name: “sum”; field.parentObject: myselfMoney         }                    MyLabelView{id:myfriendCash; label: “наличные друга”                 field.name: “cash”; field.parentObject: myfriendMoney         }                     MyLabelView{id:myfriendCard; label: “карта друга”                 field.name: “card”; field.parentObject: myfriendMoney         }                    MyLabelView{id:myfriendSum; label: “все деньги друга”                 field.name: “sum”; field.parentObject: myfriendMoney         }                    MyLabelView{id:mypairSum; label: “все наши деньги”                 field.name: “sum”; field.parentObject: mypairMoney         }      }             }         }     }     Text {        id: labelItem        text: viewItem.label        anchors.left: parent.left        anchors.right: parent.horizontalCenter        anchors.top: parent.top        anchors.bottom: parent.bottom    }     TextInput {        id: valueItem        text: field.value        anchors.right: parent.right        anchors.left: parent.horizontalCenter        anchors.top: parent.top        anchors.bottom: parent.bottom        onEditingFinished:{            field.value=text;        }    } }

Эмм. “А как же обещанные Digital Twin, и прочие ништяки?” – спросит внимательный читатель.
“Биндинг это конечно хорошо, но где монтирование и графы?” – добавит он.

Это справедливые вопросы, и на ответы на них будут дан в следующих статьях ;).

FavoriteLoadingДобавить в избранное
Posted in Без рубрики

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *