Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion sdk/src/Services/DynamoDBv2/Custom/DataModel/Context.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ public void RegisterTableDefinition(Table table)
/// Constructs a DynamoDBContext object with a default AmazonDynamoDBClient
/// client and a default DynamoDBContextConfig object for configuration.
/// </summary>
[Obsolete("Use the DynamoDBContextBuilder to construct a DynamoDBContext with the recommended configuration.")]
public DynamoDBContext()
: this(new AmazonDynamoDBClient()) { }

Expand All @@ -111,6 +112,7 @@ public DynamoDBContext()
/// client and a default DynamoDBContextConfig object for configuration.
/// </summary>
/// <param name="region">The region to configure the AmazonDynamoDBClient to use.</param>
[Obsolete("Use the DynamoDBContextBuilder to construct a DynamoDBContext with the recommended configuration.")]
public DynamoDBContext(RegionEndpoint region)
: this(new AmazonDynamoDBClient(region), true, new DynamoDBContextConfig()) { }

Expand All @@ -119,6 +121,7 @@ public DynamoDBContext(RegionEndpoint region)
/// Uses a default AmazonDynamoDBClient as the client.
/// </summary>
/// <param name="config"></param>
[Obsolete("Use the DynamoDBContextBuilder to construct a DynamoDBContext with the recommended configuration.")]
public DynamoDBContext(DynamoDBContextConfig config)
: this(new AmazonDynamoDBClient(), config) { }

Expand All @@ -128,6 +131,7 @@ public DynamoDBContext(DynamoDBContextConfig config)
/// </summary>
/// <param name="region">The region to configure the AmazonDynamoDBClient to use.</param>
/// <param name="config"></param>
[Obsolete("Use the DynamoDBContextBuilder to construct a DynamoDBContext with the recommended configuration.")]
public DynamoDBContext(RegionEndpoint region, DynamoDBContextConfig config)
: this(new AmazonDynamoDBClient(region), true, config) { }
#endif
Expand All @@ -137,6 +141,7 @@ public DynamoDBContext(RegionEndpoint region, DynamoDBContextConfig config)
/// Uses default DynamoDBContextConfig object for configuration.
/// </summary>
/// <param name="client">Client to use for making calls</param>
[Obsolete("Use the DynamoDBContextBuilder to construct a DynamoDBContext with the recommended configuration.")]
public DynamoDBContext(IAmazonDynamoDB client)
: this(client, false, new DynamoDBContextConfig()) { }

Expand All @@ -146,10 +151,11 @@ public DynamoDBContext(IAmazonDynamoDB client)
/// </summary>
/// <param name="client">Client to use for making calls</param>
/// <param name="config">Configuration to use</param>
[Obsolete("Use the DynamoDBContextBuilder to construct a DynamoDBContext with the recommended configuration.")]
public DynamoDBContext(IAmazonDynamoDB client, DynamoDBContextConfig config)
: this(client, false, config) { }

private DynamoDBContext(IAmazonDynamoDB client, bool ownClient, DynamoDBContextConfig config)
internal DynamoDBContext(IAmazonDynamoDB client, bool ownClient, DynamoDBContextConfig config)
{
if (client == null) throw new ArgumentNullException("client");

Expand Down
81 changes: 81 additions & 0 deletions sdk/src/Services/DynamoDBv2/Custom/DataModel/ContextBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/

using System;

namespace Amazon.DynamoDBv2.DataModel
{
/// <inheritdoc cref="IDynamoDBContextBuilder" />
#if NET8_0_OR_GREATER
[System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode(Amazon.DynamoDBv2.Custom.Internal.InternalConstants.RequiresUnreferencedCodeMessage)]
#endif
public class DynamoDBContextBuilder : IDynamoDBContextBuilder
{
/// <summary>
/// The <see cref="DynamoDBContextConfig"/> object that is built and then supplied to the returned <see cref="DynamoDBContext"/>
/// </summary>
private DynamoDBContextConfig _config;

/// <summary>
/// A factory method for creating a <see cref="IAmazonDynamoDB"/> client
/// </summary>
private Func<IAmazonDynamoDB> _clientFactory;

/// <summary>
/// Creates a builder object to construct a <see cref="DynamoDBContext"/>
/// </summary>
public DynamoDBContextBuilder()
{
_config = new DynamoDBContextConfig();
_config.DisableFetchingTableMetadata = true;
}

/// <inheritdoc/>
public IDynamoDBContextBuilder ConfigureContext(Action<DynamoDBContextConfig> configure)
{
configure(_config);

return this;
}

/// <inheritdoc/>
public IDynamoDBContextBuilder WithDynamoDBClient(Func<IAmazonDynamoDB> factory)
{
_clientFactory = factory;

return this;
}

/// <inheritdoc/>
public DynamoDBContext Build()
{
IAmazonDynamoDB client;
bool ownClient;

if (_clientFactory is null)
{
client = new AmazonDynamoDBClient();
ownClient = true;
}
else
{
client = _clientFactory.Invoke();
ownClient = false;
}

return new DynamoDBContext(client, ownClient, _config);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,9 @@ internal Table GetTargetTable(ItemStorageConfig storageConfig, DynamoDBFlatConfi
return table;
}

// This is the call we want to avoid with disableFetchingTableMetadata = true, but as long as we still support false, we still need to call the discouraged sync-over-async 'Table.LoadTable(Client, emptyConfig)'
#pragma warning disable CS0618

// Retrieves Config-less Table from cache or constructs it on cache-miss
// This Table should not be used for data operations.
// To use for data operations, Copy with a TableConfig first.
Expand Down Expand Up @@ -203,6 +206,8 @@ internal Table GetUnconfiguredTable(string tableName, bool disableFetchingTableM
}
}

#pragma warning restore CS0618

/// <summary>
/// Stores a table in the cache if there is not an existing entry for the given key
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/

using System;

namespace Amazon.DynamoDBv2.DataModel
{
/// <summary>
/// Interface for a builder that constructs a <see cref="DynamoDBContext"/>
Copy link
Member

Choose a reason for hiding this comment

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

Add would suggest giving more context for users upgrading about how this newer approach disables the DescribeTable mechanism. And explain how the can use the ConfigureContext method to revert to pervious behavior if they need it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added more docs in the interface and inheritor.

Copy link
Member

Choose a reason for hiding this comment

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

Add a line that says alternatively to attributes on the class you can register the table definition using the RegisterTableDefinition method on the context object.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

/// Using <see cref="IDynamoDBContextBuilder"/> to construct a <see cref="DynamoDBContext"/> will implicitly set
/// <see cref="DynamoDBContextConfig.DisableFetchingTableMetadata"/> to true which avoids the DescribeTable call
/// and relies entirely on the DynamoDB attributes set on the .NET classes. Alternatively, you can register the
/// table definition using <see cref="DynamoDBContext.RegisterTableDefinition(DocumentModel.Table)"/>.
/// If needed, you can revert back to the previous behavior by setting <see cref="DynamoDBContextConfig.DisableFetchingTableMetadata"/>
/// to false using <see cref="IDynamoDBContextBuilder.ConfigureContext(Action{DynamoDBContextConfig})"/> as such:
/// <code>
/// var context = new DynamoDBContextBuilder()
/// .ConfigureContext(x =>
/// {
/// x.DisableFetchingTableMetadata = false;
/// })
/// .Build();
/// </code>
/// </summary>
public interface IDynamoDBContextBuilder
{
/// <summary>
/// Supplies a factory method for creating a <see cref="IAmazonDynamoDB"/> client.
/// If a factory method is not provided, a new <see cref="IAmazonDynamoDB"/> client
/// will be created using the environment to search for credentials and region configuration.
/// </summary>
/// <param name="factory">Factory method for creating a <see cref="IAmazonDynamoDB"/> client</param>
IDynamoDBContextBuilder WithDynamoDBClient(Func<IAmazonDynamoDB> factory);

/// <summary>
/// Configures the <see cref="DynamoDBContext"/> that is being constructed
/// </summary>
/// <param name="configure">The configuration applied to the constructed <see cref="DynamoDBContext"/></param>
IDynamoDBContextBuilder ConfigureContext(Action<DynamoDBContextConfig> configure);

/// <summary>
/// Call at the end to retrieve the new <see cref="DynamoDBContext"/>
/// </summary>
/// <returns>Built <see cref="DynamoDBContext"/></returns>
DynamoDBContext Build();
}
}
12 changes: 12 additions & 0 deletions sdk/src/Services/DynamoDBv2/Custom/DocumentModel/Table.cs
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,7 @@ public static void ClearTableCache()
/// <param name="ddbClient">Client to use to access DynamoDB.</param>
/// <param name="config">Configuration to use for the table.</param>
/// <returns>Table object representing the specified table.</returns>
[Obsolete("Use the TableBuilder to construct a Table with the recommended configuration.")]
public static Table LoadTable(IAmazonDynamoDB ddbClient, TableConfig config)
{
Table table = new Table(ddbClient, config);
Expand Down Expand Up @@ -648,6 +649,7 @@ internal static Table CreateTableFromItemStorageConfig(IAmazonDynamoDB client, T
/// <param name="ddbClient">Client to use to access DynamoDB.</param>
/// <param name="tableName">Name of the table.</param>
/// <returns>Table object representing the specified table.</returns>
[Obsolete("Use the TableBuilder to construct a Table with the recommended configuration.")]
public static Table LoadTable(IAmazonDynamoDB ddbClient, string tableName)
{
return LoadTable(ddbClient, tableName, DynamoDBEntryConversion.CurrentConversion, false);
Expand All @@ -663,6 +665,7 @@ public static Table LoadTable(IAmazonDynamoDB ddbClient, string tableName)
/// <param name="tableName">Name of the table.</param>
/// <param name="conversion">Conversion to use for converting .NET values to DynamoDB values.</param>
/// <returns>Table object representing the specified table.</returns>
[Obsolete("Use the TableBuilder to construct a Table with the recommended configuration.")]
public static Table LoadTable(IAmazonDynamoDB ddbClient, string tableName, DynamoDBEntryConversion conversion)
{
return LoadTable(ddbClient, tableName, conversion, false);
Expand All @@ -678,6 +681,7 @@ public static Table LoadTable(IAmazonDynamoDB ddbClient, string tableName, Dynam
/// <param name="tableName">Name of the table.</param>
/// <param name="isEmptyStringValueEnabled">If the property is false, empty string values will be interpreted as null values.</param>
/// <returns>Table object representing the specified table.</returns>
[Obsolete("Use the TableBuilder to construct a Table with the recommended configuration.")]
public static Table LoadTable(IAmazonDynamoDB ddbClient, string tableName, bool isEmptyStringValueEnabled)
{
return LoadTable(ddbClient, tableName, DynamoDBEntryConversion.CurrentConversion, isEmptyStringValueEnabled);
Expand All @@ -694,6 +698,7 @@ public static Table LoadTable(IAmazonDynamoDB ddbClient, string tableName, bool
/// <param name="conversion">Conversion to use for converting .NET values to DynamoDB values.</param>
/// <param name="isEmptyStringValueEnabled">If the property is false, empty string values will be interpreted as null values.</param>
/// <returns>Table object representing the specified table.</returns>
[Obsolete("Use the TableBuilder to construct a Table with the recommended configuration.")]
public static Table LoadTable(IAmazonDynamoDB ddbClient, string tableName, DynamoDBEntryConversion conversion, bool isEmptyStringValueEnabled)
{
var config = new TableConfig(tableName, conversion, DynamoDBConsumer.DocumentModel, storeAsEpoch: null, isEmptyStringValueEnabled: isEmptyStringValueEnabled, metadataCachingMode: MetadataCachingMode.Default);
Expand All @@ -715,6 +720,7 @@ public static Table LoadTable(IAmazonDynamoDB ddbClient, string tableName, Dynam
/// requests. This controls how the cache key is derived, which influences when the SDK will call
/// IAmazonDynamoDB.DescribeTable(string) internally to populate the cache.</param>
/// <returns>Table object representing the specified table.</returns>
[Obsolete("Use the TableBuilder to construct a Table with the recommended configuration.")]
public static Table LoadTable(IAmazonDynamoDB ddbClient, string tableName, DynamoDBEntryConversion conversion, bool isEmptyStringValueEnabled, MetadataCachingMode metadataCachingMode)
{
var config = new TableConfig(tableName, conversion, DynamoDBConsumer.DocumentModel, storeAsEpoch: null, isEmptyStringValueEnabled: isEmptyStringValueEnabled, metadataCachingMode: metadataCachingMode);
Expand All @@ -736,6 +742,7 @@ public static Table LoadTable(IAmazonDynamoDB ddbClient, string tableName, Dynam
/// <returns>
/// True if table was successfully loaded; otherwise false.
/// </returns>
[Obsolete("Use the TableBuilder to construct a Table with the recommended configuration.")]
public static bool TryLoadTable(IAmazonDynamoDB ddbClient, string tableName, out Table table)
{
return TryLoadTable(ddbClient, tableName, DynamoDBEntryConversion.CurrentConversion, false, out table);
Expand All @@ -754,6 +761,7 @@ public static bool TryLoadTable(IAmazonDynamoDB ddbClient, string tableName, out
/// <returns>
/// True if table was successfully loaded; otherwise false.
/// </returns>
[Obsolete("Use the TableBuilder to construct a Table with the recommended configuration.")]
public static bool TryLoadTable(IAmazonDynamoDB ddbClient, string tableName, DynamoDBEntryConversion conversion, out Table table)
{
return TryLoadTable(ddbClient, tableName, conversion, false, out table);
Expand All @@ -772,6 +780,7 @@ public static bool TryLoadTable(IAmazonDynamoDB ddbClient, string tableName, Dyn
/// <returns>
/// True if table was successfully loaded; otherwise false.
/// </returns>
[Obsolete("Use the TableBuilder to construct a Table with the recommended configuration.")]
public static bool TryLoadTable(IAmazonDynamoDB ddbClient, string tableName, bool isEmptyStringValueEnabled, out Table table)
{
return TryLoadTable(ddbClient, tableName, DynamoDBEntryConversion.CurrentConversion, isEmptyStringValueEnabled, out table);
Expand All @@ -791,6 +800,7 @@ public static bool TryLoadTable(IAmazonDynamoDB ddbClient, string tableName, boo
/// <returns>
/// True if table was successfully loaded; otherwise false.
/// </returns>
[Obsolete("Use the TableBuilder to construct a Table with the recommended configuration.")]
public static bool TryLoadTable(IAmazonDynamoDB ddbClient, string tableName, DynamoDBEntryConversion conversion, bool isEmptyStringValueEnabled, out Table table)
{
return TryLoadTable(ddbClient, tableName, conversion, isEmptyStringValueEnabled, MetadataCachingMode.Default, out table);
Expand All @@ -813,6 +823,7 @@ public static bool TryLoadTable(IAmazonDynamoDB ddbClient, string tableName, Dyn
/// <returns>
/// True if table was successfully loaded; otherwise false.
/// </returns>
[Obsolete("Use the TableBuilder to construct a Table with the recommended configuration.")]
public static bool TryLoadTable(IAmazonDynamoDB ddbClient,
string tableName,
DynamoDBEntryConversion conversion,
Expand Down Expand Up @@ -842,6 +853,7 @@ public static bool TryLoadTable(IAmazonDynamoDB ddbClient,
/// <returns>
/// True if table was successfully loaded; otherwise false.
/// </returns>
[Obsolete("Use the TableBuilder to construct a Table with the recommended configuration.")]
public static bool TryLoadTable(IAmazonDynamoDB ddbClient, TableConfig config, out Table table)
{
if (config == null)
Expand Down
10 changes: 10 additions & 0 deletions sdk/test/Services/DynamoDBv2/IntegrationTests/Cache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,15 @@ public void MultipleClientsTest()
Table table;
using (var nc = new AmazonDynamoDBClient())
{
#pragma warning disable CS0618 // Disable the warning for the deprecated DynamoDBContext constructors
table = Table.LoadTable(nc, tableName);
#pragma warning restore CS0618 // Re-enable the warning
}

Table.ClearTableCache();
#pragma warning disable CS0618 // Disable the warning for the deprecated DynamoDBContext constructors
table = Table.LoadTable(client, tableName);
#pragma warning restore CS0618 // Re-enable the warning
}

[TestMethod]
Expand All @@ -123,7 +127,9 @@ public void ChangingTableTest()
var tableCache = SdkCache.GetCache<string, TableDescription>(client, DynamoDBTests.TableCacheIdentifier, StringComparer.Ordinal);

CreateTable(TABLENAME, defaultKeys: true);
#pragma warning disable CS0618 // Disable the warning for the deprecated DynamoDBContext constructors
var table = Table.LoadTable(client, TABLENAME);
#pragma warning restore CS0618 // Re-enable the warning
table.PutItem(item);

using (var counter = new ServiceResponseCounter(client))
Expand All @@ -144,7 +150,9 @@ public void ChangingTableTest()

counter.Reset();
Table.ClearTableCache();
#pragma warning disable CS0618 // Disable the warning for the deprecated DynamoDBContext constructors
table = Table.LoadTable(client, TABLENAME);
#pragma warning restore CS0618 // Re-enable the warning
doc = table.GetItem(42, "Yes");
Assert.IsNotNull(doc);
Assert.AreNotEqual(0, doc.Count);
Expand All @@ -153,11 +161,13 @@ public void ChangingTableTest()
counter.Reset();
Table.ClearTableCache();
PutItem(tableCache, TABLENAME, oldTableDescription);
#pragma warning disable CS0618 // Disable the warning for the deprecated DynamoDBContext constructors
table = Table.LoadTable(client, TABLENAME);
doc = tableCache.UseCache(TABLENAME,
() => table.GetItem(42, "Yes"),
() => table = Table.LoadTable(client, TABLENAME),
shouldRetryForException: null);
#pragma warning restore CS0618 // Re-enable the warning

Assert.IsNotNull(doc);
Assert.AreNotEqual(0, doc.Count);
Expand Down
Loading