Bug description

Streamed chunks might end up in a wrong order:

data: <A>
data: <B>

can end up as <B> => <A>

Environment * Spring AI 1.0.1 * Java 21

Steps to reproduce It's enough to inject the default AzureOpenAIChatModel, build a ChatClient and call

val chatClient = ChatClient.builder(chatModel).build()

chatClient
    .prompt(createPrompt(simpleResponseDeploymentName))
    .stream()
    .content()
    .collectList()
    .block()

On a local machine I need many sequential runs to trigger the issue, thus, a setup with WireMock is advisable.

Expected behavior The response chunks should be ordered correctly.

Minimal Complete Reproducible example Repo with test setup: https://github.com/robinmayerhofer/spring-ai-azure-openai-streaming-issue

Comment From: robinmayerhofer

I have a 99% suspicion that these two flatMap operations cause this: * https://github.com/spring-projects/spring-ai/blob/e5e2f45a83c3269126c0af4c7b3b3e32f729b4dd/models/spring-ai-azure-openai/src/main/java/org/springframework/ai/azure/openai/AzureOpenAiChatModel.java#L354 * https://github.com/spring-projects/spring-ai/blob/e5e2f45a83c3269126c0af4c7b3b3e32f729b4dd/models/spring-ai-azure-openai/src/main/java/org/springframework/ai/azure/openai/AzureOpenAiChatModel.java#L380

flatMap does not guarantee ordering and by evaluating the thread and I can see that this runs on boundedElastic by checking the thread name. Moreover, AzureOpenAiChatModel also explicitly uses Schedulers.boundedElastic() for tool calls: https://github.com/spring-projects/spring-ai/blob/e5e2f45a83c3269126c0af4c7b3b3e32f729b4dd/models/spring-ai-azure-openai/src/main/java/org/springframework/ai/azure/openai/AzureOpenAiChatModel.java#L406

Using flatMapSequential fixes this behavior, at least I cannot trigger it anymore with my setup.

Comment From: robinmayerhofer

The GitHub Action run on my reproduction repo shows that the issue can be triggered: https://github.com/robinmayerhofer/spring-ai-azure-openai-streaming-issue/actions/runs/16973297866/job/48115646716

```

Task :test

SpringAiAzureOpenaiStreamingIssueApplicationTests > tool call response scenario - order should not be messed up(RepetitionInfo) > repetition 21 of 20000 FAILED org.opentest4j.AssertionFailedError at SpringAiAzureOpenaiStreamingIssueApplicationTests.kt:106

SpringAiAzureOpenaiStreamingIssueApplicationTests > simple response - order should not be messed up(RepetitionInfo) > repetition 18863 of 20000 FAILED org.opentest4j.AssertionFailedError at SpringAiAzureOpenaiStreamingIssueApplicationTests.kt:84 ```

PR with the fix: #4156