/// <summary> /// Creates a <see cref="Flow{TIn,TOut,TMat}"/> for ack grouped SQS messages using a <paramref name="client"/>. /// </summary> public static Flow <MessageAction, ISqsAckResultEntry, NotUsed> Grouped(IAmazonSQS client, string queueUrl, SqsAckGroupedSettings settings = null) { settings = settings ?? SqsAckGroupedSettings.Default; return(Flow.FromGraph(GraphDsl.Create(builder => { var p = builder.Add(new Partition <MessageAction>(3, action => { switch (action) { case Delete _: return 0; case ChangeMessageVisibility _: return 1; case Ignore _: return 2; default: throw new NotSupportedException($"Message of type [{action.GetType()}] is not supported by the Akka.Streams.SQS.SqsAckFlow.Grouped method."); } })); var merge = builder.Add(new Merge <ISqsAckResultEntry>(3)); var delete = builder.Add(Flow.Create <MessageAction>().Collect(a => a as Delete)); var changeMessageVisibility = builder.Add(Flow.Create <MessageAction>().Collect(a => a as ChangeMessageVisibility)); var ignore = builder.Add(Flow.Create <MessageAction>().Collect(a => a as Ignore)); builder.From(p.Out(0)).Via(delete).Via(GroupedDelete(client, queueUrl, settings).Select(x => (ISqsAckResultEntry)x)).To(merge.In(0)); builder.From(p.Out(1)).Via(changeMessageVisibility).Via(GroupedChangeMessageVisibility(client, queueUrl, settings).Select(x => (ISqsAckResultEntry)x)).To(merge.In(1)); builder.From(p.Out(2)).Via(ignore).Via(Flow.Create <Ignore>().Select(action => (ISqsAckResultEntry) new SqsIgnoreResultEntry(action))).To(merge.In(2)); return new FlowShape <MessageAction, ISqsAckResultEntry>(p.In, merge.Out); }))); }
public static Flow <Delete, SqsDeleteResultEntry, NotUsed> GroupedDelete(IAmazonSQS client, string queueUrl, SqsAckGroupedSettings settings = null) { settings = settings ?? SqsAckGroupedSettings.Default; return(Flow.Create <Delete>() .GroupedWithin(settings.MaxBatchSize, settings.MaxBatchWait) .Select(requests => { var entries = new List <DeleteMessageBatchRequestEntry>(); var actions = new List <Delete>(); var i = 0; foreach (var request in requests) { actions.Add(request); entries.Add(new DeleteMessageBatchRequestEntry(i.ToString(), request.Message.ReceiptHandle)); i++; } return Tuple.Create(actions, new DeleteMessageBatchRequest(queueUrl, entries)); }) .SelectAsync(settings.ConcurrentRequests, async tuple => { var actions = tuple.Item1; var request = tuple.Item2; var response = await client.DeleteMessageBatchAsync(request); if (response.Failed.Count == 0) { var responseMetadata = response.ResponseMetadata; var resultEntries = response.Successful.ToDictionary(e => int.Parse(e.Id), e => e); var results = new List <SqsDeleteResultEntry>(request.Entries.Count); var i = 0; foreach (var action in actions) { var result = resultEntries[i]; results.Add(new SqsDeleteResultEntry(action, result, responseMetadata)); i++; } return results; } else { var numberOfMessages = request.Entries.Count; var nrOfFailedMessages = response.Failed.Count; throw new SqsBatchException($"Some messages are failed to delete. {nrOfFailedMessages} of {numberOfMessages} messages are failed"); } }) .SelectMany(x => x)); }
/// <summary> /// Creates a <see cref="Sink{TIn,TMat}"/> for ack grouped SQS messages using a <paramref name="client"/>. /// </summary> public static Sink <MessageAction, Task> Grouped(IAmazonSQS client, string queueUrl, SqsAckGroupedSettings settings = null) => SqsAckFlow.Grouped(client, queueUrl, settings) .ToMaterialized(Sink.Ignore <ISqsAckResultEntry>(), Keep.Right);