-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Consumer and service for update status sms (#409)
* Consumer and service for update status sms * Fixed codesmells * re-wrote get tests * fixed code smell * Update src/Altinn.Notifications.Core/Models/Notification/EmailSendOperationResult.cs Co-authored-by: Stephanie Buadu <47737608+acn-sbuad@users.noreply.github.com> * Removed nullable from SmsSendOperationResult * Update test/Altinn.Notifications.IntegrationTests/Notifications/EmailNotificationsController/GetTests.cs * Add test for invalid SmsSendOperationResult * Adjust test for failed parsing --------- Co-authored-by: acn-sbuad <stephanie.buadu@avanade.com> Co-authored-by: Stephanie Buadu <47737608+acn-sbuad@users.noreply.github.com>
- Loading branch information
1 parent
1c61702
commit 682f951
Showing
16 changed files
with
311 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
71 changes: 71 additions & 0 deletions
71
src/Altinn.Notifications.Core/Models/Notification/SmsSendOperationResult.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
using System.Text.Json; | ||
|
||
using Altinn.Notifications.Core.Enums; | ||
|
||
namespace Altinn.Notifications.Core.Models.Notification; | ||
|
||
/// <summary> | ||
/// A class representing a sms send operation update object | ||
/// </summary> | ||
public class SmsSendOperationResult | ||
{ | ||
/// <summary> | ||
/// The notification id | ||
/// </summary> | ||
public Guid NotificationId { get; set; } | ||
|
||
/// <summary> | ||
/// The reference to the delivery in sms gateway | ||
/// </summary> | ||
public string GatewayReference { get; set; } = string.Empty; | ||
|
||
/// <summary> | ||
/// The sms send result | ||
/// </summary> | ||
public SmsNotificationResultType SendResult { get; set; } | ||
|
||
/// <summary> | ||
/// Json serializes the <see cref="SmsSendOperationResult"/> | ||
/// </summary> | ||
public string Serialize() | ||
{ | ||
return JsonSerializer.Serialize(this, JsonSerializerOptionsProvider.Options); | ||
} | ||
|
||
/// <summary> | ||
/// Deserialize a json string into the <see cref="SmsSendOperationResult"/> | ||
/// </summary> | ||
public static SmsSendOperationResult? Deserialize(string serializedString) | ||
{ | ||
return JsonSerializer.Deserialize<SmsSendOperationResult>( | ||
serializedString, JsonSerializerOptionsProvider.Options); | ||
} | ||
|
||
/// <summary> | ||
/// Try to parse a json string into a<see cref="SmsSendOperationResult"/> | ||
/// </summary> | ||
public static bool TryParse(string input, out SmsSendOperationResult value) | ||
{ | ||
SmsSendOperationResult? parsedOutput; | ||
value = new SmsSendOperationResult(); | ||
|
||
if (string.IsNullOrEmpty(input)) | ||
{ | ||
return false; | ||
} | ||
|
||
try | ||
{ | ||
parsedOutput = Deserialize(input!); | ||
|
||
value = parsedOutput!; | ||
return value.NotificationId != Guid.Empty; | ||
} | ||
catch | ||
{ | ||
// try parse, we simply return false if fails | ||
} | ||
|
||
return false; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
59 changes: 59 additions & 0 deletions
59
src/Altinn.Notifications.Integrations/Kafka/Consumers/SmsStatusConsumer.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
using Altinn.Notifications.Core.Integrations; | ||
using Altinn.Notifications.Core.Models.Notification; | ||
using Altinn.Notifications.Core.Services.Interfaces; | ||
using Altinn.Notifications.Integrations.Configuration; | ||
using Microsoft.Extensions.Logging; | ||
using Microsoft.Extensions.Options; | ||
|
||
namespace Altinn.Notifications.Integrations.Kafka.Consumers; | ||
|
||
/// <summary> | ||
/// Kafka consumer class for status messages about sms notifications | ||
/// </summary> | ||
public class SmsStatusConsumer : KafkaConsumerBase<SmsStatusConsumer> | ||
{ | ||
private readonly ISmsNotificationService _smsNotificationsService; | ||
private readonly IKafkaProducer _producer; | ||
private readonly string _retryTopicName; | ||
private readonly ILogger<SmsStatusConsumer> _logger; | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="SmsStatusConsumer"/> class. | ||
/// </summary> | ||
public SmsStatusConsumer( | ||
ISmsNotificationService smsNotificationsService, | ||
IKafkaProducer producer, | ||
IOptions<KafkaSettings> settings, | ||
ILogger<SmsStatusConsumer> logger) | ||
: base(settings, logger, settings.Value.SmsStatusUpdatedTopicName) | ||
{ | ||
_smsNotificationsService = smsNotificationsService; | ||
_producer = producer; | ||
_retryTopicName = settings.Value.SmsStatusUpdatedTopicName; | ||
_logger = logger; | ||
} | ||
|
||
/// <inheritdoc/> | ||
protected override Task ExecuteAsync(CancellationToken stoppingToken) | ||
{ | ||
return Task.Run(() => ConsumeMessage(ProcessStatus, RetryStatus, stoppingToken), stoppingToken); | ||
} | ||
|
||
private async Task ProcessStatus(string message) | ||
{ | ||
bool succeeded = SmsSendOperationResult.TryParse(message, out SmsSendOperationResult result); | ||
|
||
if (!succeeded) | ||
{ | ||
_logger.LogError("// SmsStatusConsumer // ProcessStatus // Deserialization of message failed. {Message}", message); | ||
return; | ||
} | ||
|
||
await _smsNotificationsService.UpdateSendStatus(result); | ||
} | ||
|
||
private async Task RetryStatus(string message) | ||
{ | ||
await _producer.ProduceAsync(_retryTopicName, message!); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
100 changes: 100 additions & 0 deletions
100
...ns.IntegrationTests/Notifications.Integrations/TestingConsumers/SmsStatusConsumerTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
using Altinn.Notifications.Core.Enums; | ||
using Altinn.Notifications.Core.Models.Notification; | ||
using Altinn.Notifications.Integrations.Kafka.Consumers; | ||
using Altinn.Notifications.IntegrationTests.Utils; | ||
using Microsoft.Extensions.Hosting; | ||
|
||
using Xunit; | ||
|
||
namespace Altinn.Notifications.IntegrationTests.Notifications.Integrations.TestingConsumers; | ||
|
||
public class SmsStatusConsumerTests : IAsyncLifetime | ||
{ | ||
private readonly string _statusUpdatedTopicName = Guid.NewGuid().ToString(); | ||
private readonly string _sendersRef = $"ref-{Guid.NewGuid()}"; | ||
|
||
[Fact] | ||
public async Task RunTask_ConfirmExpectedSideEffects() | ||
{ | ||
// Arrange | ||
Dictionary<string, string> vars = new() | ||
{ | ||
{ "KafkaSettings__SmsStatusUpdatedTopicName", _statusUpdatedTopicName }, | ||
{ "KafkaSettings__Admin__TopicList", $"[\"{_statusUpdatedTopicName}\"]" } | ||
}; | ||
|
||
using SmsStatusConsumer consumerService = (SmsStatusConsumer)ServiceUtil | ||
.GetServices(new List<Type>() { typeof(IHostedService) }, vars) | ||
.First(s => s.GetType() == typeof(SmsStatusConsumer))!; | ||
|
||
(_, SmsNotification notification) = await PostgreUtil.PopulateDBWithOrderAndSmsNotification(_sendersRef); | ||
|
||
SmsSendOperationResult sendOperationResult = new() | ||
{ | ||
NotificationId = notification.Id, | ||
SendResult = SmsNotificationResultType.Accepted, | ||
GatewayReference = Guid.NewGuid().ToString() | ||
}; | ||
|
||
await KafkaUtil.PublishMessageOnTopic(_statusUpdatedTopicName, sendOperationResult.Serialize()); | ||
|
||
// Act | ||
await consumerService.StartAsync(CancellationToken.None); | ||
await Task.Delay(10000); | ||
await consumerService.StopAsync(CancellationToken.None); | ||
|
||
// Assert | ||
string smsNotificationStatus = await SelectSmsNotificationStatus(notification.Id); | ||
Assert.Equal(SmsNotificationResultType.Accepted.ToString(), smsNotificationStatus); | ||
} | ||
|
||
[Fact] | ||
public async Task RunTask_ParseSmsSendOperationResult_StatusNotUpdated() | ||
{ | ||
// Arrange | ||
Dictionary<string, string> vars = new() | ||
{ | ||
{ "KafkaSettings__SmsStatusUpdatedTopicName", _statusUpdatedTopicName }, | ||
{ "KafkaSettings__Admin__TopicList", $"[\"{_statusUpdatedTopicName}\"]" } | ||
}; | ||
|
||
using SmsStatusConsumer consumerService = (SmsStatusConsumer)ServiceUtil | ||
.GetServices(new List<Type>() { typeof(IHostedService) }, vars) | ||
.First(s => s.GetType() == typeof(SmsStatusConsumer))!; | ||
|
||
(_, SmsNotification notification) = await PostgreUtil.PopulateDBWithOrderAndSmsNotification(_sendersRef); | ||
|
||
await KafkaUtil.PublishMessageOnTopic(_statusUpdatedTopicName, string.Empty); | ||
|
||
// Act | ||
await consumerService.StartAsync(CancellationToken.None); | ||
await Task.Delay(10000); | ||
await consumerService.StopAsync(CancellationToken.None); | ||
|
||
// Assert | ||
string smsNotificationStatus = await SelectSmsNotificationStatus(notification.Id); | ||
Assert.Equal(SmsNotificationResultType.New.ToString(), smsNotificationStatus); | ||
} | ||
|
||
public Task InitializeAsync() | ||
{ | ||
return Task.CompletedTask; | ||
} | ||
|
||
public async Task DisposeAsync() | ||
{ | ||
await Dispose(true); | ||
} | ||
|
||
protected virtual async Task Dispose(bool disposing) | ||
{ | ||
await PostgreUtil.DeleteOrderFromDb(_sendersRef); | ||
await KafkaUtil.DeleteTopicAsync(_statusUpdatedTopicName); | ||
} | ||
|
||
private static async Task<string> SelectSmsNotificationStatus(Guid notificationId) | ||
{ | ||
string sql = $"select result from notifications.smsnotifications where alternateid = '{notificationId}'"; | ||
return await PostgreUtil.RunSqlReturnOutput<string>(sql); | ||
} | ||
} |
Oops, something went wrong.