|
| 1 | +--- |
| 2 | +title: "Stream Metainfo" |
| 3 | +date: 2025-01-13 |
| 4 | +weight: 1 |
| 5 | +keywords: ["Stream Metainfo"] |
| 6 | +description: "" |
| 7 | +--- |
| 8 | + |
| 9 | +## Preface |
| 10 | + |
| 11 | +The overall usage of message pass-through is similar to [Kitex - 元信息透传](https://bytedance.larkoffice.com/wiki/Y3ChwldJzihF4Vkb6Ekcie38no4), except that each stream can only **pass-through meta-information when created** , and sending messages cannot pass-through. |
| 12 | + |
| 13 | +## User guide |
| 14 | + |
| 15 | +### Client pass-through meta-message |
| 16 | + |
| 17 | +```go |
| 18 | +ctx = metainfo.WithPersistentValue(ctx, "k1", "v1") |
| 19 | +ctx = metainfo.WithValue(ctx, "k2", "v2") |
| 20 | + |
| 21 | +s, err := streamClient.ClientStream(ctx) |
| 22 | +``` |
| 23 | + |
| 24 | +### Server receives meta message |
| 25 | + |
| 26 | +```go |
| 27 | +func (s *streamingService) ClientStream(ctx context.Context, |
| 28 | + stream streamx.ClientStreamingServer[Request, Response]) (*Response, error) { |
| 29 | + |
| 30 | + v, ok := metainfo.GetPersistentValue(ctx, "k1") |
| 31 | + // v == "v1" |
| 32 | + v, ok = metainfo.GetValue(ctx, "k2") |
| 33 | + // v == "v2" |
| 34 | +} |
| 35 | +``` |
| 36 | + |
| 37 | +### Server reverse pass-through meta-message |
| 38 | + |
| 39 | +Reverse pass-through introduces a new concept, Header and Trailer. Any complete data stream must include Header and Trailer. Use these two frames to reverse pass-through information. |
| 40 | + |
| 41 | +```go |
| 42 | +func (s *streamingService) ClientStream(ctx context.Context, |
| 43 | + stream streamx.ClientStreamingServer[Request, Response]) (*Response, error) { |
| 44 | + |
| 45 | + // SetTrailer set 的 trailer 会在 server handler 结束后发送 |
| 46 | + err := stream.SetTrailer(streamx.Trailer{"t1": "v1"}) |
| 47 | + // 立刻发送 Header |
| 48 | + err = stream.SendHeader(streamx.Header{"h1": "v1"}) |
| 49 | + if err != nil { |
| 50 | + return err |
| 51 | + } |
| 52 | + // 发送正常数据 |
| 53 | + err = stream.Send(req) |
| 54 | +} |
| 55 | +``` |
| 56 | + |
| 57 | +### Client receives a reverse pass-through meta message |
| 58 | + |
| 59 | +```go |
| 60 | +s, err := streamClient.ClientStream(ctx) |
| 61 | + |
| 62 | +// Header/Trailer 函数会一直阻塞到对端发送了 Header/Trailer 为止,或中间发生了错误 |
| 63 | +hd, err := s.Header() |
| 64 | +// hd["h1"] == "v1" |
| 65 | +tl, err := s.Trailer() |
| 66 | +// tl["t1"] == "v1" |
| 67 | +``` |
| 68 | + |
| 69 | +## FAQ |
| 70 | + |
| 71 | +### Why is the reverse pass-through interface inconsistent with 's reverse pass-through? |
| 72 | + |
| 73 | +Because the concept of flow is different from , under the flow, the Header can be sent independently, which means that my server can send the Header in the first second, send the Data after 10 seconds, and send the Trailer after 1 second. |
| 74 | + |
| 75 | +At the same time, the client can also choose whether to call `.Header () ` or `.Trailer () ` to block. |
| 76 | + |
| 77 | +Therefore, the semantics of traditional CTX cannot meet the reverse pass-through function of streams. Forward pass-through is still consistent with the original . |
0 commit comments