mirror of
https://github.com/photoprism/photoprism.git
synced 2026-07-17 16:49:04 +00:00
Backend: Compact verbose comments in config and MCP handler
This commit is contained in:
parent
2e93a02195
commit
c802b05e09
2 changed files with 17 additions and 55 deletions
|
|
@ -67,14 +67,8 @@ func ServeMCP(router *gin.RouterGroup) {
|
|||
Version: conf.Version(),
|
||||
}, conf.Edition())
|
||||
|
||||
// Streamable HTTP handler. Warn-level logging keeps the default log
|
||||
// quiet under normal operation while still surfacing SDK warnings.
|
||||
// McpSessionTimeout bounds how long idle sessions linger; active
|
||||
// clients renew the timer on every request, so interactive IDE use
|
||||
// is unaffected while abandoned sessions free up promptly.
|
||||
// CrossOriginProtection must be set explicitly: go-sdk v1.6.0 dropped
|
||||
// the implicit default that previously rejected cross-origin requests
|
||||
// when the field was nil (modelcontextprotocol/go-sdk#906).
|
||||
// Streamable HTTP handler with warn-level logging and an explicit
|
||||
// CrossOriginProtection (go-sdk no longer enables it implicitly).
|
||||
handler := sdkmcp.NewStreamableHTTPHandler(
|
||||
func(r *http.Request) *sdkmcp.Server { return mcpServer },
|
||||
&sdkmcp.StreamableHTTPOptions{
|
||||
|
|
@ -84,16 +78,10 @@ func ServeMCP(router *gin.RouterGroup) {
|
|||
},
|
||||
)
|
||||
|
||||
// mcpHandler authenticates each request, caps the JSON-RPC payload
|
||||
// size before delegating to the SDK handler, and translates an
|
||||
// oversized-body condition into a standard 413 response. In public
|
||||
// mode Session() returns the default public session (treated as
|
||||
// admin by the ACL), so the read-only tools registered today are
|
||||
// reachable anonymously — intentional to support demo deployments
|
||||
// such as demo.photoprism.app. Any future tool that touches
|
||||
// per-user state, the database, or mutates anything MUST NOT be
|
||||
// registered on this shared server without an additional per-tool
|
||||
// gate; see internal/mcp/README.md for the recommended patterns.
|
||||
// mcpHandler authenticates each request, caps the JSON-RPC payload size,
|
||||
// and surfaces 413 on overflow. Public mode reaches read-only tools as
|
||||
// the default public session; any tool that touches per-user state must
|
||||
// add an explicit gate before being registered on this shared server.
|
||||
mcpHandler := func(c *gin.Context) {
|
||||
s := Auth(c, acl.ResourceMCP, acl.ActionView)
|
||||
|
||||
|
|
@ -112,13 +100,8 @@ func ServeMCP(router *gin.RouterGroup) {
|
|||
return
|
||||
}
|
||||
|
||||
// Cap the request body size before the upstream SDK reads it
|
||||
// via io.ReadAll. LimitRequestBodyBytes swaps c.Request.Body
|
||||
// for an http.MaxBytesReader, matching the shared pattern used
|
||||
// by every other JSON API handler; mcpLimitReader then tracks
|
||||
// whether the cap was exceeded so the response-writer wrapper
|
||||
// can rewrite the SDK's 400 "failed to read body" into the
|
||||
// standard 413 we use for oversized JSON bodies elsewhere.
|
||||
// Cap the body before the SDK reads it; the wrapper rewrites the
|
||||
// SDK's "failed to read body" 400 into a standard 413 on overflow.
|
||||
LimitRequestBodyBytes(c, MaxMCPRequestBytes)
|
||||
|
||||
tripped := &atomic.Bool{}
|
||||
|
|
|
|||
|
|
@ -37,27 +37,12 @@ func (c *Config) IndexWorkersReason() string {
|
|||
return reason
|
||||
}
|
||||
|
||||
// indexWorkers derives the indexing worker count from the configured
|
||||
// option, the available logical CPUs (runtime.NumCPU(), cgroup-aware),
|
||||
// and the database driver. It returns both the count and a short reason
|
||||
// tag so callers can surface the rationale without re-deriving it.
|
||||
//
|
||||
// Auto-detection rules:
|
||||
//
|
||||
// low-memory below RecommendedMem we always run a single worker
|
||||
// sqlite-cap SQLite serializes writes, so cap to 4 on 8+ CPU hosts
|
||||
// or whenever the operator pinned more than 4
|
||||
// configured honor the operator override (clamped to runtime.NumCPU())
|
||||
// auto half of runtime.NumCPU() to leave headroom for OS, DB,
|
||||
// HTTP serving, and background workers
|
||||
// single-cpu exactly one CPU is visible — fall back to 1 worker
|
||||
//
|
||||
// The implementation deliberately does not consult cpuid.CPU.PhysicalCores
|
||||
// because that value reads CPUID leaf 0xB sub-leaf 1 (per package only,
|
||||
// not system-wide), can return 0 when the topology is masked by a
|
||||
// hypervisor, and is unreliable on dual-socket Xeons and hybrid Intel
|
||||
// CPUs. runtime.NumCPU() is the cgroup- and affinity-aware figure that
|
||||
// reflects what this process can actually schedule onto.
|
||||
// indexWorkers derives the indexing worker count from the configured option,
|
||||
// runtime.NumCPU(), and the database driver. Returns the count and a reason
|
||||
// tag (low-memory, sqlite-cap, configured, configured-clamped, auto, single-cpu)
|
||||
// so callers can surface the rationale without re-deriving it. Uses
|
||||
// runtime.NumCPU() (cgroup- and affinity-aware) rather than CPUID-based
|
||||
// physical-core probes, which are unreliable under virtualization.
|
||||
func (c *Config) indexWorkers() (n int, reason string) {
|
||||
// Cap to one worker on systems below the recommended memory threshold.
|
||||
if TotalMem < RecommendedMem {
|
||||
|
|
@ -88,10 +73,7 @@ func (c *Config) indexWorkers() (n int, reason string) {
|
|||
return configured, "configured"
|
||||
}
|
||||
|
||||
// Default to half the visible CPUs to leave headroom for the OS, the
|
||||
// database, HTTP serving, and other background workers. With HT this
|
||||
// approximates the physical core count without depending on a
|
||||
// fragile per-package CPUID read.
|
||||
// Half the visible CPUs leaves headroom for OS, DB, HTTP, and other workers.
|
||||
if half := cpus / 2; half >= 1 {
|
||||
return half, "auto"
|
||||
}
|
||||
|
|
@ -99,11 +81,8 @@ func (c *Config) indexWorkers() (n int, reason string) {
|
|||
return 1, "single-cpu"
|
||||
}
|
||||
|
||||
// parseIndexWorkers normalizes the configured index-workers option to an
|
||||
// integer. Empty strings, the IndexWorkersAuto sentinel, and unparsable
|
||||
// values map to 0 so IndexWorkers() falls through to the derived count;
|
||||
// numeric strings (positive or negative) parse with the same semantics
|
||||
// as the previous int field.
|
||||
// parseIndexWorkers normalizes the index-workers option to an int; empty,
|
||||
// "auto", and unparseable values return 0 to fall through to auto-derivation.
|
||||
func parseIndexWorkers(value string) int {
|
||||
value = strings.TrimSpace(value)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue