Skip to content

fix(adonet): add missing CleanupDefunctSiloEntriesKey to Oracle clustering - #11246

Merged
ReubenBond merged 1 commit into
dotnet:mainfrom
ranma42:fix/oracle-cleanup-defunct-silo-entries
Sep 15, 2026
Merged

ReubenBond merged 1 commit into
dotnet:mainfrom
ranma42:fix/oracle-cleanup-defunct-silo-entries

Conversation

@ranma42

@ranma42 ranma42 commented Sep 11, 2026 •

Copy link
Copy Markdown
Contributor

Solves #8676 for Oracle scripts by adding the missing query CleanupDefunctSiloEntriesKey.
Follows the same pattern as #8896 (MySQL) and #9125 (PostgreSQL). Oracle is the last ADO.NET backend still missing it.

Without the query, a silo configured for ADO.NET clustering on Oracle fails fast at startup, in the DbStoredQueries constructor:

System.ArgumentException: Not all required queries found. Missing are: CleanupDefunctSiloEntriesKey

The 3.7.0 migration does not supply it either

This gap survived the earlier per-backend fixes because the Oracle 3.7.0 migration is itself broken.

All four 3.7.0 migrations were added together in 4702095 (#7928), when CleanupDefunctSiloEntries was introduced; that commit touched no main clustering script. The MySQL, SQL Server and PostgreSQL migrations each insert CleanupDefunctSiloEntriesKey. The Oracle one instead names DeleteMembershipTableEntriesKey, while carrying the cleanup-defunct body:

INSERT INTO OrleansQuery(QueryKey, QueryText)
VALUES
(
  'DeleteMembershipTableEntriesKey','   -- wrong key
  BEGIN
    DELETE FROM OrleansMembershipTable
    WHERE DeploymentId = :DeploymentId
        AND :DeploymentId IS NOT NULL
        AND IAmAliveTime < :IAmAliveTime   -- cleanup-defunct body
        AND Status != 3;
  END;
');

The key name and the body disagree, with two consequences:

  • QUERYKEY is the primary key of ORLEANSQUERY, and Oracle-Clustering.sql already inserts DeleteMembershipTableEntriesKey. So the migration fails with ORA-00001 on any database created from the setup script, and never creates the new key.
  • Had it applied, it would have replaced the working DeleteMembershipTableEntries query with one binding an :IAmAliveTime parameter that RelationalOrleansQueries.DeleteMembershipTableEntriesAsync never supplies.

Changes

  • Oracle-Clustering.sql — add CleanupDefunctSiloEntriesKey, placed next to DeleteMembershipTableEntriesKey as in MySQL-Clustering.sql. This is a pure addition; the existing DeleteMembershipTableEntriesKey definition is untouched.
  • Migrations/Oracle-Clustering-3.7.0.sql — insert the correct key, guarded by WHERE NOT EXISTS so it is idempotent and safe on databases that already have the row, matching the guards used by the MySQL, SQL Server and PostgreSQL 3.7.0 migrations.

The setup script and the migration now define the same query text, so a fresh install and a migrated deployment end up with the same ORLEANSQUERY contents.

Testing

Verified against Oracle Database 23ai Free (gvenzl/oracle-free:slim-faststart) in Docker, using four isolated schemas. The repository has no Oracle test fixture — test/Extensions/Orleans.AdoNet.Tests/RelationalUtilities/ provides only SQL Server, MySQL and PostgreSQL — so this was done by hand. (The Do_Liveness_OracleTest_* helpers in LivenessTests.cs are misnamed shared helpers used by the other backends, not Oracle coverage.)

Scenario Scripts applied Result
Fresh install Oracle-Main + new Oracle-Clustering applies cleanly
Pre-3.7.0 deployment upgrading Oracle-Main + old Oracle-Clustering + new migration applies cleanly, key created
Migration re-run / already present Oracle-Main + new Oracle-Clustering + new migration no error, no duplicate row
Old migration, for comparison Oracle-Main + Oracle-Clustering + old migration ORA-00001: unique constraint (ORLEANSQUERY_PK) violated ... row with column values (QUERYKEY:'DeleteMembershipTableEntriesKey') already exists

The last row reproduces the failure described above, confirming the old migration could never have been applied.

Further checks on the resulting databases:

  • The fresh-install schema and the migrated schema have byte-identical ORLEANSQUERY contents (symmetric MINUS over (QueryKey, QueryText) returns no rows), which is the property this PR is really about.
  • The nine keys present match exactly the clustering keys DbStoredQueries requires — nothing missing, nothing extra.
  • The stored CleanupDefunctSiloEntriesKey text was fetched from ORLEANSQUERY and executed as-is with the binds Orleans supplies (:DeploymentId, :IAmAliveTime) against seeded membership rows. It deleted only the defunct silo, correctly preserving the Status = 3 (Dead) entry, a recently-alive entry, and another deployment's entry.

Unrelated observation

Running these scripts through plain SQL*Plus needs SET SQLBLANKLINES ON (the CREATE TABLE statements contain blank lines) and care around statement terminators: statements end with both ; and a bare /, which makes SQL*Plus execute each one twice. That is pre-existing and affects all the Oracle scripts, so I have left it alone here.

AI disclosure

This change was produced with Claude Code (Claude Opus 5). The audit that surfaced it — diffing each ADO.NET setup script against its migrations to check that the setup script alone reproduces a fully migrated database — was AI-assisted, as were the SQL edits, the testing described above and this description. I have reviewed the result.

🤖 Generated with Claude Code

Microsoft Reviewers: Open in CodeFlow

@ranma42
ranma42 requested a review from ReubenBond as a code owner September 11, 2026 12:10
…ering

Oracle-Clustering.sql never defined CleanupDefunctSiloEntriesKey. Since
DbStoredQueries validates that every required key is present in its
constructor, a silo using ADO.NET clustering on Oracle fails fast at
startup with:

  System.ArgumentException: Not all required queries found.
  Missing are: CleanupDefunctSiloEntriesKey

This is the same gap fixed for SQL Server in dotnet#8811, MySQL
in dotnet#8896 and PostgreSQL in dotnet#9125; Oracle was
the last backend still missing the query.

The 3.7.0 migration that was meant to supply it does not work either.
All four 3.7.0 migrations were added together in 4702095 (dotnet#7928) when
CleanupDefunctSiloEntries was introduced; that commit touched no main
clustering script, and the MySQL, SQL Server and PostgreSQL migrations
all insert 'CleanupDefunctSiloEntriesKey'. The Oracle one instead names
'DeleteMembershipTableEntriesKey' while carrying the cleanup-defunct
body, so the key and the body disagree.

Because QUERYKEY is the primary key of ORLEANSQUERY and the setup script
already inserts DeleteMembershipTableEntriesKey, that migration fails
with ORA-00001 on any real database and never creates the new key. Had
it applied, it would have replaced the real DeleteMembershipTableEntries
query with one binding an :IAmAliveTime parameter the caller does not
supply.

Add the query to the setup script, next to DeleteMembershipTableEntriesKey
as in MySQL-Clustering.sql, and correct the migration to insert the right
key, guarded by a NOT EXISTS check so it is idempotent and safe on
databases that already have the row - matching the guards used by the
MySQL, SQL Server and PostgreSQL 3.7.0 migrations. Oracle's existing
DeleteMembershipTableEntriesKey definition in the setup script is
unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@ReubenBond
ReubenBond force-pushed the fix/oracle-cleanup-defunct-silo-entries branch from 7478543 to 4fd1b9d Compare September 13, 2026 14:58
@ReubenBond
ReubenBond requested a balanced review from Copilot September 14, 2026 14:12

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Approval recommended

The Oracle scripts consistently define the required query for fresh and migrated databases without unresolved issues.

Pull request overview

Adds Oracle support for the required cleanup query, preventing ADO.NET clustering startup failures.

Changes:

  • Adds CleanupDefunctSiloEntriesKey to fresh Oracle installations.
  • Corrects and makes the Oracle 3.7.0 migration idempotent.
File summaries
File Description
Oracle-Clustering.sql Defines the missing cleanup query.
Migrations/Oracle-Clustering-3.7.0.sql Corrects the query key and safely avoids duplicates.
Review details
  • Files reviewed: 2/2 changed files
  • Comments generated: 0
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@ReubenBond ReubenBond changed the title Add missing query CleanupDefunctSiloEntriesKey to Oracle-Clustering fix(adonet): add missing CleanupDefunctSiloEntriesKey to Oracle clustering Sep 15, 2026
@ReubenBond
ReubenBond merged commit 8905026 into dotnet:main Sep 15, 2026
67 checks passed
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.

3 participants