wy471x opened a new pull request, #7173:
URL: https://github.com/apache/shenyu/pull/7173

   <!-- Fixes #6670 -->
   Make sure that:
   
   - [X] You have read the [contribution 
guidelines](https://shenyu.apache.org/community/contributor-guide).
   - [X] You submit test cases (unit or integration tests) that back your 
changes.
   - [X] Your local test passed `./mvnw clean install 
-Dmaven.javadoc.skip=true`.
   
   ## Summary
   
   `AiResponseTransformerPlugin` built a brand new `ObjectMapper` on every 
decorated AI response — one inside `AiResponseParser#extractBodyFromAiResponse` 
and one inside `AiResponseTransformerDecorator#writeWith`'s `flatMap`. A fresh 
`ObjectMapper` builds its own `TypeFactory`/`SerializerProvider`/cache per 
instance, so this adds needless CPU and young-gen pressure on a hot path (the 
decorator runs for every AI-transformed response). The sibling 
`AiTokenLimiterPlugin` already hoists a static `MAPPER`, so this aligns the two.
   
   ### Changes:
   
   1. `AiResponseTransformerPlugin` 
(`shenyu-plugin-ai/shenyu-plugin-ai-response-transformer/.../AiResponseTransformerPlugin.java:75`)
 — added a single `private static final ObjectMapper MAPPER = new 
ObjectMapper();` to the plugin class, following the 
`AiTokenLimiterPlugin.AiStatisticServerHttpResponse` pattern.
   2. `AiResponseParser#extractBodyFromAiResponse` (`:225`) — `new 
ObjectMapper().readTree(body)` replaced with `MAPPER.readTree(body)` 
(validation-only call, behaviour unchanged).
   3. `AiResponseTransformerDecorator#writeWith` (`:338`, `:345`) — the 
per-response local `ObjectMapper objectMapper = new ObjectMapper();` removed; 
`readTree(message)` / `writeValueAsString(messageNode)` now use the shared 
`MAPPER`. Both nested classes are static, so the single outer-class constant is 
shared. `ObjectMapper` is thread-safe for read/write operations, so a shared 
instance is safe here.
   
   ### Test Cases:
   
   1. 
`AiResponseTransformerPluginTest#testExtractBodyFromAiResponseReusesObjectMapper`
 (new, `.../response/AiResponseTransformerPluginTest.java`) — uses 
`mockConstruction(ObjectMapper.class)` around an `extractBodyFromAiResponse` 
call after forcing class initialization, asserting `0` `ObjectMapper` instances 
are constructed and that the JSON body is still returned correctly. Verified 
the test fails against the un-fixed code (`expected: <0> but was: <1>`), so it 
locks the fix in.
   2. All 21 pre-existing `AiResponseTransformerPluginTest` cases still pass, 
covering the decorator JSON-merge path 
(`testOriginalHeadersRemainWhenTransformedBodyIsInvalid`) and the body/header 
extraction paths that now use the shared mapper.
   
   ## Verification
   
   - `mvn -pl 
shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-response-transformer -am test 
-Dtest=AiResponseTransformerPluginTest` (JDK 21): `Tests run: 22, Failures: 0, 
Errors: 0, Skipped: 0`.
   - `mvn clean install -Dmaven.javadoc.skip=true` (JDK 21): BUILD SUCCESS over 
the whole reactor (checkstyle + RAT included). Note: the first run hit 
`HttpShenyuSdkClientTest#testShenyuHttpClient` timing out after 2s against 
`https://shenyu.apache.org` — an unrelated, network-dependent test in 
`shenyu-sdk-httpclient`; re-running from that module (`-rf 
:shenyu-sdk-httpclient`) passed and the remaining 15 modules built green.
   
   Fixes #6670
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to