a0ffbfa721
На 9 после включения «для всех» (23.10.2026) каждый проход открывал по два соединения с DEPO на каждый из 1158 договоров — около 50 входов в MSSQL в секунду без перерыва, а проход шёл в цикле опроса заявок ЛК и задерживал его. - Остатки всех клиентов — одним запросом (fsql.Dp03), одно соединение с DEPO на проход; по списку — запрос по клиенту на том же соединении. На боевой DEPO: общий запрос 127 мс, совпадает с запросом по клиенту (58 договоров). - Свой цикл lkPortfolioLoop (здоровье «lk-portfolio»): по списку — каждые 10 с, для всех клиентов — раз в 5 мин. Опрос заявок ЛК больше не ждёт. - Проходы по очереди: фоновый и «Заполнить сейчас» не шлют один портфель дважды; принудительный проход пропускает отправленные за последнюю минуту. - ЛК не отвечает — проход прерывается; одна и та же ошибка отправки не повторяется в журнале каждый проход. Ошибка чтения DEPO снимается, когда портфель снова читается без изменений. - Настройки: итог (договоров, отправлено, нечего отправлять, с ошибкой), последние 5 отправок; договоры с ошибкой и все договоры — под раскрытием. «Отправлять нечего» — не ошибка (поле Nothing). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q7eREaYwUt1i4fNLZcGnjn
78 lines
2.2 KiB
Go
78 lines
2.2 KiB
Go
//go:build live
|
|
|
|
package lkgateway
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"sort"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// Остатки «для всех клиентов» одним запросом (Dp03) совпадают с запросом по клиенту (Dp01). Только чтение DEPO.
|
|
// PF_SETUP — копия setup.json (по умолчанию /var/lib/bj/.bj/setup.json).
|
|
func TestLKPortfolioAllLive(t *testing.T) {
|
|
path := os.Getenv("PF_SETUP")
|
|
if path == "" {
|
|
path = "/var/lib/bj/.bj/setup.json"
|
|
}
|
|
rc, err := NewRuntimeConfig(path)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
ctx := context.Background()
|
|
fs := rc.Snapshot().Fancy
|
|
db, err := fancyOpen(fs, fs.DepoDB())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer db.Close()
|
|
t0 := time.Now()
|
|
prs, err := lkPortfolioAllPairs(ctx, rc, db)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
t1 := time.Now()
|
|
all, err := depoAllPositions(ctx, db)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
t2 := time.Now()
|
|
by := lkPortfolioByPort(all, prs)
|
|
rows := 0
|
|
for _, p := range all {
|
|
rows += len(p)
|
|
}
|
|
t.Logf("договоров %d (%s); остатков %d по %d портфелям (%s); с остатками у договоров %d",
|
|
len(prs), t1.Sub(t0).Round(time.Millisecond), rows, len(all), t2.Sub(t1).Round(time.Millisecond), len(by))
|
|
key := func(ps []DepoPosition) string {
|
|
var k []string
|
|
for _, p := range ps {
|
|
k = append(k, fmt.Sprintf("%s|%s|%g", strings.TrimSpace(p.AccountNum), strings.TrimSpace(p.ISIN), p.Quantity))
|
|
}
|
|
sort.Strings(k)
|
|
return strings.Join(k, ";")
|
|
}
|
|
step, checked := len(prs)/60+1, 0
|
|
var one time.Duration
|
|
for i := 0; i < len(prs); i += step {
|
|
pr := prs[i]
|
|
s := time.Now()
|
|
want, err := depoClientPositionsDB(ctx, db, pr.Depo)
|
|
one += time.Since(s)
|
|
if err != nil {
|
|
t.Fatalf("%s: %v", pr.Depo, err)
|
|
}
|
|
if a, b := key(want), key(by[pr.Depo]); a != b {
|
|
t.Errorf("%s ← %s: по клиенту %d строк, общим запросом %d\n %s\n %s", pr.LK, pr.Depo, len(want), len(by[pr.Depo]), a, b)
|
|
}
|
|
checked++
|
|
}
|
|
if checked > 0 {
|
|
t.Logf("сверено договоров %d, запрос по клиенту в среднем %s", checked, (one / time.Duration(checked)).Round(time.Millisecond))
|
|
}
|
|
}
|