Журнал: индекс пакетов-ответов ИШ одним проходом (кэш 3 с), поиск по номерам поручений в памяти

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4YVo4UMopqT5DzicqpPjL
This commit is contained in:
zuevav
2026-09-18 14:22:05 +03:00
parent 1c2ba3285a
commit 05154898f7
+46 -14
View File
@@ -210,25 +210,14 @@ func findOrderResponses(contrDID string) []orderResponse {
if contrDID == "" { if contrDID == "" {
return nil return nil
} }
entries, err := os.ReadDir(igwInboxDir)
if err != nil {
return nil
}
type rr struct { type rr struct {
resp orderResponse resp orderResponse
mt time.Time mt time.Time
} }
var tmp []rr var tmp []rr
for _, e := range entries { for _, pk := range pkgIndex() {
if !e.IsDir() { dir, body, mt := pk.dir, pk.body, pk.mt
continue if !strings.Contains(body, contrDID) {
}
dir := e.Name()
if strings.HasPrefix(dir, "#") || dir == "INBOX" { // наши M2M-пакеты — не ответ
continue
}
body, mt := readPkgText(filepath.Join(igwInboxDir, dir))
if body == "" || !strings.Contains(body, contrDID) {
continue continue
} }
kind, done := orderRespKind(dir, body) kind, done := orderRespKind(dir, body)
@@ -311,6 +300,49 @@ func collectOrderResponseRaw(contrDID string) []respFile {
// readPkgText собирает текст всех документов пакета: распакованные xml/htm/rpt и // readPkgText собирает текст всех документов пакета: распакованные xml/htm/rpt и
// содержимое вложенных zip (декодирует windows-1251). Возвращает текст и время. // содержимое вложенных 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 — разобранный текст пакетов ИШ по каталогу: пакет после получения не меняется, // pkgTextCache — разобранный текст пакетов ИШ по каталогу: пакет после получения не меняется,
// поэтому перечитывать его файлы при каждом обходе журнала незачем. Ключ проверки — время // поэтому перечитывать его файлы при каждом обходе журнала незачем. Ключ проверки — время
// изменения каталога пакета и число файлов в нём. // изменения каталога пакета и число файлов в нём.