Skip to content

Commit

Permalink
feat: Adds TableBuilder, which can be used to pre-populate the intern…
Browse files Browse the repository at this point in the history
…al metadata cache used by the document and object-mapper DynamoDB programming models
  • Loading branch information
ashovlin committed Sep 20, 2023
1 parent fbb55ed commit 74020f5
Show file tree
Hide file tree
Showing 7 changed files with 703 additions and 2 deletions.
55 changes: 55 additions & 0 deletions sdk/src/Services/DynamoDBv2/Custom/DataModel/Context.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,61 @@ public partial class DynamoDBContext : IDynamoDBContext

#endregion

#region Public methods
/// <summary>
/// Adds a <see cref="Table"/> to this context's internal cache, which
/// will avoid the need to fetch table metadata automatically from DynamoDB.
/// This may be used in conjunction with an <see cref="ITableBuilder"/>.
/// </summary>
/// <remarks>
/// Using this method can avoid latency and potential deadlocks due to the internal
/// <see cref="IAmazonDynamoDB.DescribeTable(string)"/> call that is used to populate
/// the SDK's cache of table metadata. It requires that the table's index schema described accurately,
/// otherwise exceptions may be thrown and/or the results of certain DynamoDB operations may change.
/// It is recommended to test your application prior to using this in production code.
/// </remarks>
/// <param name="table">Table to add to the internal cache</param>
public void RegisterTableDefinition(Table table)
{
try
{
_readerWriterLockSlim.EnterReadLock();

if (tablesMap.ContainsKey(table.TableName))
{
return;
}
}
finally
{
if (_readerWriterLockSlim.IsReadLockHeld)
{
_readerWriterLockSlim.ExitReadLock();
}
}

try
{
_readerWriterLockSlim.EnterWriteLock();

// Check to see if another thread go the write lock before this thread and filled the cache.
if (tablesMap.ContainsKey(table.TableName))
{
return;
}

tablesMap[table.TableName] = table;
}
finally
{
if (_readerWriterLockSlim.IsWriteLockHeld)
{
_readerWriterLockSlim.ExitWriteLock();
}
}
}
#endregion

#region Constructors

#if !NETSTANDARD
Expand Down
61 changes: 61 additions & 0 deletions sdk/src/Services/DynamoDBv2/Custom/DocumentModel/ITableBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* 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.
*/

namespace Amazon.DynamoDBv2.DocumentModel
{
/// <summary>
/// Interface for a builder that constructs a <see cref="Table"/>
/// </summary>
public interface ITableBuilder
{
/// <summary>
/// Call at the end to retrieve the new <see cref="Table"/>
/// </summary>
/// <returns>Built table</returns>
Table Build();

/// <summary>
/// Adds the primary key definition to the table
/// </summary>
/// <param name="hashKeyAttribute">Name of the attribute used as the partition key</param>
/// <param name="type">Type of that attribute</param>
ITableBuilder AddHashKey(string hashKeyAttribute, DynamoDBEntryType type);

/// <summary>
/// Adds a sort key definition to the table
/// </summary>
/// <param name="rangeKeyAttribute">Name of the attribute used as the sort key</param>
/// <param name="type">Type of that attribute </param>
ITableBuilder AddRangeKey(string rangeKeyAttribute, DynamoDBEntryType type);

/// <summary>
/// Adds a local secondary index definition to the table
/// </summary>
/// <param name="indexName">Name of the local secondary index</param>
/// <param name="rangeKeyAttribute">Name of the attribute used as the sort key in the local secondary index</param>
/// <param name="type">Type of that attribute</param>
ITableBuilder AddLocalSecondaryIndex(string indexName, string rangeKeyAttribute, DynamoDBEntryType type);

/// <summary>
/// Adds a global secondary index definition to the table
/// </summary>
/// <param name="indexName">Name of the global secondary index</param>
/// <param name="hashkeyAttribute">Name of the attribute used as the partition key in the GSI</param>
/// <param name="hashKeyType">Type of the hash key attribute</param>
/// <param name="rangeKeyAttribute">Name of the attribute used as the sort key in the GSI</param>
/// <param name="rangeKeyType">Type of the sort key attribute</param>
ITableBuilder AddGlobalSecondaryIndex(string indexName, string hashkeyAttribute, DynamoDBEntryType hashKeyType, string rangeKeyAttribute, DynamoDBEntryType rangeKeyType);
}
}
4 changes: 2 additions & 2 deletions sdk/src/Services/DynamoDBv2/Custom/DocumentModel/Table.cs
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ private static void ValidateConditional(IConditionalOperationConfig config)
throw new InvalidOperationException("Only one of the conditonal properties Expected, ExpectedState and ConditionalExpression can be set.");
}

private void ClearTableData()
internal void ClearTableData()
{
Keys = new Dictionary<string, KeyDescription>();
HashKeys = new List<string>();
Expand Down Expand Up @@ -399,7 +399,7 @@ internal Dictionary<string, AttributeValue> ToAttributeMap(Document doc, DynamoD

#region Constructor/factory

private Table(IAmazonDynamoDB ddbClient, TableConfig config)
internal Table(IAmazonDynamoDB ddbClient, TableConfig config)
{
if (config == null)
throw new ArgumentNullException("config");
Expand Down
Loading

0 comments on commit 74020f5

Please sign in to comment.