chore: align codebase with bible engineering contracts

- identifier-normalization: use strings.EqualFold in h3c/parser.go
- import-export: CSV now uses UTF-8 BOM and semicolon delimiter
- go-code-style: translate all Russian source strings to English (ADL-007)
- go-background-tasks: add Type, Message, Result fields to Job struct
- go-api: wrap list endpoints in {items, total_count, page, per_page, total_pages}
- module-structure: rename helpers.go → context_sleep.go
- build-version-display: htmlError renders version footer on error pages
- go-logging: migrate all log.Printf calls to log/slog with structured attrs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-13 14:35:39 +03:00
parent 47ff1c3796
commit 57de3ba6eb
14 changed files with 259 additions and 199 deletions
+22 -3
View File
@@ -3,6 +3,7 @@ package server
import (
"context"
"fmt"
"maps"
"sync"
"time"
)
@@ -22,9 +23,11 @@ func (m *JobManager) CreateJob(req CollectRequest) *Job {
now := time.Now().UTC()
job := &Job{
ID: generateJobID(),
Type: req.Protocol,
Status: CollectStatusQueued,
Progress: 0,
Logs: []string{formatCollectLogLine(now, "Задача поставлена в очередь")},
Message: "Job queued",
Logs: []string{formatCollectLogLine(now, "Job queued")},
CreatedAt: now,
UpdatedAt: now,
RequestMeta: CollectRequestMeta{
@@ -66,7 +69,7 @@ func (m *JobManager) CancelJob(id string) (*Job, bool) {
job.Status = CollectStatusCanceled
job.Error = ""
job.UpdatedAt = time.Now().UTC()
job.Logs = append(job.Logs, formatCollectLogLine(job.UpdatedAt, "Сбор отменен пользователем"))
job.Logs = append(job.Logs, formatCollectLogLine(job.UpdatedAt, "Collection canceled by user"))
}
cancelFn := job.cancel
@@ -122,6 +125,7 @@ func (m *JobManager) AppendJobLog(id, message string) (*Job, bool) {
job.Logs = append(job.Logs, message)
job.UpdatedAt = time.Now().UTC()
job.Logs[len(job.Logs)-1] = formatCollectLogLine(job.UpdatedAt, message)
job.Message = message
cloned := cloneJob(job)
m.mu.Unlock()
@@ -202,7 +206,7 @@ func (m *JobManager) SkipJob(id string) (*Job, bool) {
skipFn := job.skipFn
job.skipFn = nil
job.UpdatedAt = time.Now().UTC()
job.Logs = append(job.Logs, formatCollectLogLine(job.UpdatedAt, "Пропуск зависших запросов по команде пользователя"))
job.Logs = append(job.Logs, formatCollectLogLine(job.UpdatedAt, "Skipping stalled requests on user request"))
cloned := cloneJob(job)
m.mu.Unlock()
@@ -212,6 +216,18 @@ func (m *JobManager) SkipJob(id string) (*Job, bool) {
return cloned, true
}
func (m *JobManager) SetJobResult(id string, result map[string]interface{}) bool {
m.mu.Lock()
defer m.mu.Unlock()
job, ok := m.jobs[id]
if !ok || job == nil {
return false
}
job.Result = result
job.UpdatedAt = time.Now().UTC()
return true
}
func (m *JobManager) AttachJobCancel(id string, cancelFn context.CancelFunc) bool {
m.mu.Lock()
defer m.mu.Unlock()
@@ -265,6 +281,9 @@ func cloneJob(job *Job) *Job {
cloned.DebugInfo = cloneCollectDebugInfo(job.DebugInfo)
cloned.CurrentPhase = job.CurrentPhase
cloned.ETASeconds = job.ETASeconds
if job.Result != nil {
cloned.Result = maps.Clone(job.Result)
}
cloned.cancel = nil
cloned.skipFn = nil
return &cloned