Files
CLIProxyAPI/internal/pluginhost/client_guard.go
Luis Pater 0ed85bb88b feat(pluginhost): refactor and enhance plugin system with new execution and thinking capabilities
- Removed `examples/plugin/main.go` and `internal/pluginhost/loader_plugin.go` after migrating to a more modular system.
- Introduced `streamBridge` in `internal/pluginhost/stream_bridge.go` for efficient stream handling and communication.
- Added examples of `thinking` plugins written in both Rust and Go under `examples/plugin/thinking`.
- Enhanced test coverage for plugin host system changes, including stream chunk translation and thinking logic.
- Improved API compatibility and ensured backward-compatible upgrades for plugin execution.
2026-06-07 03:20:04 +08:00

80 lines
1.3 KiB
Go

package pluginhost
import (
"context"
"fmt"
"sync"
)
type guardedPluginClient struct {
mu sync.Mutex
cond *sync.Cond
inner pluginClient
calls int
closed bool
}
func newGuardedPluginClient(inner pluginClient) pluginClient {
client := &guardedPluginClient{inner: inner}
client.cond = sync.NewCond(&client.mu)
return client
}
func (c *guardedPluginClient) Call(ctx context.Context, method string, request []byte) ([]byte, error) {
inner, errAcquire := c.acquire()
if errAcquire != nil {
return nil, errAcquire
}
defer c.release()
return inner.Call(ctx, method, request)
}
func (c *guardedPluginClient) acquire() (pluginClient, error) {
if c == nil {
return nil, fmt.Errorf("plugin client is closed")
}
c.mu.Lock()
defer c.mu.Unlock()
if c.closed || c.inner == nil {
return nil, fmt.Errorf("plugin client is closed")
}
c.calls++
return c.inner, nil
}
func (c *guardedPluginClient) release() {
c.mu.Lock()
c.calls--
if c.calls == 0 {
c.cond.Broadcast()
}
c.mu.Unlock()
}
func (c *guardedPluginClient) Shutdown() {
if c == nil {
return
}
var inner pluginClient
c.mu.Lock()
if c.closed {
for c.calls > 0 {
c.cond.Wait()
}
c.mu.Unlock()
return
}
c.closed = true
for c.calls > 0 {
c.cond.Wait()
}
inner = c.inner
c.inner = nil
c.mu.Unlock()
if inner != nil {
inner.Shutdown()
}
}