Skip to content

Commit 6835161

Browse files
.NET: Fix flaky vector store integration tests - race condition on indexing (#2586)
* Initial plan * Add vector store indexing wait helpers to fix flaky tests Co-authored-by: rogerbarreto <19890735+rogerbarreto@users.noreply.github.com> * Use proper VectorStoreStatus struct comparison in Azure tests Co-authored-by: rogerbarreto <19890735+rogerbarreto@users.noreply.github.com> * Remove unused System.ClientModel import Co-authored-by: rogerbarreto <19890735+rogerbarreto@users.noreply.github.com> * Remove excessive comments and unnecessary status variable per code review Co-authored-by: rogerbarreto <19890735+rogerbarreto@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: rogerbarreto <19890735+rogerbarreto@users.noreply.github.com>
1 parent 3cfd348 commit 6835161

File tree

2 files changed

+85
-0
lines changed

2 files changed

+85
-0
lines changed

dotnet/tests/AzureAIAgentsPersistent.IntegrationTests/AzureAIAgentsPersistentCreateTests.cs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) Microsoft. All rights reserved.
22

33
using System;
4+
using System.Diagnostics;
45
using System.IO;
56
using System.Threading.Tasks;
67
using AgentConformance.IntegrationTests.Support;
@@ -108,6 +109,9 @@ You are a helpful agent that can help fetch data from files you know about.
108109
);
109110
var vectorStoreMetadata = await this._persistentAgentsClient.VectorStores.CreateVectorStoreAsync([uploadedAgentFile.Id], name: "WordCodeLookup_VectorStore");
110111

112+
// Wait for vector store indexing to complete before using it
113+
await this.WaitForVectorStoreReadyAsync(this._persistentAgentsClient, vectorStoreMetadata.Value.Id);
114+
111115
// Act.
112116
var agent = createMechanism switch
113117
{
@@ -292,4 +296,42 @@ public async Task CreateAgent_CreatesAgentWithAIFunctionToolsAsync(string create
292296
await this._persistentAgentsClient.Administration.DeleteAgentAsync(agent.Id);
293297
}
294298
}
299+
300+
/// <summary>
301+
/// Waits for a vector store to complete indexing by polling its status.
302+
/// </summary>
303+
/// <param name="client">The persistent agents client.</param>
304+
/// <param name="vectorStoreId">The ID of the vector store.</param>
305+
/// <param name="maxWaitSeconds">Maximum time to wait in seconds (default: 30).</param>
306+
/// <returns>A task that completes when the vector store is ready or throws on timeout/failure.</returns>
307+
private async Task WaitForVectorStoreReadyAsync(
308+
PersistentAgentsClient client,
309+
string vectorStoreId,
310+
int maxWaitSeconds = 30)
311+
{
312+
Stopwatch sw = Stopwatch.StartNew();
313+
while (sw.Elapsed.TotalSeconds < maxWaitSeconds)
314+
{
315+
PersistentAgentsVectorStore vectorStore = await client.VectorStores.GetVectorStoreAsync(vectorStoreId);
316+
317+
if (vectorStore.Status == VectorStoreStatus.Completed)
318+
{
319+
if (vectorStore.FileCounts.Failed > 0)
320+
{
321+
throw new InvalidOperationException("Vector store indexing failed for some files");
322+
}
323+
324+
return;
325+
}
326+
327+
if (vectorStore.Status == VectorStoreStatus.Expired)
328+
{
329+
throw new InvalidOperationException("Vector store has expired");
330+
}
331+
332+
await Task.Delay(1000);
333+
}
334+
335+
throw new TimeoutException($"Vector store did not complete indexing within {maxWaitSeconds}s");
336+
}
295337
}

dotnet/tests/OpenAIAssistant.IntegrationTests/OpenAIAssistantClientExtensionsTests.cs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) Microsoft. All rights reserved.
22

33
using System;
4+
using System.Diagnostics;
45
using System.IO;
56
using System.Threading.Tasks;
67
using AgentConformance.IntegrationTests.Support;
@@ -173,6 +174,9 @@ You are a helpful agent that can help fetch data from files you know about.
173174
});
174175
string vectorStoreId = vectorStoreCreate.Value.Id;
175176

177+
// Wait for vector store indexing to complete before using it
178+
await WaitForVectorStoreReadyAsync(vectorStoreClient, vectorStoreId);
179+
176180
var fileSearchTool = new HostedFileSearchTool() { Inputs = [new HostedVectorStoreContent(vectorStoreId)] };
177181

178182
var agent = createMechanism switch
@@ -219,4 +223,43 @@ You are a helpful agent that can help fetch data from files you know about.
219223
File.Delete(searchFilePath);
220224
}
221225
}
226+
227+
/// <summary>
228+
/// Waits for a vector store to complete indexing by polling its status.
229+
/// </summary>
230+
/// <param name="client">The vector store client.</param>
231+
/// <param name="vectorStoreId">The ID of the vector store.</param>
232+
/// <param name="maxWaitSeconds">Maximum time to wait in seconds (default: 30).</param>
233+
/// <returns>A task that completes when the vector store is ready or throws on timeout/failure.</returns>
234+
private static async Task WaitForVectorStoreReadyAsync(
235+
VectorStoreClient client,
236+
string vectorStoreId,
237+
int maxWaitSeconds = 30)
238+
{
239+
Stopwatch sw = Stopwatch.StartNew();
240+
while (sw.Elapsed.TotalSeconds < maxWaitSeconds)
241+
{
242+
VectorStore vectorStore = await client.GetVectorStoreAsync(vectorStoreId);
243+
VectorStoreStatus status = vectorStore.Status;
244+
245+
if (status == VectorStoreStatus.Completed)
246+
{
247+
if (vectorStore.FileCounts.Failed > 0)
248+
{
249+
throw new InvalidOperationException("Vector store indexing failed for some files");
250+
}
251+
252+
return;
253+
}
254+
255+
if (status == VectorStoreStatus.Expired)
256+
{
257+
throw new InvalidOperationException("Vector store has expired");
258+
}
259+
260+
await Task.Delay(1000);
261+
}
262+
263+
throw new TimeoutException($"Vector store did not complete indexing within {maxWaitSeconds}s");
264+
}
222265
}

0 commit comments

Comments
 (0)