Explorar el Código

fix(upstream): improve caching mechanism for disabled sockets and ensure cache validity

0xJacky hace 4 meses
padre
commit
ae86ef7a0c
Se han modificado 5 ficheros con 274 adiciones y 254 borrados
  1. 7 0
      api/upstream/list.go
  2. 2 7
      app/components.d.ts
  3. 5 5
      app/package.json
  4. 236 219
      app/pnpm-lock.yaml
  5. 24 23
      internal/upstream/service.go

+ 7 - 0
api/upstream/list.go

@@ -115,6 +115,9 @@ func UpdateUpstreamConfig(c *gin.Context) {
 			cosy.ErrHandler(c, err)
 			return
 		}
+		// Invalidate cache after creating new config
+		service := upstream.GetUpstreamService()
+		service.InvalidateDisabledSocketsCache()
 	} else {
 		// Update existing config
 		if _, err := u.Where(u.Socket.Eq(name)).Update(u.Enabled, req.Enabled); err != nil {
@@ -124,6 +127,10 @@ func UpdateUpstreamConfig(c *gin.Context) {
 		}
 	}
 
+	// Invalidate the disabled sockets cache to ensure changes take effect immediately
+	service := upstream.GetUpstreamService()
+	service.InvalidateDisabledSocketsCache()
+
 	c.JSON(http.StatusOK, gin.H{
 		"message": "Upstream config updated successfully",
 	})

+ 2 - 7
app/components.d.ts

@@ -10,7 +10,6 @@ declare module 'vue' {
   export interface GlobalComponents {
     AAlert: typeof import('ant-design-vue/es')['Alert']
     AApp: typeof import('ant-design-vue/es')['App']
-    AAutoComplete: typeof import('ant-design-vue/es')['AutoComplete']
     AAvatar: typeof import('ant-design-vue/es')['Avatar']
     ABadge: typeof import('ant-design-vue/es')['Badge']
     ABreadcrumb: typeof import('ant-design-vue/es')['Breadcrumb']
@@ -18,19 +17,16 @@ declare module 'vue' {
     AButton: typeof import('ant-design-vue/es')['Button']
     ACard: typeof import('ant-design-vue/es')['Card']
     ACheckbox: typeof import('ant-design-vue/es')['Checkbox']
+    ACheckboxGroup: typeof import('ant-design-vue/es')['CheckboxGroup']
     ACol: typeof import('ant-design-vue/es')['Col']
-    ACollapse: typeof import('ant-design-vue/es')['Collapse']
-    ACollapsePanel: typeof import('ant-design-vue/es')['CollapsePanel']
     AConfigProvider: typeof import('ant-design-vue/es')['ConfigProvider']
     ADivider: typeof import('ant-design-vue/es')['Divider']
     ADrawer: typeof import('ant-design-vue/es')['Drawer']
-    ADropdown: typeof import('ant-design-vue/es')['Dropdown']
     AEmpty: typeof import('ant-design-vue/es')['Empty']
     AForm: typeof import('ant-design-vue/es')['Form']
     AFormItem: typeof import('ant-design-vue/es')['FormItem']
     AInput: typeof import('ant-design-vue/es')['Input']
     AInputGroup: typeof import('ant-design-vue/es')['InputGroup']
-    AInputPassword: typeof import('ant-design-vue/es')['InputPassword']
     ALayout: typeof import('ant-design-vue/es')['Layout']
     ALayoutContent: typeof import('ant-design-vue/es')['LayoutContent']
     ALayoutFooter: typeof import('ant-design-vue/es')['LayoutFooter']
@@ -50,14 +46,13 @@ declare module 'vue' {
     ASelect: typeof import('ant-design-vue/es')['Select']
     ASelectOption: typeof import('ant-design-vue/es')['SelectOption']
     ASpace: typeof import('ant-design-vue/es')['Space']
-    ASpin: typeof import('ant-design-vue/es')['Spin']
     AStatistic: typeof import('ant-design-vue/es')['Statistic']
     ASubMenu: typeof import('ant-design-vue/es')['SubMenu']
     ASwitch: typeof import('ant-design-vue/es')['Switch']
+    ATable: typeof import('ant-design-vue/es')['Table']
     ATabPane: typeof import('ant-design-vue/es')['TabPane']
     ATabs: typeof import('ant-design-vue/es')['Tabs']
     ATag: typeof import('ant-design-vue/es')['Tag']
-    ATextarea: typeof import('ant-design-vue/es')['Textarea']
     ATooltip: typeof import('ant-design-vue/es')['Tooltip']
     ATypographyText: typeof import('ant-design-vue/es')['TypographyText']
     AutoCertFormAutoCertForm: typeof import('./src/components/AutoCertForm/AutoCertForm.vue')['default']

+ 5 - 5
app/package.json

@@ -17,8 +17,8 @@
     "@ant-design/icons-vue": "^7.0.1",
     "@fingerprintjs/fingerprintjs": "^4.6.2",
     "@formkit/auto-animate": "^0.9.0",
-    "@simplewebauthn/browser": "^13.2.0",
-    "@uozi-admin/curd": "^4.17.0",
+    "@simplewebauthn/browser": "^13.2.2",
+    "@uozi-admin/curd": "^4.17.1",
     "@uozi-admin/request": "^2.9.1",
     "@vue/reactivity": "^3.5.22",
     "@vue/shared": "^3.5.22",
@@ -79,7 +79,7 @@
     "@vue/tsconfig": "^0.8.1",
     "ace-builds": "^1.43.3",
     "autoprefixer": "^10.4.21",
-    "eslint": "^9.36.0",
+    "eslint": "^9.37.0",
     "eslint-plugin-sonarjs": "^3.0.5",
     "less": "^4.4.1",
     "postcss": "^8.5.6",
@@ -87,9 +87,9 @@
     "unplugin-auto-import": "^20.2.0",
     "unplugin-vue-components": "^29.1.0",
     "unplugin-vue-define-options": "^3.1.1",
-    "vite": "^7.1.8",
+    "vite": "^7.1.9",
     "vite-plugin-inspect": "^11.3.3",
     "vite-svg-loader": "^5.1.0",
     "vue-tsc": "^3.1.0"
   }
-}
+}

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 236 - 219
app/pnpm-lock.yaml


+ 24 - 23
internal/upstream/service.go

@@ -33,16 +33,15 @@ type Service struct {
 	availabilityMap map[string]*Status     // key: host:port
 	configTargets   map[string][]string    // configPath -> []targetKeys
 	// Public upstream definitions storage
-	Upstreams                   map[string]*Definition // key: upstream name
-	upstreamsMutex              sync.RWMutex
-	targetsMutex                sync.RWMutex
-	lastUpdateTime              time.Time
-	testInProgress              bool
-	testMutex                   sync.Mutex
-	cachedDisabledSockets       map[string]bool
-	disabledSocketsCacheMutex   sync.RWMutex
-	disabledSocketsCacheExpiry  time.Time
-	disabledSocketsCacheDuration time.Duration
+	Upstreams                 map[string]*Definition // key: upstream name
+	upstreamsMutex            sync.RWMutex
+	targetsMutex              sync.RWMutex
+	lastUpdateTime            time.Time
+	testInProgress            bool
+	testMutex                 sync.Mutex
+	cachedDisabledSockets     map[string]bool
+	disabledSocketsCacheMutex sync.RWMutex
+	disabledSocketsCacheValid bool // true if cache is valid, false if needs refresh
 }
 
 var (
@@ -70,12 +69,12 @@ func formatSocketAddress(host, port string) string {
 func GetUpstreamService() *Service {
 	serviceOnce.Do(func() {
 		upstreamService = &Service{
-			targets:                      make(map[string]*TargetInfo),
-			availabilityMap:              make(map[string]*Status),
-			configTargets:                make(map[string][]string),
-			Upstreams:                    make(map[string]*Definition),
-			lastUpdateTime:               time.Now(),
-			disabledSocketsCacheDuration: 30 * time.Second,
+			targets:                   make(map[string]*TargetInfo),
+			availabilityMap:           make(map[string]*Status),
+			configTargets:             make(map[string][]string),
+			Upstreams:                 make(map[string]*Definition),
+			lastUpdateTime:            time.Now(),
+			disabledSocketsCacheValid: false, // Initialize as invalid to force first load
 		}
 	})
 	return upstreamService
@@ -309,11 +308,11 @@ func (s *Service) findUpstreamNameForTarget(target ProxyTarget) string {
 	return ""
 }
 
-// getDisabledSockets queries the database for disabled sockets with caching
+// getDisabledSockets queries the database for disabled sockets with event-driven caching
 func (s *Service) getDisabledSockets() map[string]bool {
-	// Check if cache is still valid
+	// Check if cache is valid
 	s.disabledSocketsCacheMutex.RLock()
-	if time.Now().Before(s.disabledSocketsCacheExpiry) && s.cachedDisabledSockets != nil {
+	if s.disabledSocketsCacheValid && s.cachedDisabledSockets != nil {
 		// Return a copy of the cached data
 		result := make(map[string]bool, len(s.cachedDisabledSockets))
 		for k, v := range s.cachedDisabledSockets {
@@ -324,7 +323,7 @@ func (s *Service) getDisabledSockets() map[string]bool {
 	}
 	s.disabledSocketsCacheMutex.RUnlock()
 
-	// Cache expired or not initialized, refresh from database
+	// Cache invalid or not initialized, refresh from database
 	disabled := make(map[string]bool)
 
 	db := model.UseDB()
@@ -342,12 +341,14 @@ func (s *Service) getDisabledSockets() map[string]bool {
 		disabled[config.Socket] = true
 	}
 
-	// Update cache
+	// Update cache and mark as valid
 	s.disabledSocketsCacheMutex.Lock()
 	s.cachedDisabledSockets = disabled
-	s.disabledSocketsCacheExpiry = time.Now().Add(s.disabledSocketsCacheDuration)
+	s.disabledSocketsCacheValid = true
 	s.disabledSocketsCacheMutex.Unlock()
 
+	logger.Debug("Disabled sockets cache refreshed from database, found", len(disabled), "disabled sockets")
+
 	// Return a copy to prevent external modification
 	result := make(map[string]bool, len(disabled))
 	for k, v := range disabled {
@@ -360,7 +361,7 @@ func (s *Service) getDisabledSockets() map[string]bool {
 func (s *Service) InvalidateDisabledSocketsCache() {
 	s.disabledSocketsCacheMutex.Lock()
 	defer s.disabledSocketsCacheMutex.Unlock()
-	s.disabledSocketsCacheExpiry = time.Time{} // Set to zero time to force refresh
+	s.disabledSocketsCacheValid = false
 	logger.Debug("Disabled sockets cache invalidated")
 }
 

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio