Skip to content

Fix IOException in MSSQL pipeline by disposing config file watchers#3243

Open
aaronburtle wants to merge 13 commits intomainfrom
dev/aaronburtle/MSSQLIntegrationTestPipelineCleanupFix
Open

Fix IOException in MSSQL pipeline by disposing config file watchers#3243
aaronburtle wants to merge 13 commits intomainfrom
dev/aaronburtle/MSSQLIntegrationTestPipelineCleanupFix

Conversation

@aaronburtle
Copy link
Contributor

@aaronburtle aaronburtle commented Mar 12, 2026

Why make this change?

Closes #2992

Several configuration tests create a TestServer that sets up a ConfigFileWatcher to support hot-reload. When the file watcher detects a change, its callback reads the file, holding a read handle. Neither ConfigFileWatcher nor FileSystemRuntimeConfigLoader implemented IDisposable, so when the TestServer is disposed, the DI container could not clean up the file watcher. The watcher remained active, and if its callback was mid-read when CleanupAfterEachTest called File.Delete, the delete failed with an IOException

What is this change?

ConfigFileWatcher now implements IDisposable. It stops raising events, unsubscribes the Changed handler, and disposes the underlying IFileSystemWatcher.

FileSystemRuntimeConfigLoader now implements IDisposable. It disposes the owned ConfigFileWatcher. As a DI singleton, it is now automatically disposed when the TestServer shuts down.

CleanupAfterEachTest retries with exponential backoff. As a safety net, File.Delete is retried up to 3 times on IOException (2s, 4s, 8s delays), matching the existing retry pattern used elsewhere.

How was this tested?

Run against the pipeline. Several pipeline runs were initiated to add certainty that the fix is working, since this issue is intermittent.

https://dev.azure.com/sqldab/Data%20API%20builder%20Dependency%20Packages/_build/results?buildId=18957&view=results

https://dev.azure.com/sqldab/Data%20API%20builder%20Dependency%20Packages/_build/results?buildId=18958&view=results

https://dev.azure.com/sqldab/Data%20API%20builder%20Dependency%20Packages/_build/results?buildId=18952&view=results

https://dev.azure.com/sqldab/Data%20API%20builder%20Dependency%20Packages/_build/results?buildId=18959&view=results

https://dev.azure.com/sqldab/Data%20API%20builder%20Dependency%20Packages/_build/results?buildId=18960&view=results

@aaronburtle
Copy link
Contributor Author

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 6 pipeline(s).

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses intermittent MSSQL pipeline test failures caused by lingering config file watchers holding file handles during test cleanup, leading to IOException on File.Delete. It introduces explicit disposal of config file watcher resources and adds a retry-based safety net in test cleanup.

Changes:

  • Implement IDisposable on ConfigFileWatcher to stop events, unsubscribe handlers, and dispose the underlying watcher.
  • Implement IDisposable on FileSystemRuntimeConfigLoader so DI can dispose the owned ConfigFileWatcher when the test server shuts down.
  • Add exponential backoff retries around test config file deletion in CleanupAfterEachTest.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
src/Service.Tests/Configuration/ConfigurationTests.cs Adds retry/backoff around deleting the custom config file during test cleanup to reduce flakiness from transient file locks.
src/Config/FileSystemRuntimeConfigLoader.cs Makes the loader disposable so the DI container can clean up the hot-reload watcher on shutdown.
src/Config/ConfigFileWatcher.cs Makes the watcher disposable to stop notifications and release OS resources/file handles.

aaronburtle and others added 3 commits March 12, 2026 19:32
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@aaronburtle
Copy link
Contributor Author

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 6 pipeline(s).

Copy link
Contributor

@souvikghosh04 souvikghosh04 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved with a follow-up comment

@souvikghosh04
Copy link
Contributor

/azp run

@souvikghosh04 souvikghosh04 enabled auto-merge (squash) March 13, 2026 04:59
@azure-pipelines
Copy link

Azure Pipelines successfully started running 6 pipeline(s).

@aaronburtle
Copy link
Contributor Author

/azp run

… of github.com:Azure/data-api-builder into dev/aaronburtle/MSSQLIntegrationTestPipelineCleanupFix
@azure-pipelines
Copy link

Azure Pipelines successfully started running 6 pipeline(s).

@aaronburtle
Copy link
Contributor Author

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 6 pipeline(s).

@aaronburtle
Copy link
Contributor Author

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 6 pipeline(s).

@aaronburtle
Copy link
Contributor Author

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 6 pipeline(s).

… of github.com:Azure/data-api-builder into dev/aaronburtle/MSSQLIntegrationTestPipelineCleanupFix
@aaronburtle
Copy link
Contributor Author

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 6 pipeline(s).

// arriving before that completes will fail with "Initialization of metadata incomplete."
JsonElement reloadGQLContents = default;
bool querySucceeded = false;
for (int attempt = 1; attempt <= 10; attempt++)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please mention this retry attempt added for GraphQL too over here in the description.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Fix failing MS SQL Integration tests in the pipeline

4 participants