- windsurf_gateway_service: 添加上游延迟/TTFT/错误上下文记录 - endpoint: DeriveUpstreamEndpoint 添加 PlatformWindsurf 分支 - ops_error_logger: guessPlatformFromPath 添加 /windsurf/ 识别
159 lines
3.5 KiB
Go
159 lines
3.5 KiB
Go
package windsurf
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"sync"
|
|
)
|
|
|
|
type LSConnector interface {
|
|
Mode() string
|
|
Acquire(ctx context.Context, proxyURL string) (*LSLease, error)
|
|
Health(ctx context.Context) error
|
|
Status() *LSConnectorStatus
|
|
}
|
|
|
|
type LSLease struct {
|
|
Mode string
|
|
Endpoint string
|
|
Client *LocalLSClient
|
|
Release func()
|
|
}
|
|
|
|
type LSConnectorStatus struct {
|
|
Mode string `json:"mode"`
|
|
Healthy bool `json:"healthy"`
|
|
Instances int `json:"instances"`
|
|
Endpoint string `json:"endpoint,omitempty"`
|
|
}
|
|
|
|
type DockerConnector struct {
|
|
host string
|
|
port int
|
|
csrfToken string
|
|
client *LocalLSClient
|
|
once sync.Once
|
|
}
|
|
|
|
func NewDockerConnector(host string, port int, csrfToken string) *DockerConnector {
|
|
return &DockerConnector{host: host, port: port, csrfToken: csrfToken}
|
|
}
|
|
|
|
func (d *DockerConnector) Mode() string { return "docker" }
|
|
|
|
func (d *DockerConnector) Acquire(_ context.Context, _ string) (*LSLease, error) {
|
|
d.once.Do(func() {
|
|
d.client = NewLocalLSClient(d.port, d.csrfToken)
|
|
d.client.BaseURL = fmt.Sprintf("http://%s:%d", d.host, d.port)
|
|
})
|
|
return &LSLease{
|
|
Mode: "docker",
|
|
Endpoint: fmt.Sprintf("%s:%d", d.host, d.port),
|
|
Client: d.client,
|
|
Release: func() {},
|
|
}, nil
|
|
}
|
|
|
|
func (d *DockerConnector) Health(ctx context.Context) error {
|
|
_, err := d.Acquire(ctx, "")
|
|
return err
|
|
}
|
|
|
|
func (d *DockerConnector) Status() *LSConnectorStatus {
|
|
return &LSConnectorStatus{
|
|
Mode: "docker",
|
|
Healthy: d.client != nil,
|
|
Instances: 1,
|
|
Endpoint: fmt.Sprintf("%s:%d", d.host, d.port),
|
|
}
|
|
}
|
|
|
|
type EmbeddedConnector struct {
|
|
pool *LSPool
|
|
}
|
|
|
|
func NewEmbeddedConnector(pool *LSPool) *EmbeddedConnector {
|
|
return &EmbeddedConnector{pool: pool}
|
|
}
|
|
|
|
func (e *EmbeddedConnector) Mode() string { return "embedded" }
|
|
|
|
func (e *EmbeddedConnector) Acquire(ctx context.Context, proxyURL string) (*LSLease, error) {
|
|
entry, err := e.pool.Ensure(ctx, proxyURL)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &LSLease{
|
|
Mode: "embedded",
|
|
Endpoint: fmt.Sprintf("localhost:%d", entry.Port),
|
|
Client: entry.Client,
|
|
Release: func() {},
|
|
}, nil
|
|
}
|
|
|
|
func (e *EmbeddedConnector) Health(_ context.Context) error {
|
|
status := e.pool.Status()
|
|
if !status.Running {
|
|
return fmt.Errorf("no LS instances running")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (e *EmbeddedConnector) Status() *LSConnectorStatus {
|
|
status := e.pool.Status()
|
|
readyCount := 0
|
|
for _, inst := range status.Instances {
|
|
if inst.Ready {
|
|
readyCount++
|
|
}
|
|
}
|
|
return &LSConnectorStatus{
|
|
Mode: "embedded",
|
|
Healthy: readyCount > 0,
|
|
Instances: len(status.Instances),
|
|
}
|
|
}
|
|
|
|
type ExternalConnector struct {
|
|
baseURL string
|
|
port int
|
|
csrfToken string
|
|
client *LocalLSClient
|
|
once sync.Once
|
|
}
|
|
|
|
func NewExternalConnector(baseURL string, port int, csrfToken string) *ExternalConnector {
|
|
return &ExternalConnector{baseURL: baseURL, port: port, csrfToken: csrfToken}
|
|
}
|
|
|
|
func (x *ExternalConnector) Mode() string { return "external" }
|
|
|
|
func (x *ExternalConnector) Acquire(_ context.Context, _ string) (*LSLease, error) {
|
|
x.once.Do(func() {
|
|
x.client = NewLocalLSClient(x.port, x.csrfToken)
|
|
if x.baseURL != "" {
|
|
x.client.BaseURL = x.baseURL
|
|
}
|
|
})
|
|
return &LSLease{
|
|
Mode: "external",
|
|
Endpoint: x.baseURL,
|
|
Client: x.client,
|
|
Release: func() {},
|
|
}, nil
|
|
}
|
|
|
|
func (x *ExternalConnector) Health(ctx context.Context) error {
|
|
_, err := x.Acquire(ctx, "")
|
|
return err
|
|
}
|
|
|
|
func (x *ExternalConnector) Status() *LSConnectorStatus {
|
|
return &LSConnectorStatus{
|
|
Mode: "external",
|
|
Healthy: x.client != nil,
|
|
Instances: 1,
|
|
Endpoint: x.baseURL,
|
|
}
|
|
}
|