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); }
public async Task <APIGatewayProxyResponse> OnDisconnectHandler(APIGatewayProxyRequest request, ILambdaContext context) { try { var connectionId = request.RequestContext.ConnectionId; context.Logger.LogLine($"ConnectionId: {connectionId}"); var ddbRequest = new DeleteItemRequest { TableName = ConnectionMappingTable, Key = new Dictionary <string, AttributeValue> { { ConnectionIdField, new AttributeValue { S = connectionId } } } }; await DDBClient.DeleteItemAsync(ddbRequest); return(new APIGatewayProxyResponse { StatusCode = 200, Body = "Disconnected." }); } catch (Exception e) { context.Logger.LogLine("Error disconnecting: " + e.Message); context.Logger.LogLine(e.StackTrace); return(new APIGatewayProxyResponse { StatusCode = 500, Body = $"Failed to disconnect: {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}" }); } }
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}" }); } }