feat: add reliable event consumer SDK and process recovery tests

This commit is contained in:
2026-09-17 20:22:41 +08:00
parent 8485a662b2
commit b17d9b1977
25 changed files with 2170 additions and 28 deletions

View File

@@ -48,18 +48,23 @@ func integrationWorkerClient(t *testing.T) (*Client, string, string) {
// workerFaultGateway 在实际服务端确认后丢弃指定 ACK;SDK 到网关使用真实 TLS。
// 只丢响应,不伪造任务状态,测试凭据不进入 URL 或输出。
type workerFaultGateway struct {
drop atomic.Value
target atomic.Value
dropOffline atomic.Bool
dropCancel atomic.Bool
offline atomic.Bool
mu sync.Mutex
active map[*websocket.Conn]struct{}
dropped chan string
server *httptest.Server
confirmedEventPings atomic.Uint64
drop atomic.Value
target atomic.Value
dropOffline atomic.Bool
dropCancel atomic.Bool
offline atomic.Bool
mu sync.Mutex
active map[*websocket.Conn]struct{}
dropped chan string
server *httptest.Server
}
func newWorkerFaultGateway(t *testing.T, upstream string) *workerFaultGateway {
return newProtocolFaultGateway(t, upstream, "/v1/worker/connect", workerSubprotocol)
}
func newProtocolFaultGateway(t *testing.T, upstream, path, protocol string) *workerFaultGateway {
t.Helper()
g := &workerFaultGateway{dropped: make(chan string, 4), active: make(map[*websocket.Conn]struct{})}
g.drop.Store("")
@@ -77,14 +82,14 @@ func newWorkerFaultGateway(t *testing.T, upstream string) *workerFaultGateway {
defer stop()
header := http.Header{}
header.Set("Authorization", r.Header.Get("Authorization"))
up, _, err := websocket.Dial(bridge, g.target.Load().(string)+"/v1/worker/connect", &websocket.DialOptions{HTTPHeader: header, Subprotocols: []string{workerSubprotocol}})
up, _, err := websocket.Dial(bridge, g.target.Load().(string)+path, &websocket.DialOptions{HTTPHeader: header, Subprotocols: []string{protocol}})
if err != nil {
http.Error(w, "upstream unavailable", 503)
return
}
defer up.CloseNow()
up.SetReadLimit(512 << 10)
down, err := websocket.Accept(w, r, &websocket.AcceptOptions{Subprotocols: []string{workerSubprotocol}})
down, err := websocket.Accept(w, r, &websocket.AcceptOptions{Subprotocols: []string{protocol}})
if err != nil {
return
}
@@ -138,6 +143,9 @@ func newWorkerFaultGateway(t *testing.T, upstream string) *workerFaultGateway {
operation := operations[f.ReplyTo]
delete(operations, f.ReplyTo)
mu.Unlock()
if f.Type == "ack" && operation == "events.ping" {
g.confirmedEventPings.Add(1)
}
if f.Type == "task.cancel" && g.dropCancel.CompareAndSwap(true, false) {
g.dropped <- "task.cancel"
return