Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Dec 24, 2025

CleanEntityStorageAsync ignored transient entities and entity queries reported IncludeState=false when state was missing, leaving empty/transient entities behind.

  • Entity cleaning: After server-side clean, traverse transient entities and purge those with no state/locks, ensuring empty entities are removed.
  • Metadata correctness: Preserve IncludesState=true even when state payload is empty/null; avoid null dereference and use consistent empty-state detection.
  • Coverage: Added gRPC client tests for transient purge and state-included metadata scenarios.
var result = await client.Entities.CleanEntityStorageAsync(
    new CleanEntityStorageRequest { RemoveEmptyEntities = true, ReleaseOrphanedLocks = true });
// Transient empty entities are now removed; state-included metadata reports IncludesState=true even when state is null.
Original prompt

This section details on the original issue you should resolve

<issue_title>CleanEntityStorageAsync() does not clean entities (likely 'transient' ones)</issue_title>
<issue_description>Hi! I am migrating some code from from in-process durable framework to isolated model, and I got stuck with handling entities.
I was looking for an option to completely delete entities. Reading docs, I learned that I can use DurableTaskClient.CleanEntityStorageAsync() to clean storage. I manually delete state for entities I wish to query and then I call this method, which does nothing, reporting that it purged exactly 0 entities.
Now my entities in question appear to be 'transient' so that I need to pass new EntityQuery { IncludeTransient = true } to GetAllEntitiesAsync() in order to see them in the output. It feels like by deleting state I promoted entities to transient and now entity storage is not cleaned because of that. The scenario for debugging is roughly the following:

// Here I get two transient entities with no state
var entities = await client.Entities
  .GetAllEntitiesAsync(
      new EntityQuery
      {
          IncludeState = true,
          IncludeTransient = true
      }
  )
  .ToListAsync();

// And here I get 0 removed entities and 0 orphaned locks released
var result = await client.Entities.CleanEntityStorageAsync(
    new CleanEntityStorageRequest
    {
        RemoveEmptyEntities = true,
        ReleaseOrphanedLocks = true
    }
  );

// Here again I get two entities
var entitiesAfter = await client.Entities
  .GetAllEntitiesAsync(
      new EntityQuery
      {
          IncludeState = true,
          IncludeTransient = true
      }
  )
  .ToListAsync();

Perhaps I do not understand something about this flow?

Also, when querying for entities, even though I specify IncludeState = true, resulting metadata do not include state and have IncludesState set to false. Is this how it is supposed to work?

I debug this code locally, backing durable framework by Azurite storage, so I can access and inspect my entities, and check if they are removed or not, or if they have associated state.</issue_description>

Comments on the Issue (you are @copilot in this section)


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI changed the title [WIP] Fix CleanEntityStorageAsync() not cleaning transient entities Clean transient entities and preserve state-included metadata Dec 24, 2025
Copilot AI requested a review from YunchuWang December 24, 2025 20:08
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.

CleanEntityStorageAsync() does not clean entities (likely 'transient' ones)

2 participants