gsbelarus / gdmn Goto Github PK
View Code? Open in Web Editor NEWGDMN — это революционная облачная платформа с открытым исходным кодом для создания приложений автоматизации учета/управления на предприятии.
License: MIT License
GDMN — это революционная облачная платформа с открытым исходным кодом для создания приложений автоматизации учета/управления на предприятии.
License: MIT License
У ФБ есть режим локального подключения, когда вызывающий процесс и сам сервер физически выполняются на одной машине. В этом случае не указывается имя сервера и номер порта. Локальное подключение быстрее так как не задействуется TCP/IP стек, а процессы общаются между собой другими средствами.
Посмотреть возможность подключения через встроенный сервер (embedded). В этом случае отдельный процесс сервера ФБ вообще не запускается.
Сейчас после потери соединения объект класса AConnection говорит о том, что соединение все еще есть, но вызов любых методов взаимодействия кидает ошибку Error writing data to the connection.
или Error reading data to the connection.
Нужно добавить обработку этой ошибки в каждый метод взаимодействия и помечать соединение как разорванное, либо автоматически делать reconnect, если это возможно.
Иногда, стресс тест валится из-за ошибки сравнение дат. Причем может отработать и час и 10 часов без ошибок.
Что происходит:
Ошибка происходит в пункте 4. Разница между датами небольшая - 1 час.
Было бы удобно для объекта Connection иметь метод, куда передается просто запрос и выполняется. При этом транзакция создается, стартует и завершается автоматически.
Опциональный параметр -- параметры транзакции.
Вопрос в оптимальности. Надо посмотреть, что придумало Microsoft в fabric-ui, как и на что они заменили глобальные enum.
Единственное, что чуть-чуть можно подождать до очередной версии TS. Возможно, что они как-то решат эту проблему на уровне компилятора.
Тут непонимание проблемы! Миграция структуры БД не имеет ничего общего с переносом пользовательских структур данных (пространства имен в терминах Гедымина). Соответственно никаких gdmn-orm и gdmn-bridge не требуется. ТОЛЬКО ПРЯМОЕ ОБРАЩЕНИЕ К БД через gdmn-db. И не более!
Речь идет об апгрейде системной структуры базы данных, необходимой для функционирования платформы.
Переписать ТЗ и переделать.
Существующие БД подправить вручную.
Если во время открытия соединения происходит ошибка, connection pool пытается открыть соединение сново и если ошибка не исчезает, то это приводит к зависанию.
Проблема в библиотеке для организации connection pool, т.к. в ней нет ограничения на количество попыток. См.
Если мы упремся в производительност сервера nodejs, когда часть бизнес логики будет крутиться в нем, а не в браузере, будет плохо.
Как вариант -- использование кластера nodejs.
Надо посмотреть, будет ли в нем такая возможность:
Идея такая, что один процесс nodejs будет работать с одной базой данных. В этом случае тяжелый код в этом процессе никак не притормозит другие процессы.
Следует добавить механизм точного определения типа атрибута entity.
Сейчас они определяются путем перебора через instanceof всех возможных типов сверху вниз по иерархии. Это может вызвать ошибки т.к если нужен тип находящийся в середине иерархии, то при определении совпадения нужного типа, нужны дополнительные проверки для отсечения нижних типов.
Нужно определить что атрибут имеет тип EntityAttribute
.
Иерархия наследования:
`Attribute`
|
`EntityAttibute`
_______________|_______________
| | |
`DetailAttibute` `ParentAttribute` `SetAttribute`
При совпадении instanceof с типом EntityAttibute
нам нужно убедится, что тип не является DetailAttibute
или каким-либо другим.
Это очень не удобно, особенно если в будущем появятся дополнительные типы.
Добавить enum AttrType {}
со всеми типами и поле type: AttrType
в Attribute
наверное уже забыл )) какую роль все-таки выполняет babel в gdmn-front?
вот у меня проект gdmn-grid-demo. там используется:
react + redux + redux-thunk + gdmn-recordset + gdmn-grid + microsoft ui
то есть вс тоже самое, что и в gdmn-front за исключением stomp, websocket и observable.
все прекрасно компилируется без babel. настройки вебпака самые минимальные:
module: {
rules: [
{
test: /\.(ts|tsx)$/,
loader: 'ts-loader'
},
{ enforce: "pre", test: /\.js$/, loader: "source-map-loader" },
{
test: /\.css$/,
use: [
{ loader: "style-loader" },
{ loader: "css-loader" }
]
}
]
},
hot reloading работает нормально.
при этом, хотя проекты сопоставимы по размерам, время rebuild различается кардинально.
35 сек для gdmn-grid-demo и 157 сек для gdmn-front.
и еще там нет проблемы с exported enum, которая возникает, когда в babel используется опция forceIsolatedModules: true.
Я думаю надо тщательно подумать и, если в бабеле нет нужды, то избавиться от него.
Два транспайлера, один сидит на другом, нам совершенно ни к чему.
Записав одно значение (930687.8979) в поле с типом FLOAT после чтения получаем другое (930687.875).
Нужно разобраться в чем проблема и исправить
Сейчас FieldDefs это массив. Скорее всего надо переделать его в объект, так как внутри рекордсета часто идет обращение по имени поля. Сейчас это find -- простой перебор по массиву.
Если во время открытия соединения происходит ошибка, connection pool пытается открыть соединение сново и если ошибка не исчезает, то это приводит к зависанию.
Проблема в библиотеке для организации connection pool, т.к. в ней нет ограничения на количество попыток. См.
Быть готовым к получению одинаковых сообщений, что на клиенте, что на сервере.
Такое может произойти когда клиент или сервер послал сообщение и пока ждал подтверждение произошел обрыв соединения. В тоже время само сообщение успело дойти до адресата.
В этой ситуации тот кто послал сообщение и не дождался подтверждения, после переподключения сново пошлет это же сообщение.
Пример:
>>> SEND // любая задача, например бэкап базы
-lost connection- X<<< RECIEPT // подтверждение получения
>>> CONNECT // переподключение
>>> SEND // это сообщение должно игнорироваться сервером, т.к задача уже создана
<<< RECEIPT // подтверждение получения
К чему лишний код?
await this._getDDLHelper().addColumns(tableName, [{name: fieldName, domain: domainName}]);
await this._insertATAttr(attr, {relationName: tableName, fieldName, domainName});
Наворачивание сложности, там где это не надо, не входило изначально в тз и не просилось, приводит к тому, что типов у нас сейчас нет...
И как разобраться с этим я не знаю.
Единственный вариант, который я вижу -- удалять слой за слоем. Возвращаться к самому началу. Добиваться правильных типов там и только потом, осторожно шаг за шагом добавлять функционал, на каждом шагу проверяя, что типы сохраняются и работают как надо.
Сейчас внутри рендерера отдельно получается строка из набора данных, но когда формируется текст клетки для отображения вызывается метод getString у рекорд сета, который внутри опять получит строку данных. Учитывая, что immutable каждый раз создает новый объект это лишние действия, нагружающие систему.
Observable это и так уже абстракция. Зачем на верх еще какой-то свой бридж? Ради чего? Это только портит, замедляет и усложняет.
Продолжаем с языковой частью. Сейчас мы можем разбирать фразу "Покажи всех клиентов из Минска".
Добавим к ней еще и сортировку. Сортировка задается отдельным предложением. Например:
Для выполнения надо будет:
Сейчас перемещение происходит по action applySortDialog, т.е. после вызова диалогового окна. А надо чтобы и при вызове из программного кода, тоже происходило.
внутри ERModel не должно быть никаких транзакций. Она должна быть вообще агностической к базе данных. Это дело bridge -- взаимодействие со структурой конкретной реляционной или не реляционной БД. Надо убирать и переделывать. А получается так потому что сначала надо хотя бы на бумаге прорировать схему взаимодействия объектов/подсистем.
После последних изменений в репозитории куча предупреждений при yarn rebuild проекта gdmn-grid-demo. Причем вчера их еще не было. Т.е. можно подозревать какие-то из последних комитов:
WARNING in C:/Golden/NS/gdmn/node_modules/object-assign/index.js
There are multiple modules with names that only differ in casing.
This can lead to unexpected behavior when compiling on a filesystem with other case-semantic.
Use equal casing. Compare these module identifiers:
- c:\Golden\NS\gdmn\node_modules\source-map-loader\index.js!C:\Golden\NS\gdmn\node_modules\object-assign\index.js
Used by 7 module(s), i. e.
c:\Golden\NS\gdmn\node_modules\source-map-loader\index.js!C:\Golden\NS\gdmn\packages\gdmn-grid\node_modules\react\cjs\react.development.js- c:\Golden\NS\gdmn\node_modules\source-map-loader\index.js!c:\Golden\NS\gdmn\node_modules\object-assign\index.js
Used by 4 module(s), i. e.
c:\Golden\NS\gdmn\node_modules\source-map-loader\index.js!c:\Golden\NS\gdmn\src\gdmn-grid-demo\node_modules\react\cjs\react.development.js
@ C:/Golden/NS/gdmn/node_modules/object-assign/index.js
@ C:/Golden/NS/gdmn/packages/gdmn-grid/node_modules/react/cjs/react.development.js
@ C:/Golden/NS/gdmn/packages/gdmn-grid/node_modules/react/index.js
@ C:/Golden/NS/gdmn/packages/gdmn-grid/dist/src/GridPanel.js
@ C:/Golden/NS/gdmn/packages/gdmn-grid/dist/src/index.js
@ ./src/app/App.tsx
@ multi ./src/app/App.tsx webpack-hot-middleware/client
Вот, если мы в дополнение к написанному добавим:
И у нас получится сделать всю систему легковесной и быстрой, то мы получим сразу:
Останется только использовать данный объект внутри других объектов, там где происходят интересующие нас процессы.
Механизм взаимодействия Query из todo0006 с серверной частью перекликается со списком задач, который оговаривался в todo0005. Я думаю вполне логично объединить их в один механизм, а не делать два параллельных. Для этого достаточно расширить функционал команды. Теперь это не только доступ к данным, но и функциям системы (бэкап/рестор) и к алгоритмам (запуск макросов).
Тут напрашивается два варианта. Первый, это реализовать правила формальной грамматики для отражения однородных членов. Проблема в том, что эти правила придется дублировать в каждой грамматике, для каждого типа предложения (которых у нас будут многие десятки). Можно конечно автоматизировать данный процесс, но...
Второй -- сначала токенизировать предложение и найти однородные члены. Далее, заменить их на один токен и где-то запомнить, что на самом деле их там много. После разбора предложения, в визиторе, в момент построения дерева объектов фразы, использовать сохраненную информацию.
Для простых форм не нужен. Для сложных... скорее всего тоже не нужен, так как у нас будет свой механизм, подобный механизму поддержки Tdlg_G в Гедымине. Накладывать один на один три механизма: редукс -> редукс-форм -> наш -- это неоправданное усложнение кода, которое приведет к трудновыявимым ошибкам, потере времени на программирование и головной боли с обновлением зависимостей.
К тому же, редукс-форм дублирует поля формы в редусере и дергает редусер на каждое изменение каждого поля. Мы будем использовать gdmn-recordset для хранения данных Entity на клиенте и не ясно, как это будет сочетаться с редукс-форм. Надо ли будет копировать данные из рекод-сета в редусер формы, а потом обратно? Это совершенно ненужная последовательность действий.
Наш проект рассчитан не на один год и пока у нас мало кода, нам доступна роскошь простого обновления до новейших разработок в мире реакта и редукса.
В ближайшее время будет выпущен реакт 17 (с hook-ами и другими улучшениями) и реакт-редукс 6.
Многие библиотеки станут не нужны (recompose, reselect), а многие должны быть изменены (redux-form). Это еще одна причина, почему хотелось бы сейчас тащить в проект минимум зависимостей -- чтобы они не стали препятствием по обновлению ключевых библиотек в будущем.
Создать тесты на основе самой большой нашей базы:
Количество итераций должно быть значительным. Время выполнения теста не менее 10-12 часов.
Пользователь видит на экране (в гриде) отформатированные числовые значения и даты. Соответственно, он ожидает, что поиск и фильтрация будут брать эти значения, а не простое преобразование в строку.
И если из-за одной отсутствующей все будет падать, то я вообще никогда на подключусь к Гедымину.
Во-первых, какая структура этой бд? В Гедымине у нас есть SQL файлы, а тут все зашито в код?
Во-вторых, ее структуру со временем тоже придется апгрейдить и это лишняя головная боль на ровном месте.
В-третьих, чтобы влезть в нее понадобится сторонняя (и платная) утилита IBExpert. И я даже не знаю, существуют ли какие либо утилиты под Mac или Linux.
В-четвертых, как переносить информацию из базы в базу, как объединять? А это обязательно понадобится разработчикам у каждого из которых может быть свой локальный сервер баз данных и свой gdmn-back.
В-пятых, понадобится сервер для доступа к этой базе, который может конфликтовать с основным сервером баз данных предприятия, или, даже если не будет конфликтовать, то мы будем подключаться под учетной записью, пароль которой будет где, у нас в коде прописан?
Надо использовать JSON файл для этих целей, который снимает все вышеуказанные проблемы.
И, перед тем как переделывать, написать и обсудить TODO, чтобы потом в третий раз не пришлось переделывать.
Для этого у Entity
должны быть типы:
Так же поддержку деревьев нужно добавить в gdmn-er-bridge.
ERModel
в физическую структуру БД и обратноошибка.
Я еще не залазил в код, просто спрошу. Сделанный алгоритм устойчив к повторному вызову. Например, в Гедымине я периодически проверяю -- очищаю таблицу с информацией о версиях БД и за пускаю программу. Все процедуры проходят заново и не должно быть ошибок. Т.е. каждый код сначала проверяет, может уже такие объекты есть, и только потом выполняет заданные действия по апгрейду.
Надо сесть и аккуратно написать диаграмму состояний для клиентской и серверной частей и диаграмму последовательности. Пока наш протокол еще не стал слишком сложным.
Можно просто текстом сделать. Я сам оформлю как надо.
yarn build проходит, а вот yarn start -- нет.
ERROR in ./src/app/index.tsx
Module build failed (from C:/Golden/NS/gdmn/node_modules/react-hot-loader/webpack.js):
TypeError: Cannot read property 'indexOf' of undefined
at transform (C:\Golden\NS\gdmn\node_modules\react-hot-loader\dist\webpack.development.js:70:14)
at Object.transform$1 (C:\Golden\NS\gdmn\node_modules\react-hot-loader\dist\webpack.development.js:107:14)
@ multi ./node_modules/error-overlay-webpack-plugin/lib/entry.js (webpack)-dev-server/client?http://localhost:9090 (webpack)/hot/dev-server.js ./src/app/index.tsx app[3]
i 「wdm」: Failed to compile.
× 「atl」: Child process failed to process the request: Error: Debug Failure. Invalid cast. The supplied value [object Object] did not pass the test 'isJsonSourceFile'.
Сейчас после потери соединения объект класса AConnection говорит о том, что соединение все еще есть, но вызов любых методов взаимодействия кидает ошибку Error writing data to the connection
. или Error reading data to the connection.
Возможно следует добавить обработку этой ошибки в каждый метод взаимодействия и помечать соединение как разорванное, либо автоматически делать reconnect, если это возможно.
Проверить.
Насколько я понимаю, структура исходников будет следующая:
\
\packages
\gdmn-db
\dist
\node_modules
\src
...
\gdmn-orm
\dist
\node_modules
\src
...
\src
\gdmn-front
...
\gdmn-back
...
Если не так, поправьте меня.
Предположим, что gdmn-orm использует gdmn-db. Т.е. содержит операторы import { something } from 'gdmn-db';
Что именно подключается в данном случае?
а) код Typescript из папки \src\packages\gdmn-db\src
б) код Javascript + .d.ts из папки \src\packages\gdmn-orm\node_modules\gdmn-db
в) код Javascript + .d.ts из папки \src\packages\gdmn-db\dist
Если один из последних двух пунктов, то кто и в какой момент компилирует код Typescript в Javascript? А если п. б) то еще и переносит измененные файлы из папки dist, куда их помещает компилятор typescript в папку node_modules?
Или по другому: если в одном окне редактора у меня открыт файл с классом из проекта gdmn-db, а во втором -- файл из gdmn-orm, который использует этот класс. Я делаю изменения в gdmn-db. В какой момент они станут известны в gdmn-orm?
а) сразу, без сохранения файла (как сейчас происходит при работе в рамках одного проекта).
б) после того как я сохраню изменения gdmn-db на диске.
в) после сохранения изменений на диске и выполнения некоторых команд в терминале.
Останется ли возможность выполнять команды tsc, npm run build, npm t для каждого проекта в отдельности?
Например, выполнить npm run build внутри папки gdmn-front чтобы получить готовые к размещению на вебсервере файлы.
Насколько я понимаю, теперь все исходники будут находиться в одном гигантском репозитории и если появится сторонний разработчик, который захочет присоединиться, например, к проекту gdmn-nlp, то ему всё равно придется качать все исходники и устанавливать ВСЕ библиотеки для всех проектов?
Если же мы хотим иметь отдельный репозиторий для gdmn-nlp, то только на таких условиях:
Существуют ли еще решения?
(Про сабмодули я читал, что у них много существенных ограничений, из-за которых они не подойдут нам. Например, сабмодули могут существовать только внутри ветки мастер и т.п.)
Конечно, мы можем составить полностью свой формат. Например, сообщение будет выглядеть как JSON объект такой структуры:
{
version: "1.0",
messageType: "data-packet",
messageBody: {
recordSet: [
{record1},
{record2},
...
{recordN}
]
}
}
Но, почему бы не придерживаться одного из известных форматов? Вреда не будет, а польза может и появиться со временем. Это как пространства имен в Гедымине в формате YAML. Мы нигде, никогда не использовали никакой сторонней программы, которая бы что-то делала с нашими ПИ и требовала формата YAML. Т.е. мы вполне могли изобрести свой личный формат.
Транспорт. Это протокол низового уровня, который будет передавать наши сообщения. Он ничего не знает о нашей бизнес-логике и умеет только работать с сетью. Для этих целей мы будем использовать готовые решения/библиотеки. Например, WebSocket, HTTP, HTTP2 и т.п.
Клиент -- программа работающая в браузере или на мобильном устройстве. Наш проект gdmn-front.
Сервер -- программа, облуживающая запросы от клиента. Наш проект gdmn-back.
Обмен данными и командами между клиентом и сервером осуществляется ТОЛЬКО посредством посылки-приема сообщений.
Очередь сообщений это массив JavaScript или объект, включающий в себя такой массив. Сообщения помещаются в массив, после чего механизм пересылки начинает их передачу на сервер. Если в данный момент времени нет соединения, то механизм ждет, пока оно появится. Насколько это возможно, клиент продолжает работу даже если в очереди есть неотосланные сообщения.
На сервере тоже ведется очередь сообщений, куда сетевой механизм помещает принятые сообщения, и откуда механизм выполнения берет информацию чем ему заниматься. При пересылке сообщения на клиента тоже может возникнуть ситуация, когда соединение отсутствует. В этом случае сетевой механизм сервера ждет и пересылает сообщение позже.
Протокол -- это набор правил, регламентирующих порядок обмена сообщениями. Например:
Сообщение, помещенное в очередь получает статус ready-to-send.
Сообщение переданное на сервер и помещенное в очередь для обработки получает статус in-queue.
Сообщение полученное с сервера получает статус recieved.
Выше -- это только пример. Сам протокол и надо сейчас разработать, задокументировать и проиллюстрировать схемами.
Возможно, в будущем, мы придем к системе, где будет использоваться несколько баз данных. Тогда сообщения можно рассылать нескольким серверам и тут нам может понадобится отдельный, внешний брокер и т.п. Именно по этому я и говорю, что по возможности мы должны следовать стандартам в формате сообщения. И, возможно, реализовывать наш протокол максимально близко к неким существующим протоколам.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.