mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-10-25 23:35:00 +03:00
73fad424ed
Every subscription fetch read and scanned each inbound's whole settings blob, about 25 MB at 100k clients, although subscription bodies resolve their clients from the clients table and never use its clients array. Each inbound's settings minus the clients array are now cached, keyed by inbound and shared by all its subscribers; the inbound row, clients, stats and hosts are still read per fetch, and WireGuard and AmneziaWG keep full settings for their peers. Panel edits purge the cache through an invalidator registry the subscription server releases on stop, with a 10 s TTL as the backstop. At 100k clients a hit takes 2.1 ms on SQLite (72.5 ms before) and 20.7 ms on PostgreSQL (332 ms).
35 lines
998 B
Go
35 lines
998 B
Go
package service
|
|
|
|
import "sync"
|
|
|
|
var (
|
|
subDataInvalidatorsMu sync.Mutex
|
|
subDataInvalidators = map[int]func(){}
|
|
nextSubDataInvalidator int
|
|
)
|
|
|
|
// RegisterSubDataInvalidator registers a callback run after any mutation that can change what a
|
|
// subscription serves; release unregisters it, so a stopped subscription server's cache goes.
|
|
func RegisterSubDataInvalidator(f func()) (release func()) {
|
|
subDataInvalidatorsMu.Lock()
|
|
defer subDataInvalidatorsMu.Unlock()
|
|
id := nextSubDataInvalidator
|
|
nextSubDataInvalidator++
|
|
subDataInvalidators[id] = f
|
|
return func() {
|
|
subDataInvalidatorsMu.Lock()
|
|
defer subDataInvalidatorsMu.Unlock()
|
|
delete(subDataInvalidators, id)
|
|
}
|
|
}
|
|
|
|
// InvalidateSubData drops every registered subscription snapshot. Purging is
|
|
// clearing a small map, so callers never need to compute affected subIds.
|
|
func InvalidateSubData() {
|
|
subDataInvalidatorsMu.Lock()
|
|
defer subDataInvalidatorsMu.Unlock()
|
|
for _, invalidate := range subDataInvalidators {
|
|
invalidate()
|
|
}
|
|
}
|