@@ -35,15 +35,22 @@ namespace Microsoft.Extensions.AI.Agents.Runtime.Storage.CosmosDB;
3535/// </summary>
3636public class CosmosActorStateStorage : IActorStateStorage
3737{
38- private readonly Container _container ;
38+ private readonly LazyCosmosContainer _lazyContainer ;
3939 private const string InitialEtag = "0" ; // Initial ETag value when no state exists
4040
4141 /// <summary>
4242 /// Constructs a new instance of <see cref="CosmosActorStateStorage"/> with the specified Cosmos DB container.
4343 /// </summary>
4444 /// <param name="container">The Cosmos DB container to use for storage.</param>
4545 /// <exception cref="ArgumentNullException">Thrown when <paramref name="container"/> is null.</exception>
46- public CosmosActorStateStorage ( Container container ) => this . _container = container ?? throw new ArgumentNullException ( nameof ( container ) ) ;
46+ public CosmosActorStateStorage ( Container container ) => this . _lazyContainer = new LazyCosmosContainer ( container ) ;
47+
48+ /// <summary>
49+ /// Constructs a new instance of <see cref="CosmosActorStateStorage"/> with the specified lazy container.
50+ /// </summary>
51+ /// <param name="lazyContainer">The lazy Cosmos DB container to use for storage.</param>
52+ /// <exception cref="ArgumentNullException">Thrown when <paramref name="lazyContainer"/> is null.</exception>
53+ public CosmosActorStateStorage ( LazyCosmosContainer lazyContainer ) => this . _lazyContainer = lazyContainer ?? throw new ArgumentNullException ( nameof ( lazyContainer ) ) ;
4754
4855 /// <summary>
4956 /// Writes state changes to the actor's persistent storage.
@@ -54,6 +61,8 @@ public async ValueTask<WriteResponse> WriteStateAsync(
5461 string etag ,
5562 CancellationToken cancellationToken = default )
5663 {
64+ var container = await this . _lazyContainer . GetContainerAsync ( ) . ConfigureAwait ( false ) ;
65+
5766 if ( operations . Count == 0 )
5867 {
5968 // No operations to perform - return success with current ETag or generate new one
@@ -62,14 +71,14 @@ public async ValueTask<WriteResponse> WriteStateAsync(
6271 }
6372
6473 var partitionKey = new PartitionKey ( actorId . ToString ( ) ) ;
65- var batch = this . _container . CreateTransactionalBatch ( partitionKey ) ;
74+ var batch = container . CreateTransactionalBatch ( partitionKey ) ;
6675
6776 // First, try to read existing root document to get current version
6877 var rootDocId = GetRootDocumentId ( actorId ) ;
6978 ActorRootDocument ? existingRoot = null ;
7079 try
7180 {
72- var rootResponse = await this . _container . ReadItemAsync < ActorRootDocument > (
81+ var rootResponse = await container . ReadItemAsync < ActorRootDocument > (
7382 rootDocId ,
7483 partitionKey ,
7584 cancellationToken : cancellationToken ) . ConfigureAwait ( false ) ;
@@ -165,10 +174,11 @@ public async ValueTask<ReadResponse> ReadStateAsync(
165174 IReadOnlyCollection < ActorStateReadOperation > operations ,
166175 CancellationToken cancellationToken = default )
167176 {
177+ var container = await this . _lazyContainer . GetContainerAsync ( ) . ConfigureAwait ( false ) ;
168178 var results = new List < ActorReadResult > ( ) ;
169179
170180 // Read root document first to get actor-level ETag
171- string actorETag = await this . GetActorETagAsync ( actorId , cancellationToken ) . ConfigureAwait ( false ) ;
181+ string actorETag = await this . GetActorETagAsync ( container , actorId , cancellationToken ) . ConfigureAwait ( false ) ;
172182
173183 foreach ( var op in operations )
174184 {
@@ -178,7 +188,7 @@ public async ValueTask<ReadResponse> ReadStateAsync(
178188 var id = GetDocumentId ( actorId , get . Key ) ;
179189 try
180190 {
181- var response = await this . _container . ReadItemAsync < ActorStateDocument > (
191+ var response = await container . ReadItemAsync < ActorStateDocument > (
182192 id ,
183193 new PartitionKey ( actorId . ToString ( ) ) ,
184194 cancellationToken : cancellationToken )
@@ -215,7 +225,7 @@ public async ValueTask<ReadResponse> ReadStateAsync(
215225 MaxItemCount = 100 // TODO Fix
216226 } ;
217227
218- var iterator = this . _container . GetItemQueryIterator < KeyProjection > (
228+ var iterator = container . GetItemQueryIterator < KeyProjection > (
219229 query ,
220230 list . ContinuationToken ,
221231 requestOptions ) ;
@@ -299,12 +309,12 @@ private static string GetRootDocumentId(ActorId actorId)
299309 /// Gets the current ETag for the actor's root document.
300310 /// Returns a generated ETag if no root document exists.
301311 /// </summary>
302- private async ValueTask < string > GetActorETagAsync ( ActorId actorId , CancellationToken cancellationToken )
312+ private async ValueTask < string > GetActorETagAsync ( Container container , ActorId actorId , CancellationToken cancellationToken )
303313 {
304314 var rootDocId = GetRootDocumentId ( actorId ) ;
305315 try
306316 {
307- var rootResponse = await this . _container . ReadItemAsync < ActorRootDocument > (
317+ var rootResponse = await container . ReadItemAsync < ActorRootDocument > (
308318 rootDocId ,
309319 new PartitionKey ( actorId . ToString ( ) ) ,
310320 cancellationToken : cancellationToken ) . ConfigureAwait ( false ) ;
0 commit comments