Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 97 additions & 0 deletions content/en/blog/releases/Kitex/release-v0_15_1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
---
title: "Kitex Release v0.15.1"
linkTitle: "Release v0.15.1"
projects: ["Kitex"]
date: 2025-09-29
description: >
---

## **Introduction to Key Changes**

### **Announcements**
1. **Go Version Support Changes**: Kitex's minimum declared Go version has been adjusted to Go1.20 and supports up to Go1.25
- Currently does not affect Go v1.18/v1.19 compilation, but after being declared for higher versions, subsequent versions will introduce features of higher versions

### **New Features**
1. **Generic Call: New v2 API Supporting Multi-Services and Streaming Calls**

The Thrift binary generic call API now provides v2 version, supporting multi-services and streaming calls. For detailed usage, see [Generic Call User Guide](/docs/kitex/tutorials/advanced-feature/generic-call/basic_usage)

2. **Generic Call: Support for Unknown Service Handler**

Facilitates rapid development of streaming proxy, see [Proxy Application Development Guide](/docs/kitex/tutorials/advanced-feature/proxy_application_development) for details

3. **Generic Call: Support for Server-Level JSON/Map Streaming Generic Calls**

See: [Generic Call User Guide](/docs/kitex/tutorials/advanced-feature/generic-call/basic_usage) for details

4. **TTHeader Streaming: Support for ctx Cancel to Control Flow Lifecycle**

- Quickly terminate streaming calls, saving model resources
- Aligns with gRPC, for detailed usage see [Stream Lifecycle Control Best Practices](/docs/kitex/tutorials/basic-feature/streamx/StreamX_Lifecycle_Control)
- Supports Client actively invoking cancel to end streaming calls
- Supports Client sensing the ctx cancel signal of the current Handler and cascading to end streaming calls

5. **Streaming Error Handling Optimization**

- Quickly address specific error scenarios, accelerate troubleshooting of cascade cancel link issues, see [Stream Error Handling Best Practices](/docs/kitex/tutorials/basic-feature/streamx/StreamX_Error_Handling) for details
- In cascade cancel scenarios, error description includes complete cancel link, quickly locating the first-hop service that actively cancels
- Error description includes specific error scenarios and corresponding unique error codes
- Unified and convenient cancel error handling method, eliminating the need for cumbersome string matching

### **Feature/Experience Optimization**
1. **Generic Client: Optimize Background Goroutine Startup Logic**

Starting from Kitex v0.13.0, a generic client supports both Ping-Pong and streaming calls, and uses the TTHeader Streaming protocol by default. Each generic client automatically starts a background goroutine to clean up idle connections for TTHeader Streaming.

If users previously used the generic client incorrectly (e.g., creating a generic client for each request), upgrading to Kitex v0.13.x would result in a large number of background goroutines being created, leading to goroutine leaks, even though streaming generics are not actually used.

The v0.15.1 version only creates background goroutines when streaming generalization is actually used.

### **Code Generation Tool Kitex Tool**
1. **Strict Enum Value Checking**

For scenarios where Thrift IDL defines enum value overflow, strict generation checks have been added, see [Kitex Tool Enum Type Checking Instructions](/docs/kitex/tutorials/code-gen/idl_enumeration_type) for details

This change will cause some products to fail to generate because correctness already has issues, posing a significant risk to the service!

### **Special Change - Minor Services May Be Affected**
> Interface Breaking Change that has no impact on 99.9% of users

Kitex will ensure compatibility with normal usage patterns of internal users. However, individual users may have dependencies on definitions in the Kitex repository, and this version adjustment of Kitex will have an impact on these users.

This version has made minor adjustments to non-standard usage of `remote.Message`, `rpcinfo.RPCInfo` or `generic.Generic` interfaces. If there are special usages, they need to be adjusted to conform to the new version's interface definition.

## **Full Change**

### Feature
* feat(ttstream): support ctx cancel and detailed canceled error by @DMwangnima in [#1821](https://github.com/cloudwego/kitex/pull/1821) | [#1859](https://github.com/cloudwego/kitex/pull/1859) | [#1856](https://github.com/cloudwego/kitex/pull/1856)
* feat(generic): support new thrift binary generic call api, server streaming generic call and unknown service or method handler by @jayantxie in [#1837](https://github.com/cloudwego/kitex/pull/1837) | [#1857](https://github.com/cloudwego/kitex/pull/1857)
* feat(grpc): support dump MaxConcurrentStreams of HTTP2 Client by @DMwangnima in [#1820](https://github.com/cloudwego/kitex/pull/1820)

### Fix
* fix(retry): shallow copy response to avoid data race by @jayantxie in [#1799](https://github.com/cloudwego/kitex/pull/1799) | [#1814](https://github.com/cloudwego/kitex/pull/1814)
* fix(lbcache): check the existence before new Balancer to prevent leakage by @ppzqh in [#1825](https://github.com/cloudwego/kitex/pull/1825)
* fix(generic): descriptor.HTTPRequest.GetParam nil pointer exception by @jayantxie in [#1827](https://github.com/cloudwego/kitex/pull/1827)
* fix(generic): fix generic write int range check by @HeyJavaBean in [#1861](https://github.com/cloudwego/kitex/pull/1861)
* fix(rpcinfo): protect bizErr and extra field of ri.Invocation by lock by @jayantxie in [#1850](https://github.com/cloudwego/kitex/pull/1850)
* fix(timeout): remove timer pool to avoid timer race issue by @jayantxie in [#1858](https://github.com/cloudwego/kitex/pull/1858)
* fix(tool): disable fast api for protobuf by @DMwangnima in [#1807](https://github.com/cloudwego/kitex/pull/1807)
* fix(tool): skip pb code gen for arg -use by @xiaost in [#1819](https://github.com/cloudwego/kitex/pull/1819)

### Optimize
* optimize(grpc): access metadata.MD without ToLower by @xiaost in [#1806](https://github.com/cloudwego/kitex/pull/1806)
* optimize(ttstream): lazy init cleaning task for ObjectPool to reduce the impact of lots of goroutines caused by creating too many Generic Client by @DMwangnima in [#1842](https://github.com/cloudwego/kitex/pull/1842)
* optimize(tool): remove string deepcopy because the string type is read-only in Go by @jayantxie in [#1832](https://github.com/cloudwego/kitex/pull/1832)

### Refactor
* refactor(ttstream): remove ttstream provider by @jayantxie in [#1805](https://github.com/cloudwego/kitex/pull/1805)
* refactor(rpcinfo): move service/method info from message to rpcinfo, remove protocol info from message and update min go version to 1.20 by @jayantxie in [#1818](https://github.com/cloudwego/kitex/pull/1818) | [#1855](https://github.com/cloudwego/kitex/pull/1855)
* refactor(server): remove service middleware and SupportedTransportsFunc api by @jayantxie in [#1839](https://github.com/cloudwego/kitex/pull/1839)
* refactor(server): remove useless TargetSvcInfo field by @jayantxie in [#1840](https://github.com/cloudwego/kitex/pull/1840)

### Chore
* chore: update dependencies of kitex to support go 1.25 and new features by @jayantxie @AsterDY in [#1848](https://github.com/cloudwego/kitex/pull/1848) | [#1834](https://github.com/cloudwego/kitex/pull/1834) | [#1862](https://github.com/cloudwego/kitex/pull/1862) | [#1836](https://github.com/cloudwego/kitex/pull/1836)
* chore: update version v0.15.0 by @jayantxie in [#1864](https://github.com/cloudwego/kitex/pull/1864)
* docs: fix broken link to blogs by @scientiacoder in [#1813](https://github.com/cloudwego/kitex/pull/1813)
* chore: support custom ctx key to pass to downstream in Service-Inline by @Duslia in [#1709](https://github.com/cloudwego/kitex/pull/1709)
Original file line number Diff line number Diff line change
@@ -1,38 +1,73 @@
---
title: "StreamX Error Handling"
date: 2025-01-13
weight: 4
keywords: ["Stream Error Handling"]
description: ""
title: "Stream Error Handling Best Practices"
linkTitle: "Stream Error Handling Best Practices"
weight: 3
date: 2025-09-29
description: "Kitex StreamX stream error handling best practices, introducing TTHeader Streaming error codes and error handling mechanisms."
---

## Preface

Unlike RPC, stream errors can occur at any time during stream processing. For example, a server can return an error after sending multiple messages. However, once a stream has sent an error, it cannot send any more messages.
Unlike PingPong RPC, stream errors can occur at any time during stream processing. For example, a server can return an error after sending multiple messages. However, once a stream has sent an error, it cannot send any more messages.

## Error type
## Error Types

### Business exception
### Framework Exceptions

**Usage example** : For example, in the ChatGPT scenario, we need to constantly check whether the user account balance can continue to call the large model to generate returns.
#### Error Description Meaning

Server implementation:
```
[ttstream error, code=12007] [server-side stream] [canceled path: ServiceA] user code invoking stream RPC with context processed by context.WithCancel or context.WithTimeout, then invoking cancel() actively
```

| Error Description | Meaning | Notes |
|-------------------|---------|-------|
| [ttstream error, code=12007] | TTHeader Streaming error, error code 12007, corresponding to the scenario where upstream actively cancels | |
| [server-side stream] | Indicates that the error is thrown by the Stream on the server side | |
| [canceled path: ServiceA] | Indicates that ServiceA actively initiated cancel | |
| user code invoking stream RPC with context processed by context.WithCancel or context.WithTimeout, then invoking cancel() actively | Specific error description | |

#### Error Code Summary

TTHeader Streaming Error Summary

| Error Code | Error Description | Meaning | Notes |
|------------|-------------------|---------|-------|
| 12001 | application exception | Business exception, downstream handler returns err | |
| 12002 | unexpected header frame | Header Frame related errors | |
| 12003 | illegal biz err | Failed to parse business exception contained in Trailer Frame | |
| 12004 | illegal frame | Failed to parse basic information of Frame | |
| 12005 | illegal operation | Error due to improper Stream usage, such as Stream has been CloseSend but still Send | |
| 12006 | transport is closing | Connection exception, such as connection has been closed | |
| 12007 | user code invoking stream RPC with context processed by context.WithCancel or context.WithTimeout, then invoking cancel() actively | Upstream actively uses cancel() | |
| 12008 | user code canceled with cancelCause(error) | Upstream uses context.WithCancelCause and actively uses cancel(err) | |
| 12009 | canceled by downstream | Canceled by downstream service | |
| 12010 | canceled by upstream | Canceled by upstream service | |
| 12011 | Internal canceled | Cascade cancel scenario, such as gRPC handler ctx is canceled, cascade cancel TTHeader Streaming | |
| 12012 | canceled by business handler returning | Handler exits early, but there are still asynchronous goroutines using Recv/Send | |
| 12013 | canceled by connection closed | Stream lifecycle ends due to connection closure, common in server-side service migration/update | |

### Business Exceptions

Usage example: For example, in the ChatGPT scenario, we need to constantly check whether the user account balance can continue to call the large model to generate returns.

**Server Implementation:**

```go
func (si *streamingService) ServerStreamWithErr(ctx context.Context, req *echo.Request, stream echo.TestService_ServerStreamWithErrServer) error {
// 检查用户账户余额
// Check user account balance
for isHasBalance (req.UserId) {
stream.Send(ctx, res)
}
// 返回用户余额不足错误
// Return insufficient user balance error
bizErr := kerrors.NewBizStatusErrorWithExtra(
10001, "insufficient user balance", map[string]string{"testKey": "testVal"},
)
return bizErr
}
```

Client implementation:
**Client Implementation:**

```go
stream, err = cli.ServerStreamWithErr(ctx, req)
Expand All @@ -50,11 +85,11 @@ if ok {
}
```

### Other errors
### Other Errors

If the Error returned by the Server is a non-business exception, the framework will be uniformly encapsulated as `(*thrift.ApplicationException)`. At this time, only the error Message can be obtained.

Server implementation:
**Server Implementation:**

```go
func (si *streamingService) ServerStreamWithErr(ctx context.Context, req *echo.Request, stream echo.TestService_ServerStreamWithErrServer) error {
Expand All @@ -63,7 +98,7 @@ func (si *streamingService) ServerStreamWithErr(ctx context.Context, req *echo.R
}
```

Client implementation:
**Client Implementation:**

```go
stream, err = cli.ServerStreamWithErr(ctx, req)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
---
title: "Stream Lifecycle Control Best Practices"
linkTitle: "Stream Lifecycle Control Best Practices"
weight: 4
date: 2025-09-29
description: "Kitex StreamX stream lifecycle control best practices, introducing how to use ctx cancel to control streaming call lifecycle."
---

## Background

When directly interacting with the model layer through streaming, the caller needs to directly notify the model layer to stop responding in certain scenarios, thereby saving model resources.

In large model application scenarios such as classic Chat, the entire chain uses streaming interfaces that need to be connected in series, requiring perception of end-user disconnection signals and quickly ending the entire chain.

The above scenarios essentially require the upstream to be able to actively end streaming calls, often using ctx for control. When ctx is canceled, the Stream lifecycle will also end.

Kitex gRPC and TTHeader Streaming both support the mechanism of controlling Stream lifecycle based on ctx cancel, and TTHeader Streaming optimizes error descriptions on the basis of gRPC, which can better handle problem diagnosis in cascade cancel scenarios.

## TTHeader Streaming Supports Stream Lifecycle Control Based on ctx cancel

**Kitex >= v0.15.1 supports this feature**

### Upstream Actively Cancels Downstream

Here we use ServerStreaming as an example. When the upstream receives a special response, it actively calls cancel() to end the downstream Stream lifecycle.

#### Upstream - ServiceA

```go
// ctx generally comes from handler
ctx, cancel := context.WithCancel(ctx)
defer cancel()
cliSt, err := cli.InvokeStreaming(ctx, req)
if err != nil {
// Log or perform other operations
return
}

for {
resp, err := cliSt.Recv(cliSt.Context())
if err != nil {
if err == io.EOF {
// Normal end
return
}
// Log or perform other operations
// Abnormal end
return
}
// Determine if it is a business-specific response, for example, a special flag is defined in resp to indicate end
if isBizSpecialResp(resp) {
// Cancel downstream Stream
cancel()
return
}
}
```

#### Downstream - ServiceB

```go
import (
"github.com/cloudwego/kitex/pkg/kerrors"
)

func (impl *ServiceImpl) InvokeStreaming(ctx context.Context, stream Service_InvokeStreamingServer) (err error) {
// Downstream continuously sends data, only for demonstration
for {
if err = stream.Send(ctx, resp); err != nil {
if errors.Is(kerrors.ErrStreamingCanceled, err) {
// Upstream cancel
}
// Log or perform other operations
return
}
time.Sleep(100 * time.Millisecond)
}
}
```

At this time, the downstream error description is:

```
[ttstream error, code=12007] [server-side stream] [canceled path: ServiceA] user code invoking stream RPC with context processed by context.WithCancel or context.WithTimeout, then invoking cancel() actively
```

The meaning of each part of the error description is as follows:

| Error Description | Meaning | Notes |
|-------------------|---------|-------|
| [ttstream error, code=12007] | TTHeader Streaming error, error code 12007, corresponding to the scenario where upstream actively cancels | |
| [server-side stream] | Indicates that the error is thrown by the Stream on the server side | |
| [canceled path: ServiceA] | Indicates that ServiceA actively initiated cancel | |
| user code invoking stream RPC with context processed by context.WithCancel or context.WithTimeout, then invoking cancel() actively | Specific error description | |
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
---
title: "Kitex Tool Enum Type Checking Instructions"
linkTitle: "Enum Type Checking"
weight: 12
date: 2025-09-29
description: "Kitex Tool enum type checking instructions, introducing the checking mechanism for Thrift IDL enum value overflow issues."
---

## Background: Enum int32 Overflow Issue

In the Thrift protocol, enum types are actually passed as int32. If the Thrift IDL defines enum values that exceed the int32 range, they will overflow during transmission, and the peer cannot receive the correct value and cannot match the correct enum type.

**The correctness already has issues, posing a significant risk to the service!!!**

A common error writing is as follows: (treating enum values as similar to fixed-format error codes, actually overflowing as int32)

```thrift
enum MyEnum{
A = 3000000001000,
B = 3000000001001,
C = 3000000001002,
}
```

## Tool Changes: Strict Correctness Checking

Generally, Goland IDE will not prompt this Thrift syntax issue, but as long as it's written this way, using enums will definitely cause errors.

Therefore, to ensure correctness and avoid risk hazards, Kitex Tool after v0.15.1 (Thriftgo v0.4.3) will check this enum scenario, and when encountering out-of-bounds, it will directly fail to generate and prompt the location:

```
[WARN] enum overflow: the value (3000000001000) of enum 'xxx/base.thrift MyEnum' exceeds the range of int32.
Due to legacy implementation, thriftgo generates int64 for enums in Go code.
However, during network, values undergo int64->int32->int64 conversion. Values outside int32 will overflow.
Please adjust the enum value to fit within the int32 range [-2147483648, 2147483647].
If you just want to define a very big constant, please use 'const i64 MyConst = xxx' instead.
```

This error message indicates that in the `xxx/base.thrift` file, the enum `3000000001000` of `MyEnum` overflows.

## Solution: Correct Incorrect Enum Values

The tool's error message will contain information about the incorrect enum value:

```
enum overflow: the value (3000000001000) of enum 'xxx/base.thrift MyEnum'
```

You need to find the problematic enum value according to the prompt and correct it to within the int32 range (-2147483648, 2147483647).

If this IDL belongs to other public libraries, you can blame the file history and contact the corresponding classmate to modify it.

**This interception check does not support skipping for now**

## Indirect Impact of Dependency Introduction

Sorry, if your IDL introduces illegally defined Enums from others, it will affect your product generation. To eliminate this wrong usage, unified failure handling is applied. Please contact the corresponding IDL definition classmates to modify it.
Loading