// event-protocol 验证冻结结果、连接切换与ACK重报;不执行业务写入。 package main import ( "context" "encoding/json" "errors" "fmt" "os" "time" orbit "git.yuntuo.hk/k2safe/orbit/sdk/go" ) func main() { if err := run(); err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } } func run() error { token, queue := os.Getenv("ORBIT_TOKEN"), os.Getenv("ORBIT_QUEUE_ID") if path := os.Getenv("ORBIT_CREDENTIALS_FILE"); path != "" { raw, err := os.ReadFile(path) if err != nil { return err } var credential struct { Token string `json:"token"` QueueID string `json:"queue_id"` } if json.Unmarshal(raw, &credential) != nil { return errors.New("invalid credential file") } if token == "" { token = credential.Token } if queue == "" { queue = credential.QueueID } } if token == "" || queue == "" { return errors.New("event-enabled token and isolated example queue are required") } api, err := orbit.NewClient(os.Getenv("ORBIT_URL"), orbit.Options{Token: token}) if err != nil { return err } ctx, stop := context.WithTimeout(context.Background(), 15*time.Second) defer stop() id, err := orbit.NewEventMessageID() if err != nil { return err } created, err := api.CreateSubscription(ctx, "sub-"+id, orbit.CreateSubscriptionRequest{Name: "protocol-" + id, QueueID: queue, Types: []string{"task.cancelled"}, MaxPending: 10, MaxAttempts: 3}) if err != nil { return err } sub := created.Subscription task, err := api.SubmitTask(ctx, "task-"+id, orbit.SubmitTaskRequest{QueueID: queue, Handler: "object.prepare", HandlerVersion: "v1", PayloadVersion: "v1", Payload: json.RawMessage(`{}`)}) if err != nil { return err } if _, err = api.CancelTask(ctx, task.Task.ID, "cancel-"+id, orbit.CancelTaskRequest{ExpectedRevision: task.Task.Revision, Reason: "event protocol example"}); err != nil { return err } first, err := api.DialEvents(ctx, orbit.EventRegistration{SubscriptionID: sub.ID, Capacity: 1}) if err != nil { return err } defer first.Close() grant, err := first.Next(ctx) if err != nil { return err } if grant.Event.Snapshot.TaskID != task.Task.ID || grant.Event.Snapshot.State != orbit.TaskCancelled { return errors.New("unexpected example queue event") } // 本例只读取并验证结果,没有业务数据库写入;业务处理必须先提交Inbox事务再ACK。 ackID, err := orbit.NewEventMessageID() if err != nil { return err } confirmed, err := first.Ack(ctx, ackID, grant.Proof()) if err != nil { return err } first.Close() second, err := api.DialEvents(ctx, orbit.EventRegistration{SubscriptionID: sub.ID, Capacity: 1}) if err != nil { return err } defer second.Close() replayID, err := orbit.NewEventMessageID() if err != nil { return err } replayed, err := second.Ack(ctx, replayID, grant.Proof()) if err != nil { return err } if !replayed.Deduplicated || !replayed.AcknowledgedAt.Equal(confirmed.AcknowledgedAt) { return errors.New("acknowledgement receipt changed across connections") } paused, err := api.ConfigureSubscription(ctx, sub.ID, "pause-"+id, orbit.ConfigureSubscriptionRequest{ExpectedRevision: sub.Revision, Enabled: false, Reason: "protocol example completed"}) if err != nil { return err } fmt.Printf("event=%s task=%s state=%s\n", grant.Event.ID, task.Task.ID, grant.Event.Snapshot.State) fmt.Printf("ack_replayed=%t same_receipt=true pending=%d subscription_enabled=%t\n", replayed.Deduplicated, paused.Subscription.PendingCount, paused.Subscription.Enabled) return nil }