| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677 |
- package service
- import (
- "context"
- "sync"
- "time"
- openaiwsv2 "github.com/Wei-Shaw/sub2api/internal/service/openai_ws_v2"
- coderws "github.com/coder/websocket"
- "github.com/tidwall/gjson"
- )
- // Passthrough may carry many independent response.create turns. Count each
- // turn, release at its terminal event, and do not charge session.update/pings.
- type accountTrafficFrameConn struct {
- inner openaiwsv2.FrameConn
- control *AccountTrafficService
- plan AccountTrafficPlan
- ctx context.Context
- mu sync.Mutex
- permit *AccountTrafficPermit
- }
- func (c *accountTrafficFrameConn) finish(status int) {
- c.mu.Lock()
- p := c.permit
- c.permit = nil
- c.mu.Unlock()
- p.Finish(status)
- }
- func (c *accountTrafficFrameConn) ReadFrame(ctx context.Context) (coderws.MessageType, []byte, error) {
- kind, payload, err := c.inner.ReadFrame(ctx)
- if err != nil {
- c.finish(0)
- return kind, payload, err
- }
- if status, terminal := accountTrafficEventStatus(payload); terminal {
- c.finish(status)
- }
- return kind, payload, nil
- }
- func (c *accountTrafficFrameConn) WriteFrame(ctx context.Context, kind coderws.MessageType, payload []byte) error {
- if gjson.GetBytes(payload, "type").String() != "response.create" {
- return c.inner.WriteFrame(ctx, kind, payload)
- }
- c.mu.Lock()
- if c.permit != nil {
- c.mu.Unlock()
- return (&AccountTrafficLimitError{Reason: "上一轮请求尚未结束,请等待后重试", RetryAfter: time.Second}).FailoverError()
- }
- _, p, err := c.control.Begin(c.ctx, c.plan, func() { _ = c.inner.Close() })
- if err != nil {
- c.mu.Unlock()
- if failure := AccountTrafficFailover(err); failure != nil {
- return failure
- }
- return err
- }
- c.permit = p
- c.mu.Unlock()
- err = c.inner.WriteFrame(ctx, kind, payload)
- if err != nil {
- c.finish(0)
- }
- return err
- }
- func (c *accountTrafficFrameConn) Close() error { c.finish(0); return c.inner.Close() }
- func wrapAccountTrafficFrameConn(ctx context.Context, upstream HTTPUpstream, a *Account, inner openaiwsv2.FrameConn) (openaiwsv2.FrameConn, error) {
- plan, err := AccountTrafficPlanFor(a)
- if err != nil {
- return nil, err
- }
- if !plan.Policy.Enabled() {
- return inner, nil
- }
- return &accountTrafficFrameConn{inner: inner, control: accountTrafficController(upstream), plan: plan, ctx: ctx}, nil
- }
|