Add Russian inline comments
This commit is contained in:
parent
af60297d66
commit
b13d5544f2
@ -1,10 +1,13 @@
|
|||||||
<cfcomponent displayname="Application" output="true">
|
<cfcomponent displayname="Application" output="true">
|
||||||
|
<!--- Базовая конфигурация приложения и подключение JAR-клиента RabbitMQ. --->
|
||||||
<cfset this.Name = "rabbit-lsd-ui" />
|
<cfset this.Name = "rabbit-lsd-ui" />
|
||||||
<cfset this.sessionmanagement = "Yes" />
|
<cfset this.sessionmanagement = "Yes" />
|
||||||
<cfset this.datasource = "testds" />
|
<cfset this.datasource = "testds" />
|
||||||
<cfset this.javaSettings = { loadPaths = [ expandPath("./lib") ] } />
|
<cfset this.javaSettings = { loadPaths = [ expandPath("./lib") ] } />
|
||||||
|
<!--- Инициализируем datasource из переменных окружения. --->
|
||||||
<cfset getDS(this.datasource) />
|
<cfset getDS(this.datasource) />
|
||||||
|
|
||||||
|
<!--- Безопасное чтение переменной окружения с дефолтом. --->
|
||||||
<cffunction name="getEnv" access="private" returntype="string">
|
<cffunction name="getEnv" access="private" returntype="string">
|
||||||
<cfargument name="key" type="string" required="true" />
|
<cfargument name="key" type="string" required="true" />
|
||||||
<cfargument name="def" type="string" required="true" />
|
<cfargument name="def" type="string" required="true" />
|
||||||
@ -14,6 +17,7 @@
|
|||||||
<cfreturn arguments.def />
|
<cfreturn arguments.def />
|
||||||
</cffunction>
|
</cffunction>
|
||||||
|
|
||||||
|
<!--- Собираем datasource из набора *_field переменных окружения. --->
|
||||||
<cffunction name="getDS" access="private" returntype="void">
|
<cffunction name="getDS" access="private" returntype="void">
|
||||||
<cfargument name="dsname" type="string" required="true" />
|
<cfargument name="dsname" type="string" required="true" />
|
||||||
<cfset var system = createObject("java", "java.lang.System") />
|
<cfset var system = createObject("java", "java.lang.System") />
|
||||||
@ -25,6 +29,7 @@
|
|||||||
<cfset this.datasources[arguments.dsname] = ds />
|
<cfset this.datasources[arguments.dsname] = ds />
|
||||||
</cffunction>
|
</cffunction>
|
||||||
|
|
||||||
|
<!--- Публикация CRUD-сообщения в RabbitMQ. --->
|
||||||
<cffunction name="publishToRabbit" access="private" returntype="void">
|
<cffunction name="publishToRabbit" access="private" returntype="void">
|
||||||
<cfargument name="payload" type="struct" required="true" />
|
<cfargument name="payload" type="struct" required="true" />
|
||||||
<cfset var host = getEnv("RABBIT_HOST", "") />
|
<cfset var host = getEnv("RABBIT_HOST", "") />
|
||||||
@ -39,6 +44,7 @@
|
|||||||
<cfset var connection = "" />
|
<cfset var connection = "" />
|
||||||
<cfset var channel = "" />
|
<cfset var channel = "" />
|
||||||
|
|
||||||
|
<!--- Не стартуем публикацию без базовых кредов. --->
|
||||||
<cfif host EQ "" OR user EQ "" OR pass EQ "">
|
<cfif host EQ "" OR user EQ "" OR pass EQ "">
|
||||||
<cfthrow message="Rabbit credentials are missing" />
|
<cfthrow message="Rabbit credentials are missing" />
|
||||||
</cfif>
|
</cfif>
|
||||||
@ -49,6 +55,7 @@
|
|||||||
<cfset factory.setPassword(pass) />
|
<cfset factory.setPassword(pass) />
|
||||||
<cfset factory.setVirtualHost(vhost) />
|
<cfset factory.setVirtualHost(vhost) />
|
||||||
|
|
||||||
|
<!--- Подключаемся, объявляем очередь и отправляем JSON. --->
|
||||||
<cftry>
|
<cftry>
|
||||||
<cfset connection = factory.newConnection() />
|
<cfset connection = factory.newConnection() />
|
||||||
<cfset channel = connection.createChannel() />
|
<cfset channel = connection.createChannel() />
|
||||||
@ -66,6 +73,7 @@
|
|||||||
</cftry>
|
</cftry>
|
||||||
</cffunction>
|
</cffunction>
|
||||||
|
|
||||||
|
<!--- Основной обработчик запроса: подготовка БД, логов и POST-операций. --->
|
||||||
<cffunction name="OnRequest" access="public" returntype="void" output="true">
|
<cffunction name="OnRequest" access="public" returntype="void" output="true">
|
||||||
<cfargument name="template" type="string" required="true" />
|
<cfargument name="template" type="string" required="true" />
|
||||||
<cfset request.DS = this.datasource />
|
<cfset request.DS = this.datasource />
|
||||||
@ -76,6 +84,7 @@
|
|||||||
<cfset request.rabbitPassword = getEnv("RABBIT_PASSWORD", "") />
|
<cfset request.rabbitPassword = getEnv("RABBIT_PASSWORD", "") />
|
||||||
<cfset request.nodeworkerUrl = getEnv("NODEWORKER_URL", "") />
|
<cfset request.nodeworkerUrl = getEnv("NODEWORKER_URL", "") />
|
||||||
|
|
||||||
|
<!--- Гарантируем наличие основной таблицы сообщений. --->
|
||||||
<cftry>
|
<cftry>
|
||||||
<cfquery datasource="#request.DS#">
|
<cfquery datasource="#request.DS#">
|
||||||
CREATE TABLE IF NOT EXISTS #request.tableName# (id SERIAL PRIMARY KEY, test_data TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP)
|
CREATE TABLE IF NOT EXISTS #request.tableName# (id SERIAL PRIMARY KEY, test_data TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP)
|
||||||
@ -83,6 +92,7 @@
|
|||||||
<cfcatch><cfset request.db_error = cfcatch.message /></cfcatch>
|
<cfcatch><cfset request.db_error = cfcatch.message /></cfcatch>
|
||||||
</cftry>
|
</cftry>
|
||||||
|
|
||||||
|
<!--- Гарантируем наличие таблицы лога UI и обновляем статусы. --->
|
||||||
<cftry>
|
<cftry>
|
||||||
<cfquery datasource="#request.DS#">
|
<cfquery datasource="#request.DS#">
|
||||||
CREATE TABLE IF NOT EXISTS #request.logTableName# (
|
CREATE TABLE IF NOT EXISTS #request.logTableName# (
|
||||||
@ -134,6 +144,7 @@
|
|||||||
<cfcatch><cfset request.db_error = cfcatch.message /></cfcatch>
|
<cfcatch><cfset request.db_error = cfcatch.message /></cfcatch>
|
||||||
</cftry>
|
</cftry>
|
||||||
|
|
||||||
|
<!--- Обрабатываем POST CRUD и отправляем событие в очередь. --->
|
||||||
<cfif CGI.REQUEST_METHOD EQ "POST" AND structKeyExists(form, "crud_action")>
|
<cfif CGI.REQUEST_METHOD EQ "POST" AND structKeyExists(form, "crud_action")>
|
||||||
<cfset var action = lcase(form.crud_action) />
|
<cfset var action = lcase(form.crud_action) />
|
||||||
<cfset var requestId = createUUID() />
|
<cfset var requestId = createUUID() />
|
||||||
@ -141,6 +152,7 @@
|
|||||||
<cfset var logText = "" />
|
<cfset var logText = "" />
|
||||||
<cfset var logTargetId = "" />
|
<cfset var logTargetId = "" />
|
||||||
|
|
||||||
|
<!--- Формируем payload и лог для очереди. --->
|
||||||
<cftry>
|
<cftry>
|
||||||
<cfswitch expression="#action#">
|
<cfswitch expression="#action#">
|
||||||
<cfcase value="insert">
|
<cfcase value="insert">
|
||||||
@ -171,6 +183,7 @@
|
|||||||
</cfdefaultcase>
|
</cfdefaultcase>
|
||||||
</cfswitch>
|
</cfswitch>
|
||||||
|
|
||||||
|
<!--- Публикуем сообщение и пишем запись в лог UI. --->
|
||||||
<cfset publishToRabbit(payload) />
|
<cfset publishToRabbit(payload) />
|
||||||
<cfquery datasource="#request.DS#">
|
<cfquery datasource="#request.DS#">
|
||||||
INSERT INTO #request.logTableName# (action, text, request_id, target_id, queued_at, status)
|
INSERT INTO #request.logTableName# (action, text, request_id, target_id, queued_at, status)
|
||||||
|
|||||||
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
UI publishes CRUD actions to RabbitMQ and reads results from Postgres.
|
UI publishes CRUD actions to RabbitMQ and reads results from Postgres.
|
||||||
|
|
||||||
|
Коротко: интерфейс пишет в RabbitMQ, а фактическое состояние берет из Postgres, чтобы показать разницу между "поставлено в очередь" и "исполнено".
|
||||||
|
|
||||||
## Behavior
|
## Behavior
|
||||||
|
|
||||||
- Insert/Update/Delete actions are queued via RabbitMQ.
|
- Insert/Update/Delete actions are queued via RabbitMQ.
|
||||||
@ -33,6 +35,11 @@ RabbitMQ (required):
|
|||||||
Optional:
|
Optional:
|
||||||
- `PG_TABLE` (default `rabbit_messages`)
|
- `PG_TABLE` (default `rabbit_messages`)
|
||||||
|
|
||||||
|
Optional:
|
||||||
|
- `UI_LOG_TABLE` (default `rabbit_ui_log`) — таблица лога для статуса запросов UI.
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
This app uses RabbitMQ Java client JARs located in `lib/`.
|
This app uses RabbitMQ Java client JARs located in `lib/`.
|
||||||
|
|
||||||
|
Комментарий: JAR-ы подключены через `this.javaSettings.loadPaths`, поэтому важно держать `lib/` рядом с приложением.
|
||||||
|
|||||||
@ -1 +1,2 @@
|
|||||||
|
<!--- Простой редирект на основной экран UI. --->
|
||||||
<cflocation addtoken="No" url="query.cfm##q"/>
|
<cflocation addtoken="No" url="query.cfm##q"/>
|
||||||
|
|||||||
@ -52,12 +52,14 @@
|
|||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<!--- Сводный статус последней операции и базовые ссылки. --->
|
||||||
<cfset status = {}>
|
<cfset status = {}>
|
||||||
<cfset rabbitAdminUrl = request.rabbitAdminUrl>
|
<cfset rabbitAdminUrl = request.rabbitAdminUrl>
|
||||||
<cfset rabbitUser = request.rabbitUser>
|
<cfset rabbitUser = request.rabbitUser>
|
||||||
<cfset rabbitPassword = request.rabbitPassword>
|
<cfset rabbitPassword = request.rabbitPassword>
|
||||||
<cfset nodeworkerUrl = request.nodeworkerUrl>
|
<cfset nodeworkerUrl = request.nodeworkerUrl>
|
||||||
|
|
||||||
|
<!--- Лог последних событий из UI-очереди. --->
|
||||||
<cfquery name="qLog" datasource="#request.DS#">
|
<cfquery name="qLog" datasource="#request.DS#">
|
||||||
SELECT id, action, text, request_id, target_id, queued_at, processed_at, status, error_reason
|
SELECT id, action, text, request_id, target_id, queued_at, processed_at, status, error_reason
|
||||||
FROM #request.logTableName#
|
FROM #request.logTableName#
|
||||||
@ -65,6 +67,7 @@
|
|||||||
LIMIT 20
|
LIMIT 20
|
||||||
</cfquery>
|
</cfquery>
|
||||||
|
|
||||||
|
<!--- Формируем сообщение статуса из лога/ошибок. --->
|
||||||
<cfif structKeyExists(request, "queue_error")>
|
<cfif structKeyExists(request, "queue_error")>
|
||||||
<cfset status.type = "error">
|
<cfset status.type = "error">
|
||||||
<cfset status.message = "Ошибка постановки в очередь: " & request.queue_error>
|
<cfset status.message = "Ошибка постановки в очередь: " & request.queue_error>
|
||||||
@ -77,6 +80,7 @@
|
|||||||
</cfif>
|
</cfif>
|
||||||
</cfif>
|
</cfif>
|
||||||
|
|
||||||
|
<!--- Фиксированный заголовок Nubes. --->
|
||||||
<div class="header-bg">
|
<div class="header-bg">
|
||||||
<div class="container header-content">
|
<div class="container header-content">
|
||||||
<img src="https://nubes.ru/themes/custom/nubes_2025/logo.svg" alt="Nubes" class="logo">
|
<img src="https://nubes.ru/themes/custom/nubes_2025/logo.svg" alt="Nubes" class="logo">
|
||||||
@ -84,6 +88,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="container main-content">
|
<div class="container main-content">
|
||||||
|
<!--- Карточка с ссылками и кредами Rabbit/worker. --->
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="top-info">
|
<div class="top-info">
|
||||||
<div>
|
<div>
|
||||||
@ -111,6 +116,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!--- Карточка действий CRUD. --->
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<cfif structKeyExists(request, "db_error")>
|
<cfif structKeyExists(request, "db_error")>
|
||||||
<div class="alert alert-error">Ошибка базы данных: <cfoutput>#request.db_error#</cfoutput></div>
|
<div class="alert alert-error">Ошибка базы данных: <cfoutput>#request.db_error#</cfoutput></div>
|
||||||
@ -129,6 +135,7 @@
|
|||||||
<div class="small">💾 — сохранить (update), 🗑 — удалить</div>
|
<div class="small">💾 — сохранить (update), 🗑 — удалить</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!--- Две таблицы: очередь/лог и фактическая БД. --->
|
||||||
<div class="split">
|
<div class="split">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<h3>Очередь (лог отправки)</h3>
|
<h3>Очередь (лог отправки)</h3>
|
||||||
@ -166,11 +173,13 @@
|
|||||||
|
|
||||||
<div class="card wide">
|
<div class="card wide">
|
||||||
<h3>База (фактические записи)</h3>
|
<h3>База (фактические записи)</h3>
|
||||||
|
<!--- Читаем последние фактические записи для сравнения с логом. --->
|
||||||
<cfquery name="qGet" datasource="#request.DS#">SELECT * FROM #request.tableName# ORDER BY id DESC LIMIT 20</cfquery>
|
<cfquery name="qGet" datasource="#request.DS#">SELECT * FROM #request.tableName# ORDER BY id DESC LIMIT 20</cfquery>
|
||||||
<table class="tight">
|
<table class="tight">
|
||||||
<thead><tr><th class="col-id">ID</th><th class="col-content">Содержимое</th><th class="col-req">Request ID</th><th>Действия</th></tr></thead>
|
<thead><tr><th class="col-id">ID</th><th class="col-content">Содержимое</th><th class="col-req">Request ID</th><th>Действия</th></tr></thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<cfoutput query="qGet">
|
<cfoutput query="qGet">
|
||||||
|
<!--- Отделяем request_id из хвоста строки. --->
|
||||||
<cfset reqMatch = reFindNoCase("\\[req:[0-9a-f-]+\\]$", test_data, 1, true)>
|
<cfset reqMatch = reFindNoCase("\\[req:[0-9a-f-]+\\]$", test_data, 1, true)>
|
||||||
<cfset reqTag = reqMatch.pos[1] GT 0 ? mid(test_data, reqMatch.pos[1], reqMatch.len[1]) : "">
|
<cfset reqTag = reqMatch.pos[1] GT 0 ? mid(test_data, reqMatch.pos[1], reqMatch.len[1]) : "">
|
||||||
<cfset cleanText = reReplace(test_data, "(?i)\\s*\\[req:[0-9a-f-]+\\]$", "", "all")>
|
<cfset cleanText = reReplace(test_data, "(?i)\\s*\\[req:[0-9a-f-]+\\]$", "", "all")>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user