This commit is contained in:
2025-11-17 15:39:44 +08:00
parent abfa51f12e
commit 1ddda89499
46 changed files with 2185 additions and 751 deletions

View File

@@ -8,6 +8,7 @@ import (
"github.com/gofiber/fiber/v3"
"github.com/any-hub/any-hub/internal/hubmodule"
"github.com/any-hub/any-hub/internal/proxy/hooks"
"github.com/any-hub/any-hub/internal/server"
)
@@ -18,9 +19,11 @@ func RegisterModuleRoutes(app *fiber.App, registry *server.HubRegistry) {
}
app.Get("/-/modules", func(c fiber.Ctx) error {
hookStatus := hooks.Snapshot(hubmodule.Keys())
payload := fiber.Map{
"modules": encodeModules(hubmodule.List()),
"hubs": encodeHubBindings(registry.List()),
"modules": encodeModules(hubmodule.List(), hookStatus),
"hubs": encodeHubBindings(registry.List()),
"hook_registry": hookStatus,
}
return c.JSON(payload)
})
@@ -34,35 +37,39 @@ func RegisterModuleRoutes(app *fiber.App, registry *server.HubRegistry) {
if !ok {
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "module_not_found"})
}
return c.JSON(encodeModule(meta))
encoded := encodeModule(meta)
encoded.HookStatus = hooks.Status(key)
return c.JSON(encoded)
})
}
type modulePayload struct {
Key string `json:"key"`
Description string `json:"description"`
Key string `json:"key"`
Description string `json:"description"`
MigrationState hubmodule.MigrationState `json:"migration_state"`
SupportedProtocols []string `json:"supported_protocols"`
CacheStrategy cacheStrategyPayload `json:"cache_strategy"`
SupportedProtocols []string `json:"supported_protocols"`
CacheStrategy cacheStrategyPayload `json:"cache_strategy"`
HookStatus string `json:"hook_status,omitempty"`
}
type cacheStrategyPayload struct {
TTLSeconds int64 `json:"ttl_seconds"`
ValidationMode string `json:"validation_mode"`
DiskLayout string `json:"disk_layout"`
RequiresMetadataFile bool `json:"requires_metadata_file"`
SupportsStreamingWrite bool `json:"supports_streaming_write"`
TTLSeconds int64 `json:"ttl_seconds"`
ValidationMode string `json:"validation_mode"`
DiskLayout string `json:"disk_layout"`
RequiresMetadataFile bool `json:"requires_metadata_file"`
SupportsStreamingWrite bool `json:"supports_streaming_write"`
}
type hubBindingPayload struct {
HubName string `json:"hub_name"`
ModuleKey string `json:"module_key"`
Domain string `json:"domain"`
Port int `json:"port"`
Rollout string `json:"rollout_flag"`
HubName string `json:"hub_name"`
ModuleKey string `json:"module_key"`
Domain string `json:"domain"`
Port int `json:"port"`
Rollout string `json:"rollout_flag"`
Legacy bool `json:"legacy_only"`
}
func encodeModules(mods []hubmodule.ModuleMetadata) []modulePayload {
func encodeModules(mods []hubmodule.ModuleMetadata, status map[string]string) []modulePayload {
if len(mods) == 0 {
return nil
}
@@ -71,7 +78,11 @@ func encodeModules(mods []hubmodule.ModuleMetadata) []modulePayload {
})
result := make([]modulePayload, 0, len(mods))
for _, meta := range mods {
result = append(result, encodeModule(meta))
item := encodeModule(meta)
if s, ok := status[meta.Key]; ok {
item.HookStatus = s
}
result = append(result, item)
}
return result
}
@@ -84,10 +95,10 @@ func encodeModule(meta hubmodule.ModuleMetadata) modulePayload {
MigrationState: meta.MigrationState,
SupportedProtocols: append([]string(nil), meta.SupportedProtocols...),
CacheStrategy: cacheStrategyPayload{
TTLSeconds: int64(strategy.TTLHint / time.Second),
ValidationMode: string(strategy.ValidationMode),
DiskLayout: strategy.DiskLayout,
RequiresMetadataFile: strategy.RequiresMetadataFile,
TTLSeconds: int64(strategy.TTLHint / time.Second),
ValidationMode: string(strategy.ValidationMode),
DiskLayout: strategy.DiskLayout,
RequiresMetadataFile: strategy.RequiresMetadataFile,
SupportsStreamingWrite: strategy.SupportsStreamingWrite,
},
}
@@ -108,6 +119,7 @@ func encodeHubBindings(routes []server.HubRoute) []hubBindingPayload {
Domain: route.Config.Domain,
Port: route.ListenPort,
Rollout: string(route.RolloutFlag),
Legacy: route.ModuleKey == hubmodule.DefaultModuleKey(),
})
}
return result

View File

@@ -0,0 +1,67 @@
package routes
import (
"testing"
"time"
"github.com/any-hub/any-hub/internal/hubmodule"
"github.com/any-hub/any-hub/internal/proxy/hooks"
)
func TestEncodeModulesAddsHookStatus(t *testing.T) {
modules := []hubmodule.ModuleMetadata{
{
Key: "b",
CacheStrategy: hubmodule.CacheStrategyProfile{
TTLHint: time.Hour,
ValidationMode: hubmodule.ValidationModeNever,
DiskLayout: "flat",
},
},
{
Key: "a",
CacheStrategy: hubmodule.CacheStrategyProfile{
TTLHint: time.Minute,
ValidationMode: hubmodule.ValidationModeNever,
DiskLayout: "flat",
},
},
}
status := map[string]string{"a": "registered"}
encoded := encodeModules(modules, status)
if len(encoded) != 2 {
t.Fatalf("expected 2 modules, got %d", len(encoded))
}
if encoded[0].Key != "a" {
t.Fatalf("expected sorted module key a first, got %s", encoded[0].Key)
}
if encoded[0].HookStatus != "registered" {
t.Fatalf("expected hook status registered for a, got %s", encoded[0].HookStatus)
}
if encoded[1].Key != "b" {
t.Fatalf("expected second module key b, got %s", encoded[1].Key)
}
if encoded[1].HookStatus != "" {
t.Fatalf("expected empty hook status for b, got %s", encoded[1].HookStatus)
}
}
func TestEncodeModuleAddsStatusForDetail(t *testing.T) {
key := "module-routes-test"
_ = hooks.Register(key, hooks.Hooks{})
meta := hubmodule.ModuleMetadata{
Key: key,
CacheStrategy: hubmodule.CacheStrategyProfile{
TTLHint: time.Minute,
ValidationMode: hubmodule.ValidationModeNever,
DiskLayout: "flat",
},
}
payload := encodeModule(meta)
payload.HookStatus = hooks.Status(key)
if payload.HookStatus != "registered" {
t.Fatalf("expected hook status registered, got %s", payload.HookStatus)
}
}