Citeck Applications Microservice
The Citeck platform is built on artifacts, allowing functionality to be extended by writing new artifacts without affecting the existing functionality.
An artifact is a unit of configuration in the Citeck system. Examples of artifacts include: a form, journal, type, section, rights matrix, action, etc.
The microservice that manages the deployment of applications and artifacts is called ECOS Applications, or ecos-apps for short.
Microservice goals:
Artifact versioning. All changed artifacts are saved as separate revisions that cannot be modified.
Delivering artifacts from all microservices to the target one (for example, delivering forms from ecos-integrations, ecos-model, alfresco to ecos-uiserv).
Dependency tracking. If an artifact depends on another artifact, the microservice maintains the deployment order.
Managing patches for artifacts.
The artifact deployment process looks roughly as follows:
Simple Description
After a new application appears on the network (alfresco in the diagram), 3 stages occur:
Types request.
Receiving artifacts.
Deploying artifacts.
Detailed Description
The microservice periodically polls everyone connected to Rabbit MQ
While no one has connected to Rabbit, nothing happens.
When the first microservice appears, it returns a response to ECOS Apps about its presence.
After that, ECOS Apps sends a request for the types the microservice is interested in.
Having received the list of types, ECOS Apps sends a request for artifacts to all registered microservices.
Having received the necessary artifacts, ECOS Apps checks whether they have changed since the last load, and if not, does nothing.
If it turns out that the artifacts have changed, they are sent to the target microservice for deployment.
All interaction occurs via Rabbit MQ and the ecos-commands library.
ECOS Apps log when three microservices are detected (including itself):
Detected new application 'eapps' with EcosApps: [EcosAppInfo(id=eapps, lastChanged=1584425736433)]
// Обнаружено новое приложение (микросервис). eapps не содержит типов артефактов. Поэтому грузить нечего
Detected new application 'uiserv' with EcosApps: [EcosAppInfo(id=uiserv, lastChanged=1584425751061)]
// В uiserv уже есть 4 типа (форма, дашборд, действие и меню). Мы должны пройтись по всем зарегистрированным микросервисам и опросить есть ли у них модули с такими типами:
Loaded 1 modules from 'eapps' EcosApp: 'eapps' type: 'ui/form'
// нашли одну форму в eapps
Loaded 1 modules from 'eapps' EcosApp: 'eapps' type: 'ui/action'
// нашли одно действие в eapps
Loaded 0 modules from 'eapps' EcosApp: 'eapps' type: 'ui/menu'
Loaded 0 modules from 'eapps' EcosApp: 'eapps' type: 'ui/dashboard'
Loaded 3 modules from 'uiserv' EcosApp: 'uiserv' type: 'ui/form'
// нашли 3 формы в uiserv (локальные артефакты тоже деплоятся через ECOS Apps)
Loaded 7 modules from 'uiserv' EcosApp: 'uiserv' type: 'ui/action'
Loaded 0 modules from 'uiserv' EcosApp: 'uiserv' type: 'ui/menu'
Loaded 4 modules from 'uiserv' EcosApp: 'uiserv' type: 'ui/dashboard'
Modules count was changed by target app. Before: 4 After: 1
// мы отправили в uiserv изменившиеся артефакты, но он отказался принимать 3 из них (защита от перезатирания конфигурации, которую настроили на стенде)
Detected new application 'emodel' with EcosApps: [EcosAppInfo(id=emodel, lastChanged=1584425829184)]
Loaded 0 modules from 'eapps' EcosApp: 'eapps' type: 'model/section'
Loaded 0 modules from 'eapps' EcosApp: 'eapps' type: 'model/type'
Loaded 0 modules from 'uiserv' EcosApp: 'uiserv' type: 'model/section'
Loaded 1 modules from 'uiserv' EcosApp: 'uiserv' type: 'model/type'
Loaded 0 modules from 'emodel' EcosApp: 'emodel' type: 'model/section'
Loaded 3 modules from 'emodel' EcosApp: 'emodel' type: 'model/type'
Loaded 3 modules from 'emodel' EcosApp: 'emodel' type: 'ui/form'
Loaded 0 modules from 'emodel' EcosApp: 'emodel' type: 'ui/action'
Loaded 0 modules from 'emodel' EcosApp: 'emodel' type: 'ui/menu'
Loaded 0 modules from 'emodel' EcosApp: 'emodel' type: 'ui/dashboard'
Useful Scripts (EApps)
To retrieve all artifacts by type, you can run the following script:
Records.query({
sourceId: 'eapps/module',
query: {
type: 'form'
},
page: {maxItems: 100}
}).then(console.log);
As a result, a list of artifact IDs will be printed to the console.
Having the artifact ID, it can be deleted using the following script:
Records.remove(["eapps/module@form$3784f71c-5557-4123-b751-84e38c6157a1"]);
Retrieving Module Contents from the eapps Database
Get the list of revisions by ext_id and artifact type:
select module.ext_id,rev.created_date,rev.created_by,rev.content_id
from ecos_module module
join ecos_module_rev rev on module.id=rev.module_id
where module.ext_id='ECOS_FORM' and module.type='ui/form';
Look at the content_id field of the required modules and make the following request:
select id,encode(data, 'base64') from ecos_content where id=14809;
We get:
id | encode
-------+------------------------------------------------------------------------------
11448 | UEsDBBQACAgIAAAAIQAAAAAAAAAAAAAAAAAOABEARUNPU19GT1JNLmpzb25VVA0ABwAAAAAAAAAA+
| AAAAAO1aWXMbNxL+K8y8xKnSYUdOLDHZrXIoKVFiLl2Wy3nYcrnAGZADCgNQAIYUxeJ/324cc1AU+
| HR1UxM3oRRygB+jz625g5hFLonZ00umdfzntfehGO9FAquwPOoPRTCY5p19wAMYNM5xG7XlEBcyd+
| wmArZ9FiJ0qojhUbGyZFfdrIFk2YaUmTUtXCZTTSx7k2MuvaxYF0pPdjZmh8se/20/sUSfdpLPUu+
| /tp1LyALszH9QAfwEjxMWWLSqC1yznci9uoQN7fcDJhggZmE6TEnKIyXIpbZWAoqjI7a/51HnPQp+
| h1nHTQuUsRPpVE7/lCrpyFyYqD0gXFM32kmJqo8a0uf0E6PTqG1UDgOET8lMnwgcT0oyYBx2MfTK+
| DBjluAvhXE67OTdszGmX6AtdUDMxzk1Y8KJiijN8cUI4S4ixpvCqpFqTIXVqGWmUHH8pepkzhVy4+
| lbwa7Zz7/V6xiV3Jb5wx8Y6KIaoViTJyVXtkAtWii8nK05gYQ5XdeIFaGaJ6P1trEJDxE+G5588K+
| h+5BQMQIjMMEjFIRq9nYVFQGMzFNJU+o8lsosOxVlf0OJ9rvr/NBMZl5pZZLKQn+VV08F+wyrxBQ+
| pZk2VBRaT1mSoCN7gphTonriN5bQQAEmIL8qlrxzHuQJrT+9l9o7YGTkOPKjfzp/PXjpn7tEDUH2+
| 9sFSBKEIVCmp/Mr4bKREmdwD8Ebru4IXMpFQLz/4fN37SG7kQILOipGkf+bog3xWn8c3jBUTHucc+
| XKQyZh23EyZ6E+DVqsUvBWE5pAadcxCMPIO/3W53N0laadrOshaJrP7o6VoKTSb0rfZhg24FDqCo+
| TnteSd4oH9xowUCID0sWp0RAZGDci8QahXDkDaM5YMc0RUu73/TSu3AGEVkPyI9lDAc37loi69WI+
| ojT98YfDTMDrJbB8tKj5PEHFeN4aRGkQpUGUZ4oo3y8jCtZmayP9aaBmBZ6EyvEhQVoG+hagEpdD+
| Fts6UpAM+Tp2gYK1bkvPIP4zX/aCYIoNh4g886DNEZkQF6UoTvnQBok0aK/1rxYT2hAR070xUYAl+
| e1gT7zmZ9pg+tzugUl989xPyQ2L0R72SI282vzcAGECUmVkU9D/bpY8dh4C3ZrA2TMohv0YfIIQS+
| dM4IuDTWQcAA0eLz4nODtg3abh/aTl/HV0LV6zd8a2m5vwiaI5krYPfMLo3NLMaNdgbGprQjeZ4J+
| j3bYl+bWxecu5I4d0X9cGNsgA3XF6akNZOdlsKhtcsGVvXQQUDJG4pvIWt/1rZ6J+BherLXB9TbT+
| ekwxVNWKBZeSxj5W56sBUYGQymiV2oFbhdAPVGmsYIw4fCspa8NV+i/ANwPQq4pSjq2iVCsowRfu+
| l4lqcXl7KloUpbg/2SjgmFHtzjOWHL/czIWAPQmxAWA9Iri/B9jquzgfEhYIBYlMsT64nN/Hg7qm+
| HKD2d+e6y2l+XRUexKMJi0HA30PChNim5pRxSJvFpC5mmySx1UnCge5DcB3l7CgK47/kxsjSGjhx+
| At77QU5XzByDmxp6c47pU2DpPFaUCmuLrkwIr0yfW/+miZX1rf6I2aCYtUj9Ojk8SngNIpxV75cF+
| 0IXOFQSdAxftUicpcL5+DumtUwNNN1Ll5x14VRV/+bA2fXJlFGktE1Ec3UXSz1XMyhUP4KUh6uNa+
| OHs0KQx8MqHVlsLq8mOKcxKT0su9gxvQkBQSVdwEIeRmhnoCnJ16S34FZVdha7n9w1EWM7fzxNsh+
| tsHG/wdsvBMYcpYxePPVy5c+bN8XvZkP451oYFOpN7qtCAvEcXa5USZCP3tuxyBAMXZI0hN85gUq+
| NQSObmx2LrVKszF3jd3PekzEv+fzFoPBPWu+1mLx874djgIU2E11lbdlcBjkmvbGvkudFyFUG/I4+
| YbEmlL8BnPtv3kzioxraHddqzc0efkBdSlaffdQr3pvl0eaw7fGOM+4Hgnc/2fk6bDbYt93Y98wO+
| D+54GKDkVFvTTGeaTWfD4lW8zZaqikfxxegin/RrgBT6egyo0OHPw3X1QYEnbtKbtCc6KeMJtL2/+
| 1Z1vBdREK5CLl+5yyw13B88RsaNzh4TI/MR13eHwzqGnMjFuiE99LuOLsMN9at9wUOhq9JXCxIEt+
| RJtPznouFQSdu5KzJHxEbKjDtEvYd8KLsiO5G2BUjNbgxaP0kdX8ep/24K7ni5pd29MxPF/idGDO+
| 4iKBs2FaefQK7okzYXks7ZDSrN4gOUgR34+G18x2aXIw0Kge8IJxrlP/g3P740rbfxrkOtpBRtA5+
| oL2zc44kxjigj3/W8uC4afLsPzVunI9nlz9cXbgzllvSFR79tPw3W0XGKj4Eq6eslXmj4B0XqV2c+
| 4RtYfJzYbP7iuzvkvdLqoVt/rDyIpYUXtx5dT3E2cr/Cf8UXFsunKusL/eKS0ukruucl6TfffNmD+
| aHgRLkt3Wt8qKc0am39763VpyclG70mtvvxFaShwotpZHPRoqIeg2L+pH9r++mZLYXlz5cVIH1B++
| YcuLsiVZW2hsuF9p6pimjtnWOiYWwx/7l+vqmHcS1MKuiT8Y3EApY3egT1fM/C33Nryuxie5vnni+
| 8qRqx2dVoKytXjdyX9Wcy2wrDG+ubjk6uh6/acqWpmxpypYHly1H+dUr7b7Yu6sbbziqyti+pZ46+
| z/t4R16rmwJkjBXLiJqtL4FuAs/j3W84EXVgsSb+c4r/7U+PTfxv+NqiaFRKb7bQMdP9y8Hr6JG/+
| 8G8yWuPRD8poF3yqXx1at0S9vU1GsPrXoD0oeiW2++vp4i7/qb4YrCVYXWaRgv0t7bfCVk0APvMA+
| XF/R2WiT16PDFJPAYvkL18X/AFBLBwiiGE2wTAgAAFFCAABQSwECFAAUAAgICAAAACEAohhNsEwI+
| AABRQgAADgAJAAAAAAAAAAAAAAAAAAAARUNPU19GT1JNLmpzb25VVAUABwAAAABQSwUGAAAAAAEA+
| AQBFAAAAmQgAAAAA
Remove the header, | indents, line breaks, + signs at the end of lines, and get the string:
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
Upload the resulting string to any base64-to-file decoding service. For example:
https://base64.guru/converter/decode/file
Download the resulting file:
As a result, we get an archive with our module.
Useful Scripts in the ECOS Apps Database
Getting module revisions:
select module.ext_id,rev.created_date,rev.created_by,rev.is_user_rev,rev.content_id
from ecos_module module
join ecos_module_rev rev on module.id=rev.module_id
where module.ext_id='ECOS_FORM' order by rev.created_date desc;
is_user_rev flag indicates that the module was changed by a user.