Base solution for your next web application

Activities of "mpineiro"

Hello, we are currently using version 6.3.0 We are in parallel carrying out a migration to the latest versions, but we are uncertain if these problems would be resolved or we will face the same situation.

10.3.0

Hola,

tenemos una aplicación corriendo en Net Zero con ABP y sobre una infraestructura de Docker en Azure bajo base de datos SQL Server también del Elastic Pool de Azure. Lo que observamos es que cada x tiempo, el consumo de CPU se mantiene en un nivel determinado, que no llega al límite para nada, en ese momento se genera el corte, luego de algunos minutos, cae el consumo de CPU de golpe y el sitio vuelve a responder.

Es un comportamiento muy extraño.

Les agradezco la ayuda que me puedan brindar.

Dear friends, for several days now we have been experiencing errors in queries to the abp tables, we see that many of them are not performant and what happens is that they end up with timeout errors. Is there any improvement to address this type of problems? ERROR|2024-04-19 17:36:38,542|39 |Command |Failed executing DbCommand (0ms) [Parameters=[@__ef_filter__p_0='?' (DbType = Boolean), @__ef_filter__CurrentTenantId_1='?' (DbType = Int32), @__tenantId_1='?' (DbType = Int32)], CommandType='Text', CommandTimeout='30']SELECT [a].[Id], [a].[CreationTime], [a].[CreatorUserId], [a].[LastModificationTime], [a].[LastModifierUserId], [a].[Name], [a].[TenantId], [a].[UserId], [a].[Value]FROM [AbpSettings] AS [a]WHERE ((@__ef_filter__p_0 = CAST(1 AS bit)) OR ([a].[TenantId] = @__ef_filter__CurrentTenantId_1)) AND ([a].[UserId] IS NULL AND ([a].[TenantId] = @__tenantId_1))ERROR|2024-04-19 17:36:38,542|78 |Command |Failed executing DbCommand (80,493ms) [Parameters=[@__ef_filter__p_0='?' (DbType = Boolean), @__tenancyName_0='?' (Size = 64)], CommandType='Text', CommandTimeout='30']SELECT TOP(1) [a].[Id], [a].[Ciudad], [a].[CodigoPostal], [a].[Comuna], [a].[CondicionIva], [a].[ConnectionString], [a].[ContactoApellido], [a].[ContactoCargo], [a].[ContactoMail], [a].[ContactoNombre], [a].[CreationTime], [a].[CreatorUserId], [a].[CustomCssId], [a].[DeleterUserId], [a].[DeletionTime], [a].[DocumentoFiscal], [a].[Domicilio], [a].[DomicilioFiscal], [a].[EditionId], [a].[EsPep], [a].[GranContribuyente], [a].[IsActive], [a].[IsDeleted], [a].[IsInTrialPeriod], [a].[IsTemplate], [a].[LastModificationTime], [a].[LastModifierUserId], [a].[LogoFileType], [a].[LogoId], [a].[Mail], [a].[Moneda], [a].[Name], [a].[Pais], [a].[Provincia], [a].[RazonSocial], [a].[Sector], [a].[SubscriptionEndDateUtc], [a].[SubscriptionPaymentType], [a].[Telefono], [a].[TenancyName], [a].[Web]FROM [AbpTenants] AS [a]WHERE ((@__ef_filter__p_0 = CAST(1 AS bit)) OR ([a].[IsDeleted] <> CAST(1 AS bit))) AND ([a].[TenancyName] = @__tenancyName_0)ERROR|2024-04-19 17:36:38,542|32 |Command |Failed executing DbCommand (80,445ms) [Parameters=[@__ef_filter__p_0='?' (DbType = Boolean), @__p_0='?' (DbType = Int32)], CommandType='Text', CommandTimeout='30']SELECT TOP(1) [a].[Id], [a].[Ciudad], [a].[CodigoPostal], [a].[Comuna], [a].[CondicionIva], [a].[ConnectionString], [a].[ContactoApellido], [a].[ContactoCargo], [a].[ContactoMail], [a].[ContactoNombre], [a].[CreationTime], [a].[CreatorUserId], [a].[CustomCssId], [a].[DeleterUserId], [a].[DeletionTime], [a].[DocumentoFiscal], [a].[Domicilio], [a].[DomicilioFiscal], [a].[EditionId], [a].[EsPep], [a].[GranContribuyente], [a].[IsActive], [a].[IsDeleted], [a].[IsInTrialPeriod], [a].[IsTemplate], [a].[LastModificationTime], [a].[LastModifierUserId], [a].[LogoFileType], [a].[LogoId], [a].[Mail], [a].[Moneda], [a].[Name], [a].[Pais], [a].[Provincia], [a].[RazonSocial], [a].[Sector], [a].[SubscriptionEndDateUtc], [a].[SubscriptionPaymentType], [a].[Telefono], [a].[TenancyName], [a].[Web]FROM [AbpTenants] AS [a]WHERE ((@__ef_filter__p_0 = CAST(1 AS bit)) OR ([a].[IsDeleted] <> CAST(1 AS bit))) AND ([a].[Id] = @__p_0)ERROR|2024-04-19 17:36:38,835|155 |Command |Failed executing DbCommand (0ms) [Parameters=[@__ef_filter__p_0='?' (DbType = Boolean), @__ef_filter__p_1='?' (DbType = Boolean), @__ef_filter__CurrentTenantId_2='?' (DbType = Int32), @__p_0='?' (DbType = Int64)], CommandType='Text', CommandTimeout='30']SELECT TOP(1) [a].[Id], [a].[AccessFailedCount], [a].[AuthenticationSource], [a].[ConcurrencyStamp], [a].[CreationTime], [a].[CreatorUserId], [a].[DeleterUserId], [a].[DeletionTime], [a].[EmailAddress], [a].[EmailConfirmationCode], [a].[GoogleAuthenticatorKey], [a].[IsActive], [a].[IsDeleted], [a].[IsEmailConfirmed], [a].[IsExternalUser], [a].[IsLockoutEnabled], [a].[IsPhoneNumberConfirmed], [a].[IsTwoFactorEnabled], [a].[LastModificationTime], [a].[LastModifierUserId], [a].[LockoutEndDateUtc], [a].[Name], [a].[NormalizedEmailAddress], [a].[NormalizedUserName], [a].[Password], [a].[PasswordResetCode], [a].[PhoneNumber], [a].[ProfilePictureId], [a].[SecurityStamp], [a].[ShouldChangePasswordOnNextLogin], [a].[SignInToken], [a].[SignInTokenExpireTimeUtc], [a].[Surname], [a].[TenantId], [a].[UserName]FROM [AbpUsers] AS [a]WHERE (((@__ef_filter__p_0 = CAST(1 AS bit)) OR ([a].[IsDeleted] <> CAST(1 AS bit))) AND ((@__ef_filter__p_1 = CAST(1 AS bit)) OR ([a].[TenantId] = @__ef_filter__CurrentTenantId_2))) AND ([a].[Id] = @__p_0)ERROR|2024-04-19 17:36:38,982|123 |Command |Failed executing DbCommand (0ms) [Parameters=[@__ef_filter__p_0='?' (DbType = Boolean), @__ef_filter__p_1='?' (DbType = Boolean), @__ef_filter__CurrentTenantId_2='?' (DbType = Int32), @__p_0='?' (DbType = Int64)], CommandType='Text', CommandTimeout='30']SELECT TOP(1) [a].[Id], [a].[AccessFailedCount], [a].[AuthenticationSource], [a].[ConcurrencyStamp], [a].[CreationTime], [a].[CreatorUserId], [a].[DeleterUserId], [a].[DeletionTime], [a].[EmailAddress], [a].[EmailConfirmationCode], [a].[GoogleAuthenticatorKey], [a].[IsActive], [a].[IsDeleted], [a].[IsEmailConfirmed], [a].[IsExternalUser], [a].[IsLockoutEnabled], [a].[IsPhoneNumberConfirmed], [a].[IsTwoFactorEnabled], [a].[LastModificationTime], [a].[LastModifierUserId], [a].[LockoutEndDateUtc], [a].[Name], [a].[NormalizedEmailAddress], [a].[NormalizedUserName], [a].[Password], [a].[PasswordResetCode], [a].[PhoneNumber], [a].[ProfilePictureId], [a].[SecurityStamp], [a].[ShouldChangePasswordOnNextLogin], [a].[SignInToken], [a].[SignInTokenExpireTimeUtc], [a].[Surname], [a].[TenantId], [a].[UserName]FROM [AbpUsers] AS [a]WHERE (((@__ef_filter__p_0 = CAST(1 AS bit)) OR ([a].[IsDeleted] <> CAST(1 AS bit))) AND ((@__ef_filter__p_1 = CAST(1 AS bit)) OR ([a].[TenantId] = @__ef_filter__CurrentTenantId_2))) AND ([a].[Id] = @__p_0)ERROR|2024-04-19 17:36:39,145|39 |Query |An exception occurred while iterating over the results of a query for context type 'Worldsys.Compliance.EntityFrameworkCore.ComplianceDbContext'.System.Threading.Tasks.TaskCanceledException: A task was canceled.

Answer

Hi @ismcagdas,

I will send the email. Thank you

Question

Hello, I would like to know if you have a service to upgrade our current version of ASP. NET ZERO and ABP. Our current versions are: 10.3.0 -> Asp Net Zero 6.3 -> Abp

If you have a service of this type, I ask for costs and times for said upgrade.

Thank you so much I await your response soon Greetings

Hello ismcagdas,

It seems to be working fine after adding the replaceService line and the RedisOnlineClientStore file.

Thanks!

Hello ismcagdas,

We have tried to upgrade the whole platform version, from net 5 to net 7, including angular and abp, but it didn't end up working properly, so we decided to move on with other tasks, and resume the upgrade when we have the code more separated.

Would there be a way to apply the changes to these files in another way, for example using something like ReplaceServices or something like that?

Hi,

This all seems fine. Could you create a class by copying the code of https://github.com/aspnetboilerplate/aspnetboilerplate/blob/dev/src/Abp.AspNetCore.SignalR/AspNetCore/SignalR/Notifications/SignalRRealTimeNotifier.cs and then replace SignalRRealTimeNotifier with your CustomSignalRRealTimeNotifier and then add logs to understand if line below is called;

await signalRClient.SendAsync("getNotification", userNotification);

In order to replace SignalRRealTimeNotifier, you can do it as shown below;

Configuration.ReplaceService<IRealTimeNotifier, CustomSignalRRealTimeNotifier>(DependencyLifeStyle.Transient); 

Hello ismcagdas,

I did the changes you said, and i could see that when im triggering a notification from the front to backend, the onlineClients in the CustomSignalRRealTimeNotifier.cs file have values, meanwhile if i trigger the notification from worker to backend, this onlineClients is empty.

I tried applying this changes https://github.com/aspnetboilerplate/aspnetboilerplate/commit/b58d50ad5796da2cf1bf060fe791d33652700ba9 on the project, but i couldnt understand how to do it without modifying the abp files.

Thanks in advance

Hi,

Is it possible to share the request details of worker sending request to server ? I mean the JSON data.
If possible, it would be nice to test this on your app.

Hello ismcagdas,

I show you the method involved in this workflow

SendNotificationAsync (method in charge of sending the notification to the backend) - parameter CancellationToken is not used in this case

public async Task SendNotificationAsync(WorkerNotificationData notification, CancellationToken cancellationToken = default)
        {
            if (notification is null)
            {
                throw new ArgumentNullException(nameof(notification));
            }

            var baseUrl = BaseUri.AbsoluteUri;
            var url = new Uri(new Uri(baseUrl + (baseUrl.EndsWith("/") ? "" : "/")), "api/internals/notifications/v1/SendWorkerNotifications").ToString();
            
            var content = notification.SerializeToJson();
            var request = new HttpRequestMessage(HttpMethod.Post, new Uri(url))
            {
                Content = new StringContent(
                    content: content,
                    encoding: Encoding.UTF8,
                    mediaType: "application/json")
            };
            request.Headers.Add(UserAgentHeaderName, _userAgent);

            using var client = new HttpClient();
            using var response = await client.SendAsync(request, cancellationToken);
        }

SendWorkerNotifications endpoint in the backend

[UnitOfWork(IsDisabled = true)]
[HttpPost("SendWorkerNotifications")]
public async Task<IActionResult> SendWorkerNotifications(WorkerNotificationData notification)
{
    const string Target = TargetPrefix + "SendWorkerNotifications";
    
    if (notification.UserIds == null || notification.UserIds.Length == 0)
    {
        throw new ValidationException("Missing UserIds.");
    }
    if (string.IsNullOrWhiteSpace(notification.Message))
    {
        throw new ValidationException("Missing Message.");
    }

    UserIdentifier[] users = new UserIdentifier[notification.UserIds.Length];
    for (int i = 0; i < notification.UserIds.Length; i++)
    {
        users[i] = new UserIdentifier(notification.TenantId > 0 ? notification.TenantId : null, notification.UserIds[i]);
    }

    var data = new MessageNotificationData(notification.Message);
    if (notification.DownloadUrl.IsPresent())
    {
        data["downloadUrl"] = notification.DownloadUrl;
    }

    using (var uow = UnitOfWorkManager.Begin())
    using (var uowt = UnitOfWorkManager.Current.SetTenantId(notification.TenantId))
    {
        await _notificationPublisher.PublishAsync(
            notification.NotificationName,
            data: data,
            userIds: users,
            severity: notification.Severity);

        await uow.CompleteAsync();
    }

    return new OkResult();
}

WorkerNotificationData model

public class WorkerNotificationData
{
	/// <summary>
	/// Nombre de la notificación.
	/// </summary>
	public string NotificationName { get; set; }

	/// <summary>
	/// Mensaje a enviar.
	/// </summary>
	public string Message { get; set; }

	/// <summary>
	/// Suscriptor.
	/// </summary>
	public int TenantId { get; set; }

	/// <summary>
	/// Usuarios a los que que se envía la noificación.
	/// </summary>
	public long[] UserIds { get; set; } = Array.Empty<long>();

	/// <summary>
	/// Url opcional a incluir en la notificación.
	/// </summary>
	public string DownloadUrl { get; set; }

	/// <summary>
	/// Notification severity.
	/// </summary>
	public NotificationSeverity Severity { get; set; } = NotificationSeverity.Success;
}

Here are the headers and content of an example request:

{
  "Content-Length": "336",
  "Content-Type": "application/json; charset=utf-8",
  "Host": "localhost:44301",
  "User-Agent": "Worldsys.Compliance.Notifications.InternalNotificationClient/10.3.0.0"
}


{
  "notificationName": "Notification.BackgroundJob",
  "message": "La exportación está lista haz click aquí para descargar.",
  "tenantId": 184,
  "userIds": [
    551
  ],
  "downloadUrl": "/File/DownloadBinaryFile?id=1cddf33f-bfd9-1ceb-fe92-3a0d635c03e8&contentType=text/csv&fileName=Batch_2023-03-22T19_40_42.csv",
  "severity": "Success"
}

I have removed all the try catch statements to shorten the code in this answer.

Showing 1 to 10 of 24 entries