protected DictionaryDdbConverterBase(DynamoDbContextMetadata metadata) { KeyConverter = metadata.GetOrAddConverter <TKey>(); ValueConverter = metadata.GetOrAddConverter <TValue>(); KeyDictionaryConverter = KeyConverter as IDictionaryKeyConverter <TKey> ?? throw new DdbException($"{KeyConverter.GetType().Name} must implement IDictionaryKeyConverter in order to store value as a dictionary key."); }
public void Setup() { var metadata = new DynamoDbContextMetadata(Array.Empty <DdbConverter>()); _properties = new DdbClassInfo(typeof(MediumStringFieldsEntity), metadata, new ObjectDdbConverter <MediumStringFieldsEntity>(metadata)).Properties.OfType <DdbPropertyInfo <string> >().ToArray(); _entity = new MediumStringFieldsEntity(); }
public static Document ToDocument <T>(this T entity, DynamoDbContextMetadata metadata) where T : class { var classInfo = metadata.GetOrAddClassInfo(typeof(T)); var document = new Document(classInfo.Properties.Length); foreach (var property in classInfo.Properties) { property.SetDocumentValue(entity, document); } return(document); }
public static T ToObject <T>(this Document document, DynamoDbContextMetadata metadata) where T : class { var classInfo = metadata.GetOrAddClassInfo(typeof(T)); var entity = classInfo.Constructor !(); foreach (var pair in document) { if (!classInfo.AttributesMap.TryGetValue(pair.Key, out var propertyInfo) || pair.Value.IsNull) { continue; } propertyInfo.SetValue(entity, pair.Value); } return((T)entity); }
internal abstract DdbPropertyInfo CreateDdbPropertyInfo(PropertyInfo propertyInfo, string attributeName, DynamoDbAttributeType attributeType, DynamoDbContextMetadata dynamoDbContextMetadata);
public DdbEntityReadStack(int defaultStackLength, DynamoDbContextMetadata metadata) : this() { _previous = ArrayPool <DdbEntityReadStackFrame> .Shared.Rent(defaultStackLength); Metadata = metadata; }
public override DdbConverter CreateConverter(Type typeToConvert, DynamoDbContextMetadata metadata) => new AttributeValueDdbConverter();
public DdbPropertyInfo(PropertyInfo propertyInfo, string attributeName, DynamoDbAttributeType attributeType, DdbConverter <T> converter, DynamoDbContextMetadata metadata) : base(propertyInfo, attributeName, attributeType) { Converter = converter; Get = EmitMemberAccessor.CreatePropertyGetter <T>(propertyInfo); Set = propertyInfo.SetMethod != null?EmitMemberAccessor.CreatePropertySetter <T>(propertyInfo) : null; RuntimeClassInfo = metadata.GetOrAddClassInfo(propertyInfo.PropertyType, converter); }
public static ValueTask WriteEntityAsync(this DdbWriter writer, object entity, DynamoDbContextMetadata metadata) => WriteEntityAsync(writer, metadata.GetOrAddClassInfo(entity.GetType()), entity);
public DdbClassInfo(Type type, DynamoDbContextMetadata metadata, DdbConverter converter) { Type = type; var properties = new Dictionary <string, DdbPropertyInfo>(); var jsonProperties = new JsonReaderDictionary <DdbPropertyInfo>(); ConverterBase = converter; ConverterType = converter.GetType(); ClassType = ConverterBase.ClassType; switch (ClassType) { case DdbClassType.Object: { for (var currentType = type; currentType != null; currentType = currentType.BaseType) { const BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly; foreach (PropertyInfo propertyInfo in currentType.GetProperties(bindingFlags)) { var attribute = propertyInfo.GetCustomAttribute <DynamoDbPropertyAttribute>(); if (attribute == null) { continue; } if (properties.ContainsKey(attribute.Name)) { continue; } var propertyConverter = metadata.GetOrAddConverter(propertyInfo.PropertyType, attribute.DdbConverterType); var ddbPropertyInfo = propertyConverter.CreateDdbPropertyInfo(propertyInfo, attribute.Name, attribute.AttributeType, metadata); properties.Add(attribute.Name, ddbPropertyInfo); jsonProperties.Add(attribute.Name, ddbPropertyInfo); switch (attribute.AttributeType) { case DynamoDbAttributeType.PartitionKey: if (PartitionKey != null) { throw new DdbException($"An entity {Type.FullName} contains multiple partition key attributes"); } PartitionKey = ddbPropertyInfo; break; case DynamoDbAttributeType.SortKey: if (SortKey != null) { throw new DdbException($"An entity {Type.FullName} contains multiple sort key attributes"); } SortKey = ddbPropertyInfo; break; } if (Version == null && propertyInfo.GetCustomAttribute <DynamoDbVersionAttribute>() != null) { Version = ddbPropertyInfo; } } TableName ??= currentType.GetCustomAttribute <DynamoDbTableAttribute>()?.TableName; } Constructor = EmitMemberAccessor.CreateConstructor(type) ?? throw new InvalidOperationException($"Can't generate constructor delegate for type '{type}'."); break; } case DdbClassType.Enumerable: case DdbClassType.Dictionary: { ElementType = ConverterBase.ElementType; ElementClassInfo = metadata.GetOrAddClassInfo(ElementType !); break; } } AttributesMap = properties; PropertiesMap = properties.Values.ToDictionary(x => x.PropertyInfo.Name); JsonProperties = jsonProperties; Properties = properties.Values.ToArray(); }
public static async ValueTask <ReadResult <TEntity> > ReadAsync <TEntity>(Stream utf8Json, DdbClassInfo classInfo, DynamoDbContextMetadata metadata, bool returnCrc, int defaultBufferSize = DefaultBufferSize, CancellationToken cancellationToken = default) where TEntity : class { var readerState = new JsonReaderState(); var readStack = new DdbEntityReadStack(DdbEntityReadStack.DefaultStackLength, metadata); try { readStack.GetCurrent().ClassInfo ??= classInfo; var buffer = ArrayPool <byte> .Shared.Rent(defaultBufferSize); var clearMax = 0; try { var bytesInBuffer = 0; uint crc = 0; var isFirstBlock = true; while (true) { var isFinalBlock = false; while (true) { var bytesRead = await utf8Json.ReadAsync(new Memory <byte>(buffer, bytesInBuffer, buffer.Length - bytesInBuffer), cancellationToken).ConfigureAwait(false); if (bytesRead == 0) { isFinalBlock = true; break; } if (returnCrc) { crc = Crc32Algorithm.Append(crc, buffer, bytesInBuffer, bytesRead); } bytesInBuffer += bytesRead; if (bytesInBuffer == buffer.Length) { break; } } if (bytesInBuffer > clearMax) { clearMax = bytesInBuffer; } readStack.UseFastPath = isFirstBlock && isFinalBlock; readStack.Buffer = buffer; readStack.BufferStart = 0; readStack.BufferLength = bytesInBuffer; ReadCore <TEntity>(ref readerState, isFinalBlock, new ReadOnlySpan <byte>(buffer, 0, bytesInBuffer), ref readStack); var bytesConsumed = (int)readStack.BytesConsumed; bytesInBuffer -= bytesConsumed; if (isFinalBlock) { break; } // Check if we need to shift or expand the buffer because there wasn't enough data to complete deserialization. if ((uint)bytesInBuffer > ((uint)buffer.Length / 2)) { // We have less than half the buffer available, double the buffer size. byte[] dest = ArrayPool <byte> .Shared.Rent((buffer.Length < (int.MaxValue / 2))?buffer.Length * 2 : int.MaxValue); // Copy the unprocessed data to the new buffer while shifting the processed bytes. Buffer.BlockCopy(buffer, bytesConsumed, dest, 0, bytesInBuffer); new Span <byte>(buffer, 0, clearMax).Clear(); ArrayPool <byte> .Shared.Return(buffer); clearMax = bytesInBuffer; buffer = dest; } else if (bytesInBuffer != 0) { // Shift the processed bytes to the beginning of buffer to make more room. Buffer.BlockCopy(buffer, bytesConsumed, buffer, 0, bytesInBuffer); } isFirstBlock = false; } return(new ReadResult <TEntity>((TEntity)readStack.GetCurrent().ReturnValue !, crc)); } finally { new Span <byte>(buffer, 0, clearMax).Clear(); ArrayPool <byte> .Shared.Return(buffer); } } finally { readStack.Dispose(); } }
public NumberSetDdbConverter(DynamoDbContextMetadata metadata) : base(metadata) { }
public JsonBatchGetItemUnprocessedKeysConverter(DynamoDbContextMetadata metadata) : base(metadata) { ValueConverter = (DdbConverter <TableBatchGetItemRequest>)metadata.GetOrAddConverter(typeof(TableBatchGetItemRequest), typeof(JsonObjectDdbConverter <TableBatchGetItemRequest>)); }
public JsonIReadOnlyDictionaryDdbConverter(DynamoDbContextMetadata metadata) { _keyConverter = metadata.GetOrAddConverter <TKey>(); ValueConverter = metadata.GetOrAddConverter <TValue>(); }
public JsonBatchGetItemResponsesConverter(DynamoDbContextMetadata metadata) : base(metadata) { var entityType = typeof(TValue).GenericTypeArguments[0]; ValueConverter = (DdbConverter <TValue>)metadata.GetOrAddConverter(typeof(TValue), typeof(JsonListDdbConverter <>).MakeGenericType(entityType)); }
internal sealed override DdbPropertyInfo CreateDdbPropertyInfo(PropertyInfo propertyInfo, string attributeName, DynamoDbAttributeType attributeType, DynamoDbContextMetadata dynamoDbContextMetadata) { Debug.Fail("We should never get here."); throw new InvalidOperationException(); }
public abstract DdbConverter CreateConverter(Type typeToConvert, DynamoDbContextMetadata metadata);
public ObjectDdbConverter(DynamoDbContextMetadata metadata) { _metadata = metadata; }
public SdkEnumHashSetConverter(DynamoDbContextMetadata metadata) : base(metadata.GetOrAddConverter <TEnum>()) { }
public DdbExpressionVisitor(DynamoDbContextMetadata metadata) { _metadata = metadata; }
public DictionaryDdbConverter(DynamoDbContextMetadata metadata) : base(metadata) { }
public static async ValueTask ProcessErrorAsync(DynamoDbContextMetadata metadata, HttpResponseMessage response, CancellationToken cancellationToken = default) { try { await using var responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); if (response.StatusCode == HttpStatusCode.ServiceUnavailable) { throw new ServiceUnavailableException("DynamoDB is currently unavailable. (This should be a temporary state.)"); } var recyclableStream = DynamoDbHttpContent.MemoryStreamManager.GetStream(); try { await responseStream.CopyToAsync(recyclableStream, cancellationToken).ConfigureAwait(false); recyclableStream.Position = 0; var error = await JsonSerializer.DeserializeAsync <Error>(recyclableStream, SerializerOptions, cancellationToken).ConfigureAwait(false); recyclableStream.Position = 0; switch (response.StatusCode) { case HttpStatusCode.BadRequest: var type = error.Type; var exceptionStart = error.Type?.LastIndexOf('#') ?? -1; if (exceptionStart != -1) { type = error.Type !.Substring(exceptionStart + 1); } if (type == "TransactionCanceledException") { var classInfo = metadata.GetOrAddClassInfo(typeof(TransactionCancelledResponse), typeof(JsonObjectDdbConverter <TransactionCancelledResponse>)); var transactionCancelledResponse = await EntityDdbJsonReader .ReadAsync <TransactionCancelledResponse>(recyclableStream, classInfo, metadata, false, cancellationToken : cancellationToken) .ConfigureAwait(false); throw new TransactionCanceledException(transactionCancelledResponse.Value !.CancellationReasons, error.Message); } throw type switch { "AccessDeniedException" => new AccessDeniedException(error.Message), "ConditionalCheckFailedException" => new ConditionalCheckFailedException(error.Message), "IncompleteSignatureException" => new IncompleteSignatureException(error.Message), "ItemCollectionSizeLimitExceededException" => new ItemCollectionSizeLimitExceededException(error.Message), "LimitExceededException" => new LimitExceededException(error.Message), "MissingAuthenticationTokenException" => new MissingAuthenticationTokenException(error.Message), "ProvisionedThroughputExceededException" => new ProvisionedThroughputExceededException(error.Message), "RequestLimitExceeded" => new RequestLimitExceededException(error.Message), "ResourceInUseException" => new ResourceInUseException(error.Message), "ResourceNotFoundException" => new ResourceNotFoundException(error.Message), "ThrottlingException" => new ThrottlingException(error.Message), "UnrecognizedClientException" => new UnrecognizedClientException(error.Message), "ValidationException" => new ValidationException(error.Message), "IdempotentParameterMismatchException" => new IdempotentParameterMismatchException(error.Message), "TransactionInProgressException" => new TransactionInProgressException(error.Message), _ => new DdbException(error.Message ?? type ?? string.Empty) }; case HttpStatusCode.InternalServerError: throw new InternalServerErrorException(error.Message); default: throw new DdbException(error.Message); } } finally { await recyclableStream.DisposeAsync().ConfigureAwait(false); } } finally { response.Dispose(); } }
private static DdbConverter <TValue> CreateValueConverter(DynamoDbContextMetadata metadata) { var transactResponseType = typeof(TValue); return((DdbConverter <TValue>)metadata.GetOrAddConverter(transactResponseType, typeof(JsonObjectDdbConverter <>).MakeGenericType(transactResponseType))); }
public StringSetDdbConverter(DynamoDbContextMetadata metadata) : base(metadata) { _isString = typeof(T) == typeof(string); }
protected SetDdbConverter(DynamoDbContextMetadata metadata) { ElementConverter = metadata.GetOrAddConverter <TElement>(); ElementSetValueConverter = ElementConverter as ISetValueConverter <TElement> ?? throw new DdbException($"{ElementConverter.GetType().Name} must implement ISetValueConverter in order to store value as a part of dynamodb set."); }
public override DdbConverter CreateConverter(Type typeToConvert, DynamoDbContextMetadata metadata) => new DocumentDdbConverter();
public override DdbConverter CreateConverter(Type typeToConvert, DynamoDbContextMetadata metadata) { return(new BinaryDdbConverter()); }
public StringSetDdbConverter(DynamoDbContextMetadata metadata) : base(metadata) { }
public TransactGetItemsResponsesConverter(DynamoDbContextMetadata metadata) : base(CreateValueConverter(metadata)) { }