feat: enhance completion service with session management and language support
- Introduced session management using Redis for tracking active sessions. - Added session claiming and releasing functionality in the completion manager. - Enhanced HTTP and WebSocket completion endpoints to support multiple languages. - Implemented request timeout and maximum body size configurations for API routes. - Updated client-side code to handle session IDs and language parameters in completion requests. - Improved error handling for unsupported languages and session conflicts. - Added tests for the completion manager to ensure proper session handling and cleanup.
This commit is contained in:
@@ -33,6 +33,8 @@ type Client struct {
|
||||
nextID atomic.Int64
|
||||
|
||||
workspaceDir string
|
||||
languageID string
|
||||
clientName string
|
||||
|
||||
pendingMu sync.Mutex
|
||||
pending map[string]chan rpcResponse
|
||||
@@ -74,19 +76,33 @@ type lspCompletionList struct {
|
||||
Items []lspCompletionItem `json:"items"`
|
||||
}
|
||||
|
||||
func NewClient(parent context.Context, goplsPath, rootPath string) (*Client, error) {
|
||||
if goplsPath == "" {
|
||||
goplsPath = "gopls"
|
||||
type Config struct {
|
||||
Command string
|
||||
Args []string
|
||||
RootPath string
|
||||
LanguageID string
|
||||
ClientName string
|
||||
}
|
||||
|
||||
func NewClient(parent context.Context, cfg Config) (*Client, error) {
|
||||
if cfg.Command == "" {
|
||||
cfg.Command = "gopls"
|
||||
}
|
||||
if rootPath == "" {
|
||||
if cfg.RootPath == "" {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("get working directory: %w", err)
|
||||
}
|
||||
rootPath = cwd
|
||||
cfg.RootPath = cwd
|
||||
}
|
||||
if cfg.LanguageID == "" {
|
||||
cfg.LanguageID = "go"
|
||||
}
|
||||
if cfg.ClientName == "" {
|
||||
cfg.ClientName = "monica-lsp-gateway"
|
||||
}
|
||||
|
||||
cmd := exec.Command(goplsPath)
|
||||
cmd := exec.Command(cfg.Command, cfg.Args...)
|
||||
stdin, err := cmd.StdinPipe()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create stdin pipe: %w", err)
|
||||
@@ -98,13 +114,15 @@ func NewClient(parent context.Context, goplsPath, rootPath string) (*Client, err
|
||||
cmd.Stderr = os.Stderr
|
||||
|
||||
if err := cmd.Start(); err != nil {
|
||||
return nil, fmt.Errorf("start gopls: %w", err)
|
||||
return nil, fmt.Errorf("start language server %q: %w", cfg.Command, err)
|
||||
}
|
||||
|
||||
client := &Client{
|
||||
cmd: cmd,
|
||||
stdin: stdin,
|
||||
workspaceDir: rootPath,
|
||||
workspaceDir: cfg.RootPath,
|
||||
languageID: cfg.LanguageID,
|
||||
clientName: cfg.ClientName,
|
||||
pending: make(map[string]chan rpcResponse),
|
||||
exitCh: make(chan error, 1),
|
||||
}
|
||||
@@ -117,7 +135,7 @@ func NewClient(parent context.Context, goplsPath, rootPath string) (*Client, err
|
||||
initCtx, cancel := context.WithTimeout(parent, 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
if err := client.initialize(initCtx, rootPath); err != nil {
|
||||
if err := client.initialize(initCtx, cfg.RootPath); err != nil {
|
||||
_ = client.Close()
|
||||
return nil, err
|
||||
}
|
||||
@@ -150,7 +168,7 @@ func (c *Client) initialize(ctx context.Context, rootPath string) error {
|
||||
},
|
||||
},
|
||||
"clientInfo": map[string]string{
|
||||
"name": "monica-go-completion-backend",
|
||||
"name": c.clientName,
|
||||
"version": "0.1.0",
|
||||
},
|
||||
}
|
||||
@@ -174,7 +192,7 @@ func (c *Client) DidOpen(ctx context.Context, uri, text string, version int) err
|
||||
params := map[string]any{
|
||||
"textDocument": map[string]any{
|
||||
"uri": normalizedURI,
|
||||
"languageId": "go",
|
||||
"languageId": c.languageID,
|
||||
"version": version,
|
||||
"text": text,
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user