Skip to content

Commit ca88b41

Browse files
Refactor fields, constructors, and namespaces
Renamed private fields in CosmosDatabaseOptions and CosmosOptions for consistency. Updated method signatures to handle non-nullable parameters. Added new constructors in CosmosSharedTableOptions and CosmosSingleTableOptions for better initialization flexibility. Removed redundant code and updated namespaces for better organization. Removed the obsolete CosmosDbTestOptions file.
1 parent e69e7e6 commit ca88b41

File tree

10 files changed

+89
-93
lines changed

10 files changed

+89
-93
lines changed

src/CommunityToolkit.Datasync.Server.CosmosDb/CommunityToolkit.Datasync.Server.CosmosDb.csproj

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,4 @@
1616
<PackageReference Include="Newtonsoft.Json" />
1717
</ItemGroup>
1818

19-
<ItemGroup>
20-
<Folder Include="Controllers\" />
21-
</ItemGroup>
22-
2319
</Project>

src/CommunityToolkit.Datasync.Server.CosmosDb/Configuration/CosmosDatabaseOptions.cs

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ namespace CommunityToolkit.Datasync.Server.CosmosDb.Configuration;
1010

1111
public class CosmosDatabaseOptions : ICosmosDatabaseBuilder
1212
{
13-
private readonly Dictionary<string, CosmosContainerOptions> _containers = [];
14-
private readonly List<ServiceDescriptor> _services;
13+
private readonly Dictionary<string, CosmosContainerOptions> containers = new Dictionary<string, CosmosContainerOptions>();
14+
private readonly List<ServiceDescriptor> services;
1515

16-
internal IReadOnlyCollection<CosmosContainerOptions> Containers => this._containers.Values;
16+
internal IReadOnlyCollection<CosmosContainerOptions> Containers => this.containers.Values;
1717

1818
internal CosmosDatabaseOptions(string databaseId, List<ServiceDescriptor> services)
1919
{
@@ -23,23 +23,23 @@ internal CosmosDatabaseOptions(string databaseId, List<ServiceDescriptor> servic
2323
}
2424

2525
DatabaseId = databaseId;
26-
this._services = services ?? throw new ArgumentNullException(nameof(services));
26+
this.services = services ?? throw new ArgumentNullException(nameof(services));
2727
}
2828

2929
public string DatabaseId { get; }
3030

3131
public ThroughputProperties? ThroughputProperties { get; private set; }
3232

33-
ICosmosSharedContainerBuilder ICosmosDatabaseBuilder.Container(ContainerProperties containerProperties, bool shouldUpdateTimestamp) => Container(containerProperties);
33+
ICosmosSharedContainerBuilder ICosmosDatabaseBuilder.Container(ContainerProperties containerProperties, bool shouldUpdateTimestamp) => Container(containerProperties, shouldUpdateTimestamp);
3434

3535
internal CosmosContainerOptions Container(ContainerProperties containerProperties, bool shouldUpdateTimestamp = true)
3636
{
37-
if (this._containers.ContainsKey(containerProperties.Id))
37+
if (this.containers.ContainsKey(containerProperties.Id))
3838
{
3939
throw new InvalidOperationException($"Container {containerProperties.Id} has already been added");
4040
}
41-
CosmosContainerOptions containerBuilder = new CosmosContainerOptions(DatabaseId, containerProperties, _services, shouldUpdateTimestamp);
42-
this._containers.Add(containerProperties.Id, containerBuilder);
41+
CosmosContainerOptions containerBuilder = new CosmosContainerOptions(DatabaseId, containerProperties, services, shouldUpdateTimestamp);
42+
this.containers.Add(containerProperties.Id, containerBuilder);
4343
return containerBuilder;
4444
}
4545

@@ -59,10 +59,10 @@ ICosmosContainerBuilder ICosmosDatabaseBuilder.Container<TEntity>(ContainerPrope
5959
{
6060
CosmosContainerOptions options = Container(containerProperties, shouldUpdateTimestamp);
6161

62-
this._services.ThrowIfExists<TEntity>();
62+
this.services.ThrowIfExists<TEntity>();
6363

64-
this._services.Add(ServiceDescriptor.Singleton<ICosmosTableOptions<TEntity>>(new CosmosSingleTableOptions<TEntity>(options)));
65-
this._services.Add(ServiceDescriptor.Singleton<IRepository<TEntity>, CosmosTableRepository<TEntity>>());
64+
this.services.Add(ServiceDescriptor.Singleton<ICosmosTableOptions<TEntity>>(new CosmosSingleTableOptions<TEntity>(options)));
65+
this.services.Add(ServiceDescriptor.Singleton<IRepository<TEntity>, CosmosTableRepository<TEntity>>());
6666

6767
return options;
6868
}
@@ -71,10 +71,10 @@ ICosmosContainerBuilder ICosmosDatabaseBuilder.Container<TEntity, TEntityOptions
7171
{
7272
CosmosContainerOptions containerOptions = Container(containerProperties, shouldUpdateTimestamp);
7373

74-
this._services.ThrowIfExists<TEntity>();
74+
this.services.ThrowIfExists<TEntity>();
7575

76-
this._services.Add(ServiceDescriptor.Singleton<ICosmosTableOptions<TEntity>, TEntityOptions>());
77-
this._services.Add(ServiceDescriptor.Singleton<IRepository<TEntity>, CosmosTableRepository<TEntity>>());
76+
this.services.Add(ServiceDescriptor.Singleton<ICosmosTableOptions<TEntity>, TEntityOptions>());
77+
this.services.Add(ServiceDescriptor.Singleton<IRepository<TEntity>, CosmosTableRepository<TEntity>>());
7878

7979
return containerOptions;
8080
}
@@ -83,22 +83,22 @@ ICosmosContainerBuilder ICosmosDatabaseBuilder.Container<TEntity, TEntityOptions
8383
{
8484
CosmosContainerOptions containerOptions = Container(containerProperties, shouldUpdateTimestamp);
8585

86-
this._services.ThrowIfExists<TEntity>();
86+
this.services.ThrowIfExists<TEntity>();
8787

88-
this._services.Add(ServiceDescriptor.Singleton<ICosmosTableOptions<TEntity>>(implementationFactory.Invoke(containerOptions)));
89-
this._services.Add(ServiceDescriptor.Singleton<IRepository<TEntity>, CosmosTableRepository<TEntity>>());
88+
this.services.Add(ServiceDescriptor.Singleton<ICosmosTableOptions<TEntity>>(implementationFactory.Invoke(containerOptions)));
89+
this.services.Add(ServiceDescriptor.Singleton<IRepository<TEntity>, CosmosTableRepository<TEntity>>());
9090
return containerOptions;
9191
}
9292

9393
ICosmosContainerBuilder ICosmosDatabaseBuilder.Container<TEntity, TEntityOptions>(ContainerProperties containerProperties, Func<CosmosContainerOptions, IServiceProvider, TEntityOptions> implementationFactory, bool shouldUpdateTimestamp)
9494
{
9595
CosmosContainerOptions containerOptions = Container(containerProperties, shouldUpdateTimestamp);
9696

97-
this._services.ThrowIfExists<TEntity>();
97+
this.services.ThrowIfExists<TEntity>();
9898

9999
Func<IServiceProvider, TEntityOptions> factory = sp => implementationFactory.Invoke(containerOptions, sp);
100-
this._services.Add(ServiceDescriptor.Singleton<ICosmosTableOptions<TEntity>>(factory));
101-
this._services.Add(ServiceDescriptor.Singleton<IRepository<TEntity>, CosmosTableRepository<TEntity>>());
100+
this.services.Add(ServiceDescriptor.Singleton<ICosmosTableOptions<TEntity>>(factory));
101+
this.services.Add(ServiceDescriptor.Singleton<IRepository<TEntity>, CosmosTableRepository<TEntity>>());
102102
return containerOptions;
103103
}
104104
}

src/CommunityToolkit.Datasync.Server.CosmosDb/Configuration/CosmosOptions.cs

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,26 +11,32 @@
1111
namespace CommunityToolkit.Datasync.Server.CosmosDb.Configuration;
1212

1313
/// <summary>
14-
///
14+
/// Options to be passed to the CosmosDB service for cosmos initialization.
1515
/// </summary>
1616
public sealed class CosmosOptions : ICosmosOptionsBuilder, ICosmosOptionsBuilderWithClient
1717
{
18+
/// <summary>
19+
/// The default indexing index for Datasync.
20+
/// </summary>
1821
public static readonly Collection<CompositePath> DatasyncCompositeIndex = [
1922
new() { Path = "/updatedAt", Order = CompositePathSortOrder.Ascending },
2023
new() { Path = "/id", Order = CompositePathSortOrder.Ascending }
2124
];
2225

26+
/// <summary>
27+
/// The default indexing policy for Datasync.
28+
/// </summary>
2329
public static readonly IndexingPolicy DefaultDatasyncIndexingPolicy = new()
2430
{
2531
CompositeIndexes = { DatasyncCompositeIndex }
2632
};
2733

28-
private readonly Dictionary<string, CosmosDatabaseOptions> _databases = [];
29-
private readonly List<ServiceDescriptor> _services = [];
34+
private readonly Dictionary<string, CosmosDatabaseOptions> databases = new Dictionary<string, CosmosDatabaseOptions>();
35+
private readonly List<ServiceDescriptor> services = new List<ServiceDescriptor>();
3036

3137
internal CosmosClient? CosmosClient { get; private set; }
32-
internal IReadOnlyCollection<CosmosDatabaseOptions> Databases => this._databases.Values;
33-
internal IReadOnlyCollection<ServiceDescriptor> Services => this._services;
38+
internal IReadOnlyCollection<CosmosDatabaseOptions> Databases => this.databases.Values;
39+
internal IReadOnlyCollection<ServiceDescriptor> Services => this.services;
3440
internal CosmosOptions() { }
3541

3642
ICosmosOptionsBuilderWithClient ICosmosOptionsBuilder.UseConnectionString(string connectionString, CosmosClientOptions? clientOptions)
@@ -66,14 +72,14 @@ internal CosmosDatabaseOptions Database(string databaseName)
6672
throw new ArgumentException($"'{nameof(databaseName)}' cannot be null or empty.", nameof(databaseName));
6773
}
6874

69-
if (this._databases.ContainsKey(databaseName))
75+
if (this.databases.ContainsKey(databaseName))
7076
{
7177
throw new InvalidOperationException($"Database {databaseName} has already been added");
7278
}
7379

74-
CosmosDatabaseOptions databaseBuilder = new(databaseName, this._services);
80+
CosmosDatabaseOptions databaseBuilder = new(databaseName, this.services);
7581

76-
this._databases.Add(databaseName, databaseBuilder);
82+
this.databases.Add(databaseName, databaseBuilder);
7783

7884
return databaseBuilder;
7985
}
@@ -85,12 +91,12 @@ internal CosmosOptions Validate()
8591
throw new InvalidOperationException("CosmosClient must be configured before building");
8692
}
8793

88-
if (this._databases.Count == 0)
94+
if (this.databases.Count == 0)
8995
{
9096
throw new InvalidOperationException("At least one database must be configured");
9197
}
9298

93-
if (this._services.Count == 0)
99+
if (this.services.Count == 0)
94100
{
95101
throw new InvalidOperationException("At least one entity must be added");
96102
}
@@ -104,9 +110,9 @@ ICosmosContainerBuilder ICosmosOptionsBuilderWithClient.Database(string database
104110

105111
CosmosContainerOptions containerOptions = databaseBuilder.Container(containerProperties, shouldUpdateTimestamp);
106112

107-
this._services.Add(ServiceDescriptor.Singleton(containerOptions));
108-
this._services.Add(ServiceDescriptor.Singleton(typeof(ICosmosTableOptions<>), typeof(CosmosSharedTableOptions<>)));
109-
this._services.Add(ServiceDescriptor.Singleton(typeof(IRepository<>), typeof(CosmosTableRepository<>)));
113+
this.services.Add(ServiceDescriptor.Singleton(containerOptions));
114+
this.services.Add(ServiceDescriptor.Singleton(typeof(ICosmosTableOptions<>), typeof(CosmosSharedTableOptions<>)));
115+
this.services.Add(ServiceDescriptor.Singleton(typeof(IRepository<>), typeof(CosmosTableRepository<>)));
110116

111117
return containerOptions;
112118
}

src/CommunityToolkit.Datasync.Server.CosmosDb/Configuration/CosmosSharedTableOptions.cs renamed to src/CommunityToolkit.Datasync.Server.CosmosDb/CosmosSharedTableOptions.cs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,35 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33
// See the LICENSE file in the project root for more information.
44

5+
using CommunityToolkit.Datasync.Server.CosmosDb.Configuration;
56
using Microsoft.Azure.Cosmos;
67
using System.Linq.Expressions;
78

8-
namespace CommunityToolkit.Datasync.Server.CosmosDb.Configuration;
9+
namespace CommunityToolkit.Datasync.Server.CosmosDb;
910
/// <summary>
1011
/// Implementation of <see cref="ICosmosTableOptions{TEntity}" /> that supports storing multiple entity types in the same container.
1112
/// Defaults the partition key to the entity type name.
1213
/// </summary>
1314
/// <typeparam name="TEntity">The <see cref="CosmosTableData{T}"/> that these options applys to.</typeparam>
1415
public class CosmosSharedTableOptions<TEntity> : CosmosTableOptions<TEntity> where TEntity : CosmosTableData<TEntity>
1516
{
17+
/// <summary>
18+
/// Creates a new instance of the <see cref="CosmosSharedTableOptions{TEntity}" /> class.
19+
/// </summary>
20+
/// <param name="databaseId">The ID of the database that the container is in.</param>
21+
/// <param name="containerId">The ID of the container that the entities are stored in.</param>
22+
/// <param name="shouldUpdateTimestamp">Should the timestamp be updated when an entity is updated by the repository (default is true).</param>
23+
public CosmosSharedTableOptions(string databaseId, string containerId, bool shouldUpdateTimestamp = true) : base(databaseId, containerId, shouldUpdateTimestamp)
24+
{
25+
Entity = typeof(TEntity).Name;
26+
}
1627
/// <summary>
1728
/// Creates a new instance of the <see cref="CosmosSharedTableOptions{TEntity}" /> class.
1829
/// </summary>
1930
/// <param name="options">A <see cref="CosmosContainerOptions" /> containing the configured
2031
/// database and container for this entity</param>
21-
public CosmosSharedTableOptions(CosmosContainerOptions options) : base(options.DatabaseId, options.ContainerId, options.ShouldUpdateTimestamp)
32+
public CosmosSharedTableOptions(CosmosContainerOptions options) : this(options.DatabaseId, options.ContainerId, options.ShouldUpdateTimestamp)
2233
{
23-
Entity = typeof(TEntity).Name;
2434
}
2535
/// <summary>
2636
/// The entity type for the data. Used as the default partition key for shared containers. defaults to the entity type name.

src/CommunityToolkit.Datasync.Server.CosmosDb/Configuration/CosmosSingleTableOptions.cs renamed to src/CommunityToolkit.Datasync.Server.CosmosDb/CosmosSingleTableOptions.cs

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,34 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33
// See the LICENSE file in the project root for more information.
44

5+
using CommunityToolkit.Datasync.Server.CosmosDb.Configuration;
56
using Microsoft.Azure.Cosmos;
67
using System.Linq.Expressions;
78

8-
namespace CommunityToolkit.Datasync.Server.CosmosDb.Configuration;
9+
namespace CommunityToolkit.Datasync.Server.CosmosDb;
910
/// <summary>
1011
/// Implementation of <see cref="CosmosTableOptions{TEntity}"/> for a single table. Defaults the partition key to the entity's ID.
1112
/// </summary>
12-
/// <typeparam name="TEntity"></typeparam>
13-
/// <param name="options"></param>
14-
public class CosmosSingleTableOptions<TEntity>(CosmosContainerOptions options) : CosmosTableOptions<TEntity>(options.DatabaseId, options.ContainerId, options.ShouldUpdateTimestamp) where TEntity : CosmosTableData
13+
/// <typeparam name="TEntity">The <see cref="CosmosTableData" /> that these options apply to.</typeparam>
14+
public class CosmosSingleTableOptions<TEntity> : CosmosTableOptions<TEntity> where TEntity : CosmosTableData
1515
{
16+
/// <summary>
17+
/// Creates a new instance of the <see cref="CosmosSingleTableOptions{TEntity}" /> class.
18+
/// </summary>
19+
/// <param name="databaseId">The ID of the database that the container is in.</param>
20+
/// <param name="containerId">The ID of the container that the entities are stored in.</param>
21+
/// <param name="shouldUpdateTimestamp">Should the timestamp be updated when an entity is updated by the repository (default is true).</param>
22+
public CosmosSingleTableOptions(string databaseId, string containerId, bool shouldUpdateTimestamp = true) : base(databaseId, containerId, shouldUpdateTimestamp)
23+
{
24+
}
25+
/// <summary>
26+
/// Creates a new instance of the <see cref="CosmosSingleTableOptions{TEntity}" /> class.
27+
/// </summary>
28+
/// <param name="options">The <see cref="CosmosContainerOptions" /> containing the container configuration for these options.</param>
29+
public CosmosSingleTableOptions(CosmosContainerOptions options) : base(options.DatabaseId, options.ContainerId, options.ShouldUpdateTimestamp)
30+
{
31+
}
32+
1633
/// <summary>
1734
/// Gets a <see cref="PartitionKey"/> containing the entities Id.
1835
/// </summary>

src/CommunityToolkit.Datasync.Server.CosmosDb/Configuration/CosmosTableOptions.cs renamed to src/CommunityToolkit.Datasync.Server.CosmosDb/CosmosTableOptions.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55
using Microsoft.Azure.Cosmos;
66
using System.Linq.Expressions;
77

8-
namespace CommunityToolkit.Datasync.Server.CosmosDb.Configuration;
8+
namespace CommunityToolkit.Datasync.Server.CosmosDb;
99

1010
/// <summary>
11-
/// Base implementaion of <see cref="ICosmosTableOptions{TEntity}"/>
11+
/// Base implementation of <see cref="ICosmosTableOptions{TEntity}"/>
1212
/// </summary>
1313
/// <typeparam name="TEntity">The <see cref="CosmosTableData"/> that these options apply to.</typeparam>
1414
public abstract class CosmosTableOptions<TEntity> : ICosmosTableOptions<TEntity> where TEntity : CosmosTableData
@@ -49,7 +49,7 @@ public CosmosTableOptions(
4949
/// <inheritdoc />
5050
public virtual Func<TEntity, string> IdGenerator => (_) => Guid.NewGuid().ToString();
5151
/// <inheritdoc />
52-
public virtual bool TryParsePartitionKey(string entityId, out string? id, out PartitionKey? partitionKey)
52+
public virtual bool TryParsePartitionKey(string entityId, out string id, out PartitionKey partitionKey)
5353
{
5454
try
5555
{
@@ -59,8 +59,8 @@ public virtual bool TryParsePartitionKey(string entityId, out string? id, out Pa
5959
}
6060
catch
6161
{
62-
id = null;
63-
partitionKey = null;
62+
id = string.Empty;
63+
partitionKey = default;
6464
return false;
6565
}
6666
}

src/CommunityToolkit.Datasync.Server.CosmosDb/CosmosTableRepository.cs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,9 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33
// See the LICENSE file in the project root for more information.
44

5-
using CommunityToolkit.Datasync.Server;
6-
using CommunityToolkit.Datasync.Server.CosmosDb.Configuration;
75
using CommunityToolkit.Datasync.Server.CosmosDb.Extensions;
86
using Microsoft.Azure.Cosmos;
97
using Microsoft.Azure.Cosmos.Linq;
10-
using System.Diagnostics.CodeAnalysis;
118
using System.Net;
129
using System.Text;
1310

@@ -146,7 +143,10 @@ public virtual async ValueTask DeleteAsync(string id, byte[]? version = null, Ca
146143
throw new HttpException((int)HttpStatusCode.BadRequest, "ID is required");
147144
}
148145

149-
string entityId = Options.ParsePartitionKey(id, out PartitionKey partitionKey);
146+
if (Options.TryParsePartitionKey(id, out string entityId, out PartitionKey partitionKey) == false)
147+
{
148+
throw new HttpException((int)HttpStatusCode.BadRequest, "ID is not in the correct format");
149+
}
150150

151151
await WrapExceptionAsync(id, partitionKey, async () =>
152152
{
@@ -173,7 +173,10 @@ public virtual async ValueTask<TEntity> ReadAsync(string id, CancellationToken c
173173
throw new HttpException((int)HttpStatusCode.BadRequest, "ID is required");
174174
}
175175

176-
string entityId = Options.ParsePartitionKey(id, out PartitionKey partitionKey);
176+
if(Options.TryParsePartitionKey(id, out string entityId, out PartitionKey partitionKey) == false)
177+
{
178+
throw new HttpException((int)HttpStatusCode.BadRequest, "ID is not in the correct format");
179+
}
177180

178181
return await GetEntityAsync(entityId, partitionKey, cancellationToken).ConfigureAwait(false) ??
179182
throw new HttpException((int)HttpStatusCode.NotFound, $"Entity with id {id} not found");

src/CommunityToolkit.Datasync.Server.CosmosDb/Configuration/ICosmosTableOptions.cs renamed to src/CommunityToolkit.Datasync.Server.CosmosDb/ICosmosTableOptions.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
using Microsoft.Azure.Cosmos;
66
using System.Linq.Expressions;
77

8-
namespace CommunityToolkit.Datasync.Server.CosmosDb.Configuration;
8+
namespace CommunityToolkit.Datasync.Server.CosmosDb;
99
/// <summary>
1010
///
1111
/// </summary>
@@ -31,7 +31,7 @@ public interface ICosmosTableOptions<TEntity> where TEntity : CosmosTableData
3131
/// <param name="entityId">The entity passed from the controller to the repository ID</param>
3232
/// <param name="id">The entity ID after the entity has been parsed</param>
3333
/// <param name="partitionKey">The partition key after the entity has been parsed</param>
34-
bool TryParsePartitionKey(string entityId, out string? id, out PartitionKey? partitionKey);
34+
bool TryParsePartitionKey(string entityId, out string id, out PartitionKey partitionKey);
3535
/// <summary>
3636
/// Function to parse the partition key from the entity
3737
/// </summary>

tests/CommunityToolkit.Datasync.Server.CosmosDb.Test/CosmosDbRepository_Tests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ public async Task InitializeAsync()
127127

128128
this._repository = new CosmosTableRepository<CosmosDbMovie>(
129129
this._client,
130-
new CosmosDbTestOptions("Movies", "Movies")
130+
new CosmosSingleTableOptions<CosmosDbMovie>("Movies", "Movies")
131131
);
132132

133133
}

0 commit comments

Comments
 (0)