diff --git a/internal/lkgateway/incoming_order.go b/internal/lkgateway/incoming_order.go index 9022b2e..c0a030a 100644 --- a/internal/lkgateway/incoming_order.go +++ b/internal/lkgateway/incoming_order.go @@ -210,25 +210,14 @@ func findOrderResponses(contrDID string) []orderResponse { if contrDID == "" { return nil } - entries, err := os.ReadDir(igwInboxDir) - if err != nil { - return nil - } type rr struct { resp orderResponse mt time.Time } var tmp []rr - for _, e := range entries { - if !e.IsDir() { - continue - } - dir := e.Name() - if strings.HasPrefix(dir, "#") || dir == "INBOX" { // наши M2M-пакеты — не ответ - continue - } - body, mt := readPkgText(filepath.Join(igwInboxDir, dir)) - if body == "" || !strings.Contains(body, contrDID) { + for _, pk := range pkgIndex() { + dir, body, mt := pk.dir, pk.body, pk.mt + if !strings.Contains(body, contrDID) { continue } kind, done := orderRespKind(dir, body) @@ -311,6 +300,49 @@ func collectOrderResponseRaw(contrDID string) []respFile { // readPkgText собирает текст всех документов пакета: распакованные xml/htm/rpt и // содержимое вложенных zip (декодирует windows-1251). Возвращает текст и время. +// pkgIndex — все пакеты-ответы во входящем каталоге ИШ с их текстом, одним проходом и с +// коротким кэшем: поиск ответов по номерам поручений идёт по памяти, а не по диску на +// каждый номер (сотни номеров × две тысячи каталогов давали сотни миллисекунд на страницу). +type pkgIndexEntry struct { + dir, body string + mt time.Time +} + +var pkgIndexCache = struct { + mu sync.Mutex + at time.Time + list []pkgIndexEntry +}{} + +func pkgIndex() []pkgIndexEntry { + pkgIndexCache.mu.Lock() + defer pkgIndexCache.mu.Unlock() + if pkgIndexCache.list != nil && time.Since(pkgIndexCache.at) < 3*time.Second { + return pkgIndexCache.list + } + entries, err := os.ReadDir(igwInboxDir) + if err != nil { + return nil + } + list := make([]pkgIndexEntry, 0, len(entries)) + for _, e := range entries { + if !e.IsDir() { + continue + } + dir := e.Name() + if strings.HasPrefix(dir, "#") || dir == "INBOX" { // наши M2M-пакеты — не ответ + continue + } + body, mt := readPkgText(filepath.Join(igwInboxDir, dir)) + if body == "" { + continue + } + list = append(list, pkgIndexEntry{dir: dir, body: body, mt: mt}) + } + pkgIndexCache.list, pkgIndexCache.at = list, time.Now() + return list +} + // pkgTextCache — разобранный текст пакетов ИШ по каталогу: пакет после получения не меняется, // поэтому перечитывать его файлы при каждом обходе журнала незачем. Ключ проверки — время // изменения каталога пакета и число файлов в нём.