Учёт DEPO: шаг «Обработка» проверяет запуск джобы (есть, включена, расписание, запускалась недавно — по msdb), работа процедур (BJ_PING) — отдельной проверкой «Обработка событий»; логину bj — SQLAgentReaderRole для проверки
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FsEKyJrYF69Cj9ZXzFLRi
This commit is contained in:
@@ -777,7 +777,12 @@ END
|
||||
ELSE
|
||||
PRINT N'Джоба %[1]s уже есть — не изменялась.';
|
||||
GO
|
||||
`, depoJobName, f.DepoDB(), depoJobProcName(f), depoJobEvery(f))
|
||||
|
||||
-- Логину bj — чтение списка джоб и их истории: bj проверяет, что джоба запускается по расписанию.
|
||||
IF USER_ID(N'%[5]s') IS NULL CREATE USER [%[5]s] FOR LOGIN [%[5]s];
|
||||
IF IS_ROLEMEMBER(N'SQLAgentReaderRole', N'%[5]s') = 0 ALTER ROLE SQLAgentReaderRole ADD MEMBER [%[5]s];
|
||||
GO
|
||||
`, depoJobName, f.DepoDB(), depoJobProcName(f), depoJobEvery(f), pickStr(strings.TrimSpace(f.User), "bj_user"))
|
||||
}
|
||||
|
||||
// depoJobGrantScript — права для варианта «внутри bj».
|
||||
@@ -807,11 +812,121 @@ func depoJobPing(ctx context.Context, db *sql.DB, wait time.Duration) (bool, str
|
||||
}
|
||||
time.Sleep(3 * time.Second)
|
||||
}
|
||||
return false, fmt.Sprintf("проверочное событие BJ_PING не обработано за %s. Проверьте по порядку: 1) в базе DEPO есть процедуры обработки (FTV_M2M_JOB и FTV_M2M_PROCESS_*) — без них джоба запускается и падает; 2) джоба bj2depo есть и включена, служба SQL Server Agent запущена (история джобы в SSMS покажет ошибку); 3) пользователь, от имени которого работают процедуры (SYSDBA), есть в базе", wait)
|
||||
return false, fmt.Sprintf("проверочное событие BJ_PING не обработано за %s — процедуры обработки не отработали. Проверьте: 1) в базе DEPO есть процедуры FTV_M2M_JOB и FTV_M2M_PROCESS_*; 2) пользователь, от имени которого они работают (SYSDBA), есть в базе; 3) ошибку последнего запуска джобы — в её истории в SSMS", wait)
|
||||
}
|
||||
|
||||
// depoJobCheck — проверка готовности выбранного способа обработки.
|
||||
func depoJobCheck(ctx context.Context, rc *RuntimeConfig) (string, bool) {
|
||||
return depoJobRunnerCheck(ctx, rc, "", "")
|
||||
}
|
||||
|
||||
// depoJobRunnerCheck — запускалка обработки (05.10.2026: шаг «Обработка» проверяет только её, а не процедуры):
|
||||
// SQL Agent — джоба есть, включена, есть расписание и она запускалась недавно; «bj сам» — право EXECUTE.
|
||||
// adminUser/adminPass — разовый логин администратора (если введён), иначе — логин bj (нужен SQLAgentReaderRole в msdb).
|
||||
func depoJobRunnerCheck(ctx context.Context, rc *RuntimeConfig, adminUser, adminPass string) (string, bool) {
|
||||
f := rc.Snapshot().Fancy
|
||||
switch f.DepoJobMode {
|
||||
case "bj":
|
||||
db, err := depoEventsDB(rc)
|
||||
if err != nil {
|
||||
return "подключение к DEPO: " + err.Error(), false
|
||||
}
|
||||
defer db.Close()
|
||||
var n int
|
||||
_ = db.QueryRowContext(ctx, "SELECT COUNT(*) FROM fn_my_permissions(@p,'OBJECT') WHERE permission_name='EXECUTE'", sql.Named("p", depoJobProcName(f))).Scan(&n)
|
||||
if n == 0 {
|
||||
return "у логина " + f.User + " нет права EXECUTE на " + depoJobProcName(f) + " — выполните на сервере: " + strings.ReplaceAll(depoJobGrantScript(f), "\n", " "), false
|
||||
}
|
||||
return fmt.Sprintf("право на %s есть; bj будет вызывать её каждые %d с", depoJobProcName(f), depoJobEvery(f)), true
|
||||
case "sql-auto", "sql-manual":
|
||||
return depoAgentJobStatus(ctx, f, adminUser, adminPass)
|
||||
}
|
||||
return "способ обработки не выбран", false
|
||||
}
|
||||
|
||||
// depoAgentJobStatus — состояние джобы SQL Agent по msdb.
|
||||
func depoAgentJobStatus(ctx context.Context, f FancyMSSQLSettings, adminUser, adminPass string) (string, bool) {
|
||||
conn := f
|
||||
if strings.TrimSpace(adminUser) != "" {
|
||||
conn.User, conn.Password = strings.TrimSpace(adminUser), adminPass
|
||||
}
|
||||
mdb, err := fancyOpen(conn, "msdb")
|
||||
if err != nil {
|
||||
return "подключение к msdb: " + err.Error(), false
|
||||
}
|
||||
defer mdb.Close()
|
||||
var (
|
||||
jobEnabled, schedEnabled, subType, subInt sql.NullInt64
|
||||
runDate, runTime, runStatus sql.NullInt64
|
||||
runMsg sql.NullString
|
||||
now time.Time
|
||||
)
|
||||
err = mdb.QueryRowContext(ctx, `SELECT j.enabled, s.enabled, s.freq_subday_type, s.freq_subday_interval,
|
||||
h.run_date, h.run_time, h.run_status, h.message, GETDATE()
|
||||
FROM msdb.dbo.sysjobs j
|
||||
LEFT JOIN msdb.dbo.sysjobschedules js ON js.job_id = j.job_id
|
||||
LEFT JOIN msdb.dbo.sysschedules s ON s.schedule_id = js.schedule_id
|
||||
OUTER APPLY (SELECT TOP 1 run_date, run_time, run_status, message FROM msdb.dbo.sysjobhistory
|
||||
WHERE job_id = j.job_id AND step_id = 0 ORDER BY instance_id DESC) h
|
||||
WHERE j.name = @n`, sql.Named("n", depoJobName)).Scan(&jobEnabled, &schedEnabled, &subType, &subInt, &runDate, &runTime, &runStatus, &runMsg, &now)
|
||||
if err == sql.ErrNoRows {
|
||||
return "джобы " + depoJobName + " на сервере нет — создайте её (вариант «создаёт bj» с логином администратора или скрипт для администратора)", false
|
||||
}
|
||||
if err != nil {
|
||||
return "список джоб недоступен логину " + conn.User + " (" + quikErrorDetail(err) + "). Чтобы bj мог проверять джобу, администратору SQL — один раз: " + strings.ReplaceAll(depoJobReaderGrant(f), "\n", " "), false
|
||||
}
|
||||
if jobEnabled.Int64 != 1 {
|
||||
return "джоба " + depoJobName + " есть, но ВЫКЛЮЧЕНА — включите её в SQL Server Agent", false
|
||||
}
|
||||
if !schedEnabled.Valid || schedEnabled.Int64 != 1 {
|
||||
return "у джобы " + depoJobName + " нет включённого расписания — она не будет запускаться", false
|
||||
}
|
||||
every := time.Duration(depoJobEvery(f)) * time.Second
|
||||
if subType.Int64 == 2 && subInt.Int64 > 0 { // каждые N секунд
|
||||
every = time.Duration(subInt.Int64) * time.Second
|
||||
} else if subType.Int64 == 4 && subInt.Int64 > 0 { // каждые N минут
|
||||
every = time.Duration(subInt.Int64) * time.Minute
|
||||
}
|
||||
sched := fmt.Sprintf("джоба %s включена, запускается каждые %s", depoJobName, humanEvery(every))
|
||||
if !runDate.Valid || runDate.Int64 == 0 {
|
||||
return sched + ", но ещё ни разу не запускалась — запущена ли служба SQL Server Agent?", false
|
||||
}
|
||||
d, t := runDate.Int64, runTime.Int64
|
||||
last := time.Date(int(d/10000), time.Month(d/100%100), int(d%100), int(t/10000), int(t/100%100), int(t%100), 0, now.Location())
|
||||
age := now.Sub(last)
|
||||
limit := 3 * every
|
||||
if limit < time.Minute {
|
||||
limit = time.Minute
|
||||
}
|
||||
if age > limit {
|
||||
return fmt.Sprintf("%s, но последний запуск был %s (%s назад) — запущена ли служба SQL Server Agent?", sched, last.Format("02.01 15:04:05"), humanDur(age)), false
|
||||
}
|
||||
msg := fmt.Sprintf("%s; последний запуск %s (%d с назад)", sched, last.Format("15:04:05"), int(age.Seconds()))
|
||||
if runStatus.Int64 == 0 { // запуск есть, но обработка внутри упала — это не про джобу
|
||||
txt := strings.TrimSpace(runMsg.String)
|
||||
if r := []rune(txt); len(r) > 300 {
|
||||
txt = string(r[:300]) + "…"
|
||||
}
|
||||
msg += ". Запуск завершился ошибкой обработки — это уже не про джобу, а про процедуры (см. «Обработка событий»): " + txt
|
||||
}
|
||||
return msg, true
|
||||
}
|
||||
|
||||
func humanEvery(d time.Duration) string {
|
||||
if d < time.Minute {
|
||||
return fmt.Sprintf("%d с", int(d.Seconds()))
|
||||
}
|
||||
return fmt.Sprintf("%d мин", int(d.Minutes()))
|
||||
}
|
||||
|
||||
// depoJobReaderGrant — право логину bj видеть джобы и их историю (для проверки джобы из bj).
|
||||
func depoJobReaderGrant(f FancyMSSQLSettings) string {
|
||||
return fmt.Sprintf("USE msdb;\nIF USER_ID(N'%[1]s') IS NULL CREATE USER [%[1]s] FOR LOGIN [%[1]s];\nIF IS_ROLEMEMBER(N'SQLAgentReaderRole', N'%[1]s') = 0 ALTER ROLE SQLAgentReaderRole ADD MEMBER [%[1]s];", f.User)
|
||||
}
|
||||
|
||||
// depoProcCheck — работает ли сама обработка событий (процедуры FTV_M2M_*): таблицы, пользователь
|
||||
// процедур, ошибки обработчика, проверочное событие BJ_PING. Отдельно от запускалки (джобы).
|
||||
func depoProcCheck(ctx context.Context, rc *RuntimeConfig) (string, bool) {
|
||||
f := rc.Snapshot().Fancy
|
||||
db, err := depoEventsDB(rc)
|
||||
if err != nil {
|
||||
@@ -819,7 +934,7 @@ func depoJobCheck(ctx context.Context, rc *RuntimeConfig) (string, bool) {
|
||||
}
|
||||
defer db.Close()
|
||||
if !depoTableExists(ctx, db, "FTV_M2M_EVENTS") {
|
||||
return "в базе " + f.DepoDB() + " нет таблиц FTV_M2M* — создайте их: Настройка → Обмен Fancy → «Трансферные таблицы DEPO»", false
|
||||
return "в базе " + f.DepoDB() + " нет таблиц FTV_M2M*", false
|
||||
}
|
||||
if ok, msg := depoRunAsCheck(ctx, db, f); !ok {
|
||||
return msg, false
|
||||
@@ -828,37 +943,13 @@ func depoJobCheck(ctx context.Context, rc *RuntimeConfig) (string, bool) {
|
||||
return fmt.Sprintf("обработчик за последние сутки не смог обработать записей: %d (последняя: %s %s — %s). Устраните причину и верните их в очередь: Обмен с DEPO → «Вернуть в очередь»",
|
||||
len(fails), fails[0].TableRu(), fails[0].Type, fails[0].Comment), false
|
||||
}
|
||||
switch f.DepoJobMode {
|
||||
case "bj":
|
||||
var n int
|
||||
_ = db.QueryRowContext(ctx, "SELECT COUNT(*) FROM fn_my_permissions(@p,'OBJECT') WHERE permission_name='EXECUTE'", sql.Named("p", depoJobProcName(f))).Scan(&n)
|
||||
if n == 0 {
|
||||
return "у логина " + f.User + " нет права EXECUTE на " + depoJobProcName(f) + " — выполните на сервере: " + strings.ReplaceAll(depoJobGrantScript(f), "\n", " "), false
|
||||
}
|
||||
start := time.Now()
|
||||
if f.DepoJobMode == "bj" {
|
||||
if _, err := execProc(ctx, db, depoJobProcName(f)); err != nil {
|
||||
return "вызов " + depoJobProcName(f) + ": " + quikErrorDetail(err), false
|
||||
}
|
||||
return fmt.Sprintf("право есть, процедура %s выполнена за %s; bj будет вызывать её каждые %d с", depoJobProcName(f), time.Since(start).Round(time.Millisecond), depoJobEvery(f)), true
|
||||
case "sql-auto", "sql-manual":
|
||||
// 1) джоба видна через msdb?
|
||||
var seen string
|
||||
if mdb, err := fancyOpen(f, "msdb"); err == nil {
|
||||
var enabled int
|
||||
if e := mdb.QueryRowContext(ctx, "SELECT enabled FROM msdb.dbo.sysjobs WHERE name=@n", sql.Named("n", depoJobName)).Scan(&enabled); e == nil {
|
||||
if enabled == 1 {
|
||||
seen = "джоба " + depoJobName + " есть и включена; "
|
||||
} else {
|
||||
seen = "джоба " + depoJobName + " есть, но ВЫКЛЮЧЕНА; "
|
||||
}
|
||||
}
|
||||
mdb.Close()
|
||||
}
|
||||
// 2) реально ли обрабатывает: BJ_PING
|
||||
ok, msg := depoJobPing(ctx, db, 40*time.Second)
|
||||
return seen + msg, ok
|
||||
}
|
||||
return "способ обработки не выбран", false
|
||||
ok, msg := depoJobPing(ctx, db, 40*time.Second)
|
||||
return msg, ok
|
||||
}
|
||||
|
||||
// depoJobCreateAgent — создать джобу SQL Agent от имени логина bj (нужна роль SQLAgentOperatorRole).
|
||||
@@ -880,6 +971,7 @@ func depoJobCreateAgent(ctx context.Context, rc *RuntimeConfig, adminUser, admin
|
||||
return fmt.Errorf("нет доступа к msdb (%s). Нужны права: %s", quikErrorDetail(err), strings.ReplaceAll(depoJobAgentRightsScript(f), "\n", " "))
|
||||
}
|
||||
if n > 0 {
|
||||
depoGrantJobReader(ctx, mdb, f) // джоба осталась (msdb не восстанавливали) — права на проверку всё равно выдаём
|
||||
return fmt.Errorf("джоба %s уже существует", depoJobName)
|
||||
}
|
||||
for _, stmt := range strings.Split(depoJobAgentScript(f), "\n") {
|
||||
@@ -892,9 +984,26 @@ func depoJobCreateAgent(ctx context.Context, rc *RuntimeConfig, adminUser, admin
|
||||
}
|
||||
}
|
||||
log.Printf("depo-job: джоба SQL Agent %s создана", depoJobName)
|
||||
depoGrantJobReader(ctx, mdb, f)
|
||||
return nil
|
||||
}
|
||||
|
||||
// depoGrantJobReader — пока есть логин администратора: логину bj — чтение списка джоб (для проверки).
|
||||
func depoGrantJobReader(ctx context.Context, mdb *sql.DB, f FancyMSSQLSettings) {
|
||||
if !depoLoginRe.MatchString(f.User) {
|
||||
return
|
||||
}
|
||||
for _, q := range strings.Split(depoJobReaderGrant(f), "\n") {
|
||||
if strings.HasPrefix(q, "USE ") {
|
||||
continue
|
||||
}
|
||||
if _, err := mdb.ExecContext(ctx, q); err != nil {
|
||||
log.Printf("depo-job: право SQLAgentReaderRole логину %s: %s", f.User, quikErrorDetail(err))
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DepoJobView — данные карточки «Где запускается обработка».
|
||||
type DepoJobView struct {
|
||||
Name, Proc, GrantScript, AgentRights, AgentScript string
|
||||
|
||||
@@ -238,14 +238,20 @@ func (h *setupHandlers) checkFancyDepoJob(w http.ResponseWriter, r *http.Request
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 90*time.Second)
|
||||
defer cancel()
|
||||
msg, ok := depoJobCheck(ctx, h.rc)
|
||||
pmsg, pok := depoProcCheck(ctx, h.rc)
|
||||
s := h.rc.Snapshot().Fancy
|
||||
s.DepoJobCheck, s.DepoJobCheckOK, s.DepoJobCheckAt = msg, ok, time.Now()
|
||||
s.DepoProcCheck, s.DepoProcCheckOK, s.DepoProcCheckAt = pmsg, pok, time.Now()
|
||||
_ = h.rc.UpdateFancy(s)
|
||||
run := "НЕ готово — "
|
||||
if ok {
|
||||
setupFlash(w, r, "Обработка DEPO: готово — "+msg)
|
||||
} else {
|
||||
setupFlash(w, r, "Обработка DEPO: НЕ готово — "+msg)
|
||||
run = "готово — "
|
||||
}
|
||||
proc := "НЕ работает — "
|
||||
if pok {
|
||||
proc = "работает — "
|
||||
}
|
||||
setupFlash(w, r, "Запуск обработки (джоба): "+run+msg+" · Обработка событий (процедуры): "+proc+pmsg)
|
||||
}
|
||||
|
||||
// createFancyDepoJob — POST /admin/setup/fancy/depo-job/create: создать джобу SQL Agent от имени bj.
|
||||
|
||||
@@ -186,6 +186,10 @@ type FancyMSSQLSettings struct {
|
||||
DepoJobCheck string `json:"depo_job_check"` // результат последней проверки готовности
|
||||
DepoJobCheckOK bool `json:"depo_job_check_ok"`
|
||||
DepoJobCheckAt time.Time `json:"depo_job_check_at"`
|
||||
// DepoProcCheck — работает ли обработка событий процедурами (BJ_PING), отдельно от запуска джобы.
|
||||
DepoProcCheck string `json:"depo_proc_check,omitempty"`
|
||||
DepoProcCheckOK bool `json:"depo_proc_check_ok,omitempty"`
|
||||
DepoProcCheckAt time.Time `json:"depo_proc_check_at,omitempty"`
|
||||
DepoJobEverySec int `json:"depo_job_every_sec"`
|
||||
DepoJobProc string `json:"depo_job_proc"`
|
||||
DepoJobRunAs string `json:"depo_job_run_as,omitempty"` // пользователь базы DEPO для EXECUTE AS процедуры (пусто = SYSDBA)
|
||||
|
||||
@@ -197,7 +197,7 @@ a.wstep:hover .bub { box-shadow:0 0 0 4px var(--accent-weak); }
|
||||
<pre class="copyable" style="font-size:12px;max-height:260px">{{.DepoJob.AdminScript}}</pre></div>
|
||||
<input type="hidden" name="action" value="" id="wiz-job-action">
|
||||
<div style="display:flex;justify-content:space-between;margin-top:6px"><a href="/admin/wizard?step=3&sub=tables" class="btn" style="background:var(--card);color:var(--text);border:1px solid var(--border-strong,#c9cdd8);text-decoration:none">← Назад</a><button type="submit" class="btn" id="wiz-job-btn">Создать, проверить и далее →</button></div>
|
||||
<p class="muted" style="font-size:12px;margin:0">Проверка: bj кладёт служебное событие и ждёт до 40 секунд, пока обработка его отметит.</p>
|
||||
<p class="muted" style="font-size:12px;margin:0">Проверка: джоба есть, включена, есть расписание и она запускалась за последнюю минуту. Работают ли процедуры обработки — отдельная проверка на экране «Готово».</p>
|
||||
<p style="font-size:12.5px;margin:0"><a href="/admin/wizard?step=3&sub=done">Дальше без проверки →</a> <span class="muted">— если обработку ещё настраивает администратор (например, ставит процедуры). Вернуться и проверить можно с экрана «Готово» кнопкой «Перепроверить всё».</span></p>
|
||||
</form>
|
||||
<script>function wizJob(){var f=document.getElementById('wiz-job'),m=f.depo_job_mode.value;
|
||||
@@ -208,7 +208,8 @@ a.wstep:hover .bub { box-shadow:0 0 0 4px var(--accent-weak); }
|
||||
<table style="margin:6px 0 10px">
|
||||
<tr><td>Подключение к базе DEPO</td><td>{{if .Settings.Fancy.Server}}<span style="color:var(--ok)">✓ {{.Settings.Fancy.Server}}, база {{.DepoTables.DB}}</span>{{else}}<span style="color:var(--err)">не настроено</span>{{end}}</td></tr>
|
||||
<tr><td>Таблицы обмена FTV_M2M</td><td>{{if .Settings.Fancy.DepoTablesCheckOK}}<span style="color:var(--ok)">✓ на месте</span>{{else}}<span style="color:var(--err)">✗ {{.Settings.Fancy.DepoTablesCheck}}</span>{{end}}</td></tr>
|
||||
<tr><td>Обработка (job)</td><td>{{if .Settings.Fancy.DepoJobCheckOK}}<span style="color:var(--ok)">✓ работает</span>{{else}}<span style="color:var(--err)">✗ {{.Settings.Fancy.DepoJobCheck}}</span>{{end}}</td></tr>
|
||||
<tr><td>Запуск обработки (джоба)</td><td>{{if .Settings.Fancy.DepoJobCheckOK}}<span style="color:var(--ok)">✓ {{.Settings.Fancy.DepoJobCheck}}</span>{{else}}<span style="color:var(--err)">✗ {{.Settings.Fancy.DepoJobCheck}}</span>{{end}}</td></tr>
|
||||
<tr><td>Обработка событий (процедуры)</td><td>{{if .Settings.Fancy.DepoProcCheckOK}}<span style="color:var(--ok)">✓ {{.Settings.Fancy.DepoProcCheck}}</span>{{else if .Settings.Fancy.DepoProcCheck}}<span style="color:var(--warn)">⚠ {{.Settings.Fancy.DepoProcCheck}}</span>{{else}}<span class="muted">не проверялась — «Перепроверить всё»</span>{{end}}</td></tr>
|
||||
</table>
|
||||
{{if .Done.Depo}}<p>Учёт DEPO подключён и проверен. Можно переходить к шагу 4 — там bj предложит реквизиты вашей организации из DEPO.</p>{{else}}<p class="muted" style="font-size:13px">Не всё проверено — можно продолжить настройку (шаг 4 и дальше) и вернуться сюда позже. Пока обработка не работает, записи bj ждут в таблицах обмена со статусом TODO и будут обработаны, когда она заработает.</p>{{end}}
|
||||
<form method="post" action="/admin/setup/wizard-depo/recheck" style="margin:0"><button type="submit" class="btn" style="background:var(--card);color:var(--text);border:1px solid var(--border-strong,#c9cdd8)">Перепроверить всё</button></form>
|
||||
|
||||
@@ -109,6 +109,7 @@
|
||||
<span class="muted" style="font-size:12px">для вариантов с джобой bj пишет служебное событие BJ_PING и ждёт до 40 с, пока обработчик его отметит</span>
|
||||
</div>
|
||||
{{if .Settings.Fancy.DepoJobCheck}}<p style="margin-top:10px;font-size:13px;{{if .Settings.Fancy.DepoJobCheckOK}}color:var(--ok){{else}}color:var(--err){{end}}">{{if .Settings.Fancy.DepoJobCheckOK}}✓{{else}}✗{{end}} {{.Settings.Fancy.DepoJobCheck}} <span class="muted">({{.Settings.Fancy.DepoJobCheckAt.Format "02.01.2006 15:04"}})</span></p>{{end}}
|
||||
{{if .Settings.Fancy.DepoProcCheck}}<p style="margin-top:4px;font-size:13px;{{if .Settings.Fancy.DepoProcCheckOK}}color:var(--ok){{else}}color:var(--warn){{end}}">Обработка событий (процедуры): {{if .Settings.Fancy.DepoProcCheckOK}}✓{{else}}⚠{{end}} {{.Settings.Fancy.DepoProcCheck}}</p>{{end}}
|
||||
{{if and (eq .Settings.Fancy.DepoJobMode "bj") .Settings.Fancy.DepoJobLast}}<p class="muted" style="font-size:12px;margin-top:6px">Последний вызов процедуры — {{.Settings.Fancy.DepoJobLast}}</p>{{end}}
|
||||
{{end}}
|
||||
</div>
|
||||
|
||||
@@ -151,7 +151,13 @@ func (h *setupHandlers) wizardDepoJob(w http.ResponseWriter, r *http.Request) {
|
||||
jobNote = "джоба " + depoJobName + " создана. "
|
||||
}
|
||||
}
|
||||
msg, ok := depoJobCheck(ctx, h.rc)
|
||||
// проверяем запуск джобы (не процедуры): только что созданная джоба запускается в течение интервала — ждём
|
||||
au, ap := r.FormValue("admin_user"), r.FormValue("admin_password")
|
||||
msg, ok := depoJobRunnerCheck(ctx, h.rc, au, ap)
|
||||
for i := 0; !ok && i < 6 && strings.Contains(msg, "ни разу не запускалась"); i++ {
|
||||
time.Sleep(5 * time.Second)
|
||||
msg, ok = depoJobRunnerCheck(ctx, h.rc, au, ap)
|
||||
}
|
||||
msg = jobNote + msg
|
||||
s = h.rc.Snapshot().Fancy
|
||||
s.DepoJobCheck, s.DepoJobCheckOK, s.DepoJobCheckAt = msg, ok, time.Now()
|
||||
@@ -182,8 +188,10 @@ func (h *setupHandlers) wizardDepoRecheck(w http.ResponseWriter, r *http.Request
|
||||
return
|
||||
}
|
||||
jmsg, jok := depoJobCheck(ctx, h.rc)
|
||||
pmsg, pok := depoProcCheck(ctx, h.rc) // обработка событий — отдельно, шаг не держит
|
||||
s = h.rc.Snapshot().Fancy
|
||||
s.DepoJobCheck, s.DepoJobCheckOK, s.DepoJobCheckAt = jmsg, jok, time.Now()
|
||||
s.DepoProcCheck, s.DepoProcCheckOK, s.DepoProcCheckAt = pmsg, pok, time.Now()
|
||||
_ = h.rc.UpdateFancy(s)
|
||||
if !jok {
|
||||
wizDepoGo(w, r, "job", jmsg, false)
|
||||
|
||||
Reference in New Issue
Block a user