internal Document GetItemHelper(Key key, GetItemOperationConfig config, bool isAsync) { var currentConfig = config ?? new GetItemOperationConfig(); var request = new GetItemRequest { TableName = TableName, Key = key, ConsistentRead = currentConfig.ConsistentRead }; ((Amazon.Runtime.Internal.IAmazonWebServiceRequest)request).AddBeforeRequestHandler(isAsync ? new RequestEventHandler(UserAgentRequestEventHandlerAsync) : new RequestEventHandler(UserAgentRequestEventHandlerSync) ); if (currentConfig.AttributesToGet != null) { request.AttributesToGet = currentConfig.AttributesToGet; } var result = DDBClient.GetItem(request); var attributeMap = result.Item; if (attributeMap == null || attributeMap.Count == 0) { return(null); } return(Document.FromAttributeMap(attributeMap)); }
internal Document PutItemHelper(Document doc, PutItemOperationConfig config, bool isAsync) { var currentConfig = config ?? new PutItemOperationConfig(); PutItemRequest req = new PutItemRequest { TableName = TableName, Item = doc.ToAttributeMap() }; req.BeforeRequestEvent += isAsync ? new RequestEventHandler(UserAgentRequestEventHandlerAsync) : new RequestEventHandler(UserAgentRequestEventHandlerSync); if (currentConfig.Expected != null) { req.Expected = currentConfig.Expected.ToExpectedAttributeMap(); } if (currentConfig.ReturnValues == ReturnValues.AllOldAttributes) { req.ReturnValues = EnumToStringMapper.Convert(currentConfig.ReturnValues); } var resp = DDBClient.PutItem(req); doc.CommitChanges(); Document ret = null; if (currentConfig.ReturnValues == ReturnValues.AllOldAttributes) { ret = Document.FromAttributeMap(resp.Attributes); } return(ret); }
internal Document GetItemHelper(Key key, GetItemOperationConfig config) { var currentConfig = config ?? new GetItemOperationConfig(); var request = new GetItemRequest { TableName = TableName, Key = key, ConsistentRead = currentConfig.ConsistentRead }; this.AddRequestHandler(request, isAsync: false); if (currentConfig.AttributesToGet != null) { request.AttributesToGet = currentConfig.AttributesToGet; } var result = DDBClient.GetItem(request); var attributeMap = result.Item; if (attributeMap == null || attributeMap.Count == 0) { return(null); } return(this.FromAttributeMap(attributeMap)); }
internal async Task <Document> GetItemHelperAsync(Key key, GetItemOperationConfig config, CancellationToken cancellationToken) { var currentConfig = config ?? new GetItemOperationConfig(); var request = new GetItemRequest { TableName = TableName, Key = key, ConsistentRead = currentConfig.ConsistentRead }; this.AddRequestHandler(request, isAsync: true); if (currentConfig.AttributesToGet != null) { request.AttributesToGet = currentConfig.AttributesToGet; } var result = await DDBClient.GetItemAsync(request, cancellationToken).ConfigureAwait(false); var attributeMap = result.Item; if (attributeMap == null || attributeMap.Count == 0) { return(null); } return(this.FromAttributeMap(attributeMap)); }
internal Document DeleteHelper(Key key, DeleteItemOperationConfig config, bool isAsync) { var currentConfig = config ?? new DeleteItemOperationConfig(); var req = new DeleteItemRequest { TableName = TableName, Key = key }; req.BeforeRequestEvent += isAsync ? new RequestEventHandler(UserAgentRequestEventHandlerAsync) : new RequestEventHandler(UserAgentRequestEventHandlerSync); if (currentConfig.ReturnValues == ReturnValues.AllOldAttributes) { req.ReturnValues = EnumToStringMapper.Convert(currentConfig.ReturnValues); } if (currentConfig.Expected != null) { req.Expected = currentConfig.Expected.ToExpectedAttributeMap(); } var attributes = DDBClient.DeleteItem(req).Attributes; Document ret = null; if (currentConfig.ReturnValues == ReturnValues.AllOldAttributes) { ret = Document.FromAttributeMap(attributes); } return(ret); }
internal Document UpdateHelper(Document doc, Key key, UpdateItemOperationConfig config, bool isAsync) { var currentConfig = config ?? new UpdateItemOperationConfig(); // If the keys have been changed, treat entire document as having changed bool haveKeysChanged = HaveKeysChanged(doc); bool updateChangedAttributesOnly = !haveKeysChanged; var attributeUpdates = doc.ToAttributeUpdateMap(updateChangedAttributesOnly); foreach (var keyName in this.keyNames) { attributeUpdates.Remove(keyName); } UpdateItemRequest req = new UpdateItemRequest { TableName = TableName, Key = key, AttributeUpdates = attributeUpdates.Count == 0 ? null : attributeUpdates, // pass null if keys-only update ReturnValues = EnumMapper.Convert(currentConfig.ReturnValues) }; req.BeforeRequestEvent += isAsync ? new RequestEventHandler(UserAgentRequestEventHandlerAsync) : new RequestEventHandler(UserAgentRequestEventHandlerSync); if (currentConfig.Expected != null && currentConfig.ExpectedState != null) { throw new InvalidOperationException("Expected and ExpectedState cannot be set at the same time"); } if (currentConfig.Expected != null) { req.Expected = currentConfig.Expected.ToExpectedAttributeMap(); } if (currentConfig.ExpectedState != null && currentConfig.ExpectedState.ExpectedValues != null && currentConfig.ExpectedState.ExpectedValues.Count > 0) { req.Expected = currentConfig.ExpectedState.ToExpectedAttributeMap(); if (req.Expected.Count > 1) { req.ConditionalOperator = EnumMapper.Convert(currentConfig.ExpectedState.ConditionalOperator); } } var resp = DDBClient.UpdateItem(req); var returnedAttributes = resp.Attributes; doc.CommitChanges(); Document ret = null; if (currentConfig.ReturnValues != ReturnValues.None) { ret = Document.FromAttributeMap(returnedAttributes); } return(ret); }
internal Document PutItemHelper(Document doc, PutItemOperationConfig config, bool isAsync) { var currentConfig = config ?? new PutItemOperationConfig(); PutItemRequest req = new PutItemRequest { TableName = TableName, Item = doc.ToAttributeMap(Conversion) }; ((Amazon.Runtime.Internal.IAmazonWebServiceRequest)req).AddBeforeRequestHandler(isAsync ? new RequestEventHandler(UserAgentRequestEventHandlerAsync) : new RequestEventHandler(UserAgentRequestEventHandlerSync)); if (currentConfig.ReturnValues == ReturnValues.AllOldAttributes) { req.ReturnValues = EnumMapper.Convert(currentConfig.ReturnValues); } ValidateConditional(currentConfig); if (currentConfig.Expected != null) { req.Expected = currentConfig.Expected.ToExpectedAttributeMap(Conversion); } else if (currentConfig.ExpectedState != null && currentConfig.ExpectedState.ExpectedValues != null && currentConfig.ExpectedState.ExpectedValues.Count > 0) { req.Expected = currentConfig.ExpectedState.ToExpectedAttributeMap(Conversion); if (req.Expected.Count > 1) { req.ConditionalOperator = EnumMapper.Convert(currentConfig.ExpectedState.ConditionalOperator); } } else if (currentConfig.ConditionalExpression != null && currentConfig.ConditionalExpression.IsSet) { currentConfig.ConditionalExpression.ApplyExpression(req, this.Conversion); } var resp = DDBClient.PutItem(req); doc.CommitChanges(); Document ret = null; if (currentConfig.ReturnValues == ReturnValues.AllOldAttributes) { ret = Document.FromAttributeMap(resp.Attributes); } return(ret); }
internal async Task <Document> PutItemHelperAsync(Document doc, PutItemOperationConfig config, CancellationToken cancellationToken) { var currentConfig = config ?? new PutItemOperationConfig(); PutItemRequest req = new PutItemRequest { TableName = TableName, Item = this.ToAttributeMap(doc) }; this.AddRequestHandler(req, isAsync: true); if (currentConfig.ReturnValues == ReturnValues.AllOldAttributes) { req.ReturnValues = EnumMapper.Convert(currentConfig.ReturnValues); } ValidateConditional(currentConfig); if (currentConfig.Expected != null) { req.Expected = this.ToExpectedAttributeMap(currentConfig.Expected); } else if (currentConfig.ExpectedState != null && currentConfig.ExpectedState.ExpectedValues != null && currentConfig.ExpectedState.ExpectedValues.Count > 0) { req.Expected = currentConfig.ExpectedState.ToExpectedAttributeMap(this); if (req.Expected.Count > 1) { req.ConditionalOperator = EnumMapper.Convert(currentConfig.ExpectedState.ConditionalOperator); } } else if (currentConfig.ConditionalExpression != null && currentConfig.ConditionalExpression.IsSet) { currentConfig.ConditionalExpression.ApplyExpression(req, this); } var resp = await DDBClient.PutItemAsync(req, cancellationToken).ConfigureAwait(false); doc.CommitChanges(); Document ret = null; if (currentConfig.ReturnValues == ReturnValues.AllOldAttributes) { ret = this.FromAttributeMap(resp.Attributes); } return(ret); }
internal Document DeleteHelper(Key key, DeleteItemOperationConfig config, bool isAsync) { var currentConfig = config ?? new DeleteItemOperationConfig(); var req = new DeleteItemRequest { TableName = TableName, Key = key }; req.BeforeRequestEvent += isAsync ? new RequestEventHandler(UserAgentRequestEventHandlerAsync) : new RequestEventHandler(UserAgentRequestEventHandlerSync); if (currentConfig.ReturnValues == ReturnValues.AllOldAttributes) { req.ReturnValues = EnumMapper.Convert(currentConfig.ReturnValues); } ValidateConditional(currentConfig); if (currentConfig.Expected != null) { req.Expected = currentConfig.Expected.ToExpectedAttributeMap(Conversion); } else if (currentConfig.ExpectedState != null && currentConfig.ExpectedState.ExpectedValues != null && currentConfig.ExpectedState.ExpectedValues.Count > 0) { req.Expected = currentConfig.ExpectedState.ToExpectedAttributeMap(Conversion); if (req.Expected.Count > 1) { req.ConditionalOperator = EnumMapper.Convert(currentConfig.ExpectedState.ConditionalOperator); } } else if (currentConfig.ConditionalExpression != null && currentConfig.ConditionalExpression.IsSet) { currentConfig.ConditionalExpression.ApplyExpression(req, this.Conversion); } var attributes = DDBClient.DeleteItem(req).Attributes; Document ret = null; if (currentConfig.ReturnValues == ReturnValues.AllOldAttributes) { ret = Document.FromAttributeMap(attributes); } return(ret); }
internal async Task <Document> DeleteHelperAsync(Key key, DeleteItemOperationConfig config, CancellationToken cancellationToken) { var currentConfig = config ?? new DeleteItemOperationConfig(); var req = new DeleteItemRequest { TableName = TableName, Key = key }; this.AddRequestHandler(req, isAsync: true); if (currentConfig.ReturnValues == ReturnValues.AllOldAttributes) { req.ReturnValues = EnumMapper.Convert(currentConfig.ReturnValues); } ValidateConditional(currentConfig); if (currentConfig.Expected != null) { req.Expected = this.ToExpectedAttributeMap(currentConfig.Expected); } else if (currentConfig.ExpectedState != null && currentConfig.ExpectedState.ExpectedValues != null && currentConfig.ExpectedState.ExpectedValues.Count > 0) { req.Expected = currentConfig.ExpectedState.ToExpectedAttributeMap(this); if (req.Expected.Count > 1) { req.ConditionalOperator = EnumMapper.Convert(currentConfig.ExpectedState.ConditionalOperator); } } else if (currentConfig.ConditionalExpression != null && currentConfig.ConditionalExpression.IsSet) { currentConfig.ConditionalExpression.ApplyExpression(req, this); } var attributes = (await DDBClient.DeleteItemAsync(req, cancellationToken).ConfigureAwait(false)).Attributes; Document ret = null; if (currentConfig.ReturnValues == ReturnValues.AllOldAttributes) { ret = this.FromAttributeMap(attributes); } return(ret); }
internal Document PutItemHelper(Document doc, PutItemOperationConfig config, bool isAsync) { var currentConfig = config ?? new PutItemOperationConfig(); PutItemRequest req = new PutItemRequest { TableName = TableName, Item = doc.ToAttributeMap() }; req.BeforeRequestEvent += isAsync ? new RequestEventHandler(UserAgentRequestEventHandlerAsync) : new RequestEventHandler(UserAgentRequestEventHandlerSync); if (currentConfig.ReturnValues == ReturnValues.AllOldAttributes) { req.ReturnValues = EnumMapper.Convert(currentConfig.ReturnValues); } if (currentConfig.Expected != null && currentConfig.ExpectedState != null) { throw new InvalidOperationException("Expected and ExpectedState cannot be set at the same time"); } if (currentConfig.Expected != null) { req.Expected = currentConfig.Expected.ToExpectedAttributeMap(); } if (currentConfig.ExpectedState != null && currentConfig.ExpectedState.ExpectedValues != null && currentConfig.ExpectedState.ExpectedValues.Count > 0) { req.Expected = currentConfig.ExpectedState.ToExpectedAttributeMap(); if (req.Expected.Count > 1) { req.ConditionalOperator = EnumMapper.Convert(currentConfig.ExpectedState.ConditionalOperator); } } var resp = DDBClient.PutItem(req); doc.CommitChanges(); Document ret = null; if (currentConfig.ReturnValues == ReturnValues.AllOldAttributes) { ret = Document.FromAttributeMap(resp.Attributes); } return(ret); }
internal Document DeleteHelper(Key key, DeleteItemOperationConfig config, bool isAsync) { var currentConfig = config ?? new DeleteItemOperationConfig(); var req = new DeleteItemRequest { TableName = TableName, Key = key }; req.BeforeRequestEvent += isAsync ? new RequestEventHandler(UserAgentRequestEventHandlerAsync) : new RequestEventHandler(UserAgentRequestEventHandlerSync); if (currentConfig.ReturnValues == ReturnValues.AllOldAttributes) { req.ReturnValues = EnumMapper.Convert(currentConfig.ReturnValues); } if (currentConfig.Expected != null && currentConfig.ExpectedState != null) { throw new InvalidOperationException("Expected and ExpectedState cannot be set at the same time"); } if (currentConfig.Expected != null) { req.Expected = currentConfig.Expected.ToExpectedAttributeMap(); } if (currentConfig.ExpectedState != null && currentConfig.ExpectedState.ExpectedValues != null && currentConfig.ExpectedState.ExpectedValues.Count > 0) { req.Expected = currentConfig.ExpectedState.ToExpectedAttributeMap(); if (req.Expected.Count > 1) { req.ConditionalOperator = EnumMapper.Convert(currentConfig.ExpectedState.ConditionalOperator); } } var attributes = DDBClient.DeleteItem(req).Attributes; Document ret = null; if (currentConfig.ReturnValues == ReturnValues.AllOldAttributes) { ret = Document.FromAttributeMap(attributes); } return(ret); }
public async Task <APIGatewayProxyResponse> OnConnectHandler(APIGatewayProxyRequest request, ILambdaContext context) { try { var connectionId = request.RequestContext.ConnectionId; context.Logger.LogLine($"ConnectionId: {connectionId}"); var ddbRequest = new PutItemRequest { TableName = ConnectionMappingTable, Item = new Dictionary <string, AttributeValue> { { ConnectionIdField, new AttributeValue { S = connectionId } } } }; await DDBClient.PutItemAsync(ddbRequest); return(new APIGatewayProxyResponse { StatusCode = 200, Body = "Connected." }); } catch (Exception e) { context.Logger.LogLine("Error connecting: " + e.Message); context.Logger.LogLine(e.StackTrace); return(new APIGatewayProxyResponse { StatusCode = 500, Body = $"Failed to connect: {e.Message}" }); } }
public async Task <APIGatewayProxyResponse> SendMessageHandler(APIGatewayProxyRequest request, ILambdaContext context) { try { // Construct the API Gateway endpoint that incoming message will be broadcasted to. var domainName = request.RequestContext.DomainName; var stage = request.RequestContext.Stage; var endpoint = $"https://{domainName}/{stage}"; context.Logger.LogLine($"API Gateway management endpoint: {endpoint}"); // The body will look something like this: {"message":"sendmessage", "data":"What are you doing?"} JsonDocument message = JsonDocument.Parse(request.Body); // Grab the data from the JSON body which is the message to broadcasted. JsonElement dataProperty; if (!message.RootElement.TryGetProperty("data", out dataProperty)) { context.Logger.LogLine("Failed to find data element in JSON document"); return(new APIGatewayProxyResponse { StatusCode = (int)HttpStatusCode.BadRequest }); } var data = dataProperty.GetString(); var stream = new MemoryStream(UTF8Encoding.UTF8.GetBytes(data)); // List all of the current connections. In a more advanced use case the table could be used to grab a group of connection ids for a chat group. var scanRequest = new ScanRequest { TableName = ConnectionMappingTable, ProjectionExpression = ConnectionIdField }; var scanResponse = await DDBClient.ScanAsync(scanRequest); // Construct the IAmazonApiGatewayManagementApi which will be used to send the message to. var apiClient = ApiGatewayManagementApiClientFactory(endpoint); // Loop through all of the connections and broadcast the message out to the connections. var count = 0; foreach (var item in scanResponse.Items) { var postConnectionRequest = new PostToConnectionRequest { ConnectionId = item[ConnectionIdField].S, Data = stream }; try { context.Logger.LogLine($"Post to connection {count}: {postConnectionRequest.ConnectionId}"); stream.Position = 0; await apiClient.PostToConnectionAsync(postConnectionRequest); count++; } catch (AmazonServiceException e) { // API Gateway returns a status of 410 GONE then the connection is no // longer available. If this happens, delete the identifier // from our DynamoDB table. if (e.StatusCode == HttpStatusCode.Gone) { var ddbDeleteRequest = new DeleteItemRequest { TableName = ConnectionMappingTable, Key = new Dictionary <string, AttributeValue> { { ConnectionIdField, new AttributeValue { S = postConnectionRequest.ConnectionId } } } }; context.Logger.LogLine($"Deleting gone connection: {postConnectionRequest.ConnectionId}"); await DDBClient.DeleteItemAsync(ddbDeleteRequest); } else { context.Logger.LogLine($"Error posting message to {postConnectionRequest.ConnectionId}: {e.Message}"); context.Logger.LogLine(e.StackTrace); } } } return(new APIGatewayProxyResponse { StatusCode = (int)HttpStatusCode.OK, Body = "Data sent to " + count + " connection" + (count == 1 ? "" : "s") }); } catch (Exception e) { context.Logger.LogLine("Error disconnecting: " + e.Message); context.Logger.LogLine(e.StackTrace); return(new APIGatewayProxyResponse { StatusCode = (int)HttpStatusCode.InternalServerError, Body = $"Failed to send message: {e.Message}" }); } }
internal async Task <Document> UpdateHelperAsync(Document doc, Key key, UpdateItemOperationConfig config, CancellationToken cancellationToken) { var currentConfig = config ?? new UpdateItemOperationConfig(); // If the keys have been changed, treat entire document as having changed bool haveKeysChanged = HaveKeysChanged(doc); bool updateChangedAttributesOnly = !haveKeysChanged; var attributeUpdates = this.ToAttributeUpdateMap(doc, updateChangedAttributesOnly); foreach (var keyName in this.KeyNames) { attributeUpdates.Remove(keyName); } UpdateItemRequest req = new UpdateItemRequest { TableName = TableName, Key = key, AttributeUpdates = attributeUpdates.Count == 0 ? null : attributeUpdates, // pass null if keys-only update ReturnValues = EnumMapper.Convert(currentConfig.ReturnValues) }; this.AddRequestHandler(req, isAsync: true); ValidateConditional(currentConfig); if (currentConfig.Expected != null) { req.Expected = this.ToExpectedAttributeMap(currentConfig.Expected); } else if (currentConfig.ExpectedState != null && currentConfig.ExpectedState.ExpectedValues != null && currentConfig.ExpectedState.ExpectedValues.Count > 0) { req.Expected = currentConfig.ExpectedState.ToExpectedAttributeMap(this); if (req.Expected.Count > 1) { req.ConditionalOperator = EnumMapper.Convert(currentConfig.ExpectedState.ConditionalOperator); } } else if (currentConfig.ConditionalExpression != null && currentConfig.ConditionalExpression.IsSet) { currentConfig.ConditionalExpression.ApplyExpression(req, this); string statement; Dictionary <string, AttributeValue> expressionAttributeValues; Dictionary <string, string> expressionAttributeNames; Common.ConvertAttributeUpdatesToUpdateExpression(attributeUpdates, out statement, out expressionAttributeValues, out expressionAttributeNames); req.AttributeUpdates = null; req.UpdateExpression = statement; if (req.ExpressionAttributeValues == null) { req.ExpressionAttributeValues = expressionAttributeValues; } else { foreach (var kvp in expressionAttributeValues) { req.ExpressionAttributeValues.Add(kvp.Key, kvp.Value); } } if (req.ExpressionAttributeNames == null) { req.ExpressionAttributeNames = expressionAttributeNames; } else { foreach (var kvp in expressionAttributeNames) { req.ExpressionAttributeNames.Add(kvp.Key, kvp.Value); } } } var resp = await DDBClient.UpdateItemAsync(req, cancellationToken).ConfigureAwait(false); var returnedAttributes = resp.Attributes; doc.CommitChanges(); Document ret = null; if (currentConfig.ReturnValues != ReturnValues.None) { ret = this.FromAttributeMap(returnedAttributes); } return(ret); }
internal Document UpdateHelper(Document doc, Key key, UpdateItemOperationConfig config, bool isAsync) { var currentConfig = config ?? new UpdateItemOperationConfig(); // If the keys have been changed, treat entire document as having changed bool haveKeysChanged = HaveKeysChanged(doc); bool updateChangedAttributesOnly = !haveKeysChanged; var attributeUpdates = doc.ToAttributeUpdateMap(Conversion, updateChangedAttributesOnly); foreach (var keyName in this.KeyNames) { attributeUpdates.Remove(keyName); } UpdateItemRequest req = new UpdateItemRequest { TableName = TableName, Key = key, AttributeUpdates = attributeUpdates.Count == 0 ? null : attributeUpdates, // pass null if keys-only update ReturnValues = EnumMapper.Convert(currentConfig.ReturnValues) }; ((Amazon.Runtime.Internal.IAmazonWebServiceRequest)req).AddBeforeRequestHandler(isAsync ? new RequestEventHandler(UserAgentRequestEventHandlerAsync) : new RequestEventHandler(UserAgentRequestEventHandlerSync) ); ValidateConditional(currentConfig); if (currentConfig.Expected != null) { req.Expected = currentConfig.Expected.ToExpectedAttributeMap(Conversion); } else if (currentConfig.ExpectedState != null && currentConfig.ExpectedState.ExpectedValues != null && currentConfig.ExpectedState.ExpectedValues.Count > 0) { req.Expected = currentConfig.ExpectedState.ToExpectedAttributeMap(Conversion); if (req.Expected.Count > 1) { req.ConditionalOperator = EnumMapper.Convert(currentConfig.ExpectedState.ConditionalOperator); } } else if (currentConfig.ConditionalExpression != null && currentConfig.ConditionalExpression.IsSet) { currentConfig.ConditionalExpression.ApplyExpression(req, this.Conversion); string statement; Dictionary <string, AttributeValue> expressionAttributeValues; Dictionary <string, string> expressionAttributeNames; Common.ConvertAttributeUpdatesToUpdateExpression(attributeUpdates, out statement, out expressionAttributeValues, out expressionAttributeNames); req.AttributeUpdates = null; req.UpdateExpression = statement; if (req.ExpressionAttributeValues == null) { req.ExpressionAttributeValues = expressionAttributeValues; } else { foreach (var kvp in expressionAttributeValues) { req.ExpressionAttributeValues.Add(kvp.Key, kvp.Value); } } if (req.ExpressionAttributeNames == null) { req.ExpressionAttributeNames = expressionAttributeNames; } else { foreach (var kvp in expressionAttributeNames) { req.ExpressionAttributeNames.Add(kvp.Key, kvp.Value); } } } var resp = DDBClient.UpdateItem(req); var returnedAttributes = resp.Attributes; doc.CommitChanges(); Document ret = null; if (currentConfig.ReturnValues != ReturnValues.None) { ret = Document.FromAttributeMap(returnedAttributes); } return(ret); }
public async Task <APIGatewayProxyResponse> SendMessageHandler(APIGatewayProxyRequest request, ILambdaContext context) { try { // Construct the API Gateway endpoint that incoming message will be broadcasted to. var domainName = request.RequestContext.DomainName; var stage = request.RequestContext.Stage; var endpoint = $"https://{domainName}/{stage}"; var connectionId = request.RequestContext.ConnectionId; context.Logger.LogLine($"API Gateway management endpoint: {endpoint}"); JsonDocument message = JsonDocument.Parse(request.Body); // Grab the data from the JSON body which is the message to broadcasted. JsonElement dataProperty; if (!message.RootElement.TryGetProperty("data", out dataProperty)) { context.Logger.LogLine("Failed to find data element in JSON document"); return(new APIGatewayProxyResponse { StatusCode = (int)HttpStatusCode.BadRequest }); } var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true, }; ChatMessageRequest messageRequest = JsonSerializer.Deserialize <ChatMessageRequest>(dataProperty.ToString(), options); string date = (DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds.ToString(); await DDBUtils.PutMessage(messageRequest.Message, messageRequest.RoomID, messageRequest.UserID, date); ChatMessageResponse chatMsg = new ChatMessageResponse { Success = true, Message = messageRequest.Message, Date = date, Author = messageRequest.UserID, RoomId = messageRequest.RoomID }; string data = JsonSerializer.Serialize(chatMsg); var stream = new MemoryStream(UTF8Encoding.UTF8.GetBytes(data)); var queryRequest = new QueryRequest { TableName = RoomsConnectionsTable, KeyConditionExpression = "RoomId = :ri", ExpressionAttributeValues = new Dictionary <string, AttributeValue> { { ":ri", new AttributeValue { S = messageRequest.RoomID } } }, ProjectionExpression = "RoomId, ConnectionId" }; var queryResponse = await DDBClient.QueryAsync(queryRequest); // Construct the IAmazonApiGatewayManagementApi which will be used to send the message to. var apiClient = ApiGatewayManagementApiClientFactory(endpoint); // Loop through all of the connections and broadcast the message out to the connections. var count = 0; foreach (var item in queryResponse.Items) { var postConnectionRequest = new PostToConnectionRequest { ConnectionId = item["ConnectionId"].S, Data = stream }; try { context.Logger.LogLine($"Post to connection {count}: {postConnectionRequest.ConnectionId}"); stream.Position = 0; await apiClient.PostToConnectionAsync(postConnectionRequest); count++; } catch (AmazonServiceException e) { // API Gateway returns a status of 410 GONE then the connection is no // longer available. If this happens, delete the identifier // from our DynamoDB table. if (e.StatusCode == HttpStatusCode.Gone) { var ddbDeleteRequest = new DeleteItemRequest { TableName = RoomsConnectionsTable, Key = new Dictionary <string, AttributeValue> { { "RoomId", new AttributeValue { S = item["RoomId"].S } }, { "ConnectionId", new AttributeValue { S = postConnectionRequest.ConnectionId } } } }; context.Logger.LogLine($"Deleting gone connection: {postConnectionRequest.ConnectionId}"); await DDBClient.DeleteItemAsync(ddbDeleteRequest); } else { context.Logger.LogLine($"Error posting message to {postConnectionRequest.ConnectionId}: {e.Message}"); context.Logger.LogLine(e.StackTrace); } } } return(new APIGatewayProxyResponse { StatusCode = (int)HttpStatusCode.OK, Body = "Data sent to " + count + " connection" + (count == 1 ? "" : "s") }); } catch (Exception e) { context.Logger.LogLine("Error sending message: " + e.Message); context.Logger.LogLine(e.StackTrace); return(new APIGatewayProxyResponse { StatusCode = (int)HttpStatusCode.InternalServerError, Body = $"Failed to send message: {e.Message}" }); } }
public async Task <APIGatewayProxyResponse> LoginHandler(APIGatewayProxyRequest request, ILambdaContext context) { try { var connectionId = request.RequestContext.ConnectionId; var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true, }; LoginRequest logRequest = JsonSerializer.Deserialize <LoginRequest>(request.Body, options); var ddbRequest = new PutItemRequest { TableName = UsersRoomsTable, Item = new Dictionary <string, AttributeValue> { { "NodeId", new AttributeValue { S = "user-" + logRequest.UserID } }, { "TargetId", new AttributeValue { S = "user-" + logRequest.UserID } }, { "UserId", new AttributeValue { S = logRequest.UserID } } } }; await DDBUtils.AddUserToHisRooms(logRequest.UserID, connectionId); await DDBClient.PutItemAsync(ddbRequest); var customRoomsInfo = await DDBUtils.GetUserCustomRooms(logRequest.UserID); LoginResponse responseMsg = new LoginResponse() { Success = true, Users = await DDBUtils.GetAllUsers(), CustomRoomsNames = customRoomsInfo.Item1, CustomRoomsIds = customRoomsInfo.Item2 }; return(new APIGatewayProxyResponse { StatusCode = (int)HttpStatusCode.OK, Body = JsonSerializer.Serialize(responseMsg) }); } catch (Exception e) { context.Logger.LogLine("Error logging in: " + e.Message); context.Logger.LogLine(e.StackTrace); LoginResponse responseMsg = new LoginResponse() { Success = false }; return(new APIGatewayProxyResponse { StatusCode = (int)HttpStatusCode.InternalServerError, Body = JsonSerializer.Serialize(responseMsg) }); } }