- CDN snapshot: batch merge после parallel fetch, без race на persist - ListRevisionPrefixes: лёгкая проверка revision вместо GetRevision - Jobs: timeout/cancel context для pipeline и deploy - HTTP server timeouts; кэш birdc для GET /peers - ListModules: batch DoH profiles одним запросом - Web: tab-scoped load на /operations, debounce job search, меньше over-fetch на dashboard Co-authored-by: Cursor <cursoragent@cursor.com>
81 lines
2.2 KiB
Go
81 lines
2.2 KiB
Go
package repository
|
|
|
|
import (
|
|
"context"
|
|
|
|
"evobgp/internal/store"
|
|
)
|
|
|
|
func (p *Postgres) fillModuleDohFields(ctx context.Context, m *store.Module) error {
|
|
if m == nil {
|
|
return nil
|
|
}
|
|
return p.batchFillModuleDohFields(ctx, map[string]*store.Module{m.ID: m})
|
|
}
|
|
|
|
func (p *Postgres) batchFillModuleDohFields(ctx context.Context, modules map[string]*store.Module) error {
|
|
if len(modules) == 0 {
|
|
return nil
|
|
}
|
|
ids := make([]string, 0, len(modules))
|
|
for id := range modules {
|
|
ids = append(ids, id)
|
|
}
|
|
rows, err := p.pool.Query(ctx, `
|
|
SELECT module_id::text, doh_profile_id::text
|
|
FROM module_doh_profile
|
|
WHERE module_id = ANY($1::uuid[])
|
|
ORDER BY module_id, sort_order, doh_profile_id`, ids)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer rows.Close()
|
|
byModule := make(map[string][]string, len(modules))
|
|
for rows.Next() {
|
|
var moduleID, profileID string
|
|
if err := rows.Scan(&moduleID, &profileID); err != nil {
|
|
return err
|
|
}
|
|
byModule[moduleID] = append(byModule[moduleID], profileID)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return err
|
|
}
|
|
for id, m := range modules {
|
|
m.DohProfileIDs = store.NormalizeDohProfileIDList(byModule[id])
|
|
m.SyncLegacyDohProfileID()
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (p *Postgres) setModuleDohProfiles(ctx context.Context, moduleID string, ids []string) error {
|
|
ids = store.NormalizeDohProfileIDList(ids)
|
|
if _, err := p.pool.Exec(ctx, `DELETE FROM module_doh_profile WHERE module_id = $1`, moduleID); err != nil {
|
|
return err
|
|
}
|
|
for i, id := range ids {
|
|
if _, err := p.pool.Exec(ctx, `
|
|
INSERT INTO module_doh_profile (module_id, doh_profile_id, sort_order)
|
|
VALUES ($1, $2, $3)`, moduleID, id, i); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
var dohArg any
|
|
if len(ids) > 0 {
|
|
dohArg = ids[0]
|
|
}
|
|
_, err := p.pool.Exec(ctx, `UPDATE module SET doh_profile_id = $2, updated_at = now() WHERE id = $1`, moduleID, dohArg)
|
|
return err
|
|
}
|
|
|
|
func (p *Postgres) moduleDohProfileInUse(ctx context.Context, dohProfileID string) (bool, error) {
|
|
var n int
|
|
if err := p.pool.QueryRow(ctx, `
|
|
SELECT COUNT(*) FROM module_doh_profile mdp
|
|
JOIN module m ON m.id = mdp.module_id
|
|
WHERE mdp.doh_profile_id = $1::uuid AND m.deleted_at IS NULL`, dohProfileID).Scan(&n); err != nil {
|
|
return false, err
|
|
}
|
|
return n > 0, nil
|
|
}
|