Jak zaimplementować zdejmowanie chatbanów po 2 godzinach

0

Czat, a więc hub SignalR. Kod wygląda mniej więcej tak:

namespace Mon.Chat
{
    public class ChatHub : Hub
    {
        private readonly UserManager<ApplicationUser> userManager;
        private readonly SignInManager<ApplicationUser> signInManager;
        public ChatHub(UserManager<ApplicationUser> userManager, SignInManager<ApplicationUser> signInManager)
        {
            this.userManager = userManager;
            this.signInManager = signInManager;
        }

        [Authorize]
        public async Task SendChatMessage(string message)
        {
            var user = await userManager.GetUserAsync(Context.User);
            if (await userManager.IsInRoleAsync(user, "Muted")) return;

            if (message.Length == 0 || message.Length > 140) return;

            await Clients.All.SendAsync("ReceiveChatMessage", Context.User.Identity.Name, message);
        }

        [Authorize]
        public async Task Mute(string username)
        {
            var user = await userManager.GetUserAsync(Context.User);
            if (!await userManager.IsInRoleAsync(user, "Mod")) return;

            var bannedUser = await userManager.FindByNameAsync(username);
            if(bannedUser == null) return;

            await userManager.AddToRoleAsync(bannedUser, "Muted");

            // 2 min nie 2 h dla celów testowych
            var timer = new Timer () { Interval = 2 * 1000, AutoReset = false };
            timer.Elapsed += async (sender, e) =>
            {
                var unbannedUser = await userManager.FindByNameAsync(username);
                userManager.RemoveFromRoleAsync(unbannedUser, "Muted");
            };
            timer.Start();*/
        }
    }
}

Ten kod rzuca wyjątkami za każdym razem, gdy lambda w timerze próbuje użyć userManager. A więc problem jest w tych kilku linijkach:

timer.Elapsed += async (sender, e) =>
{
    var unbannedUser = await userManager.FindByNameAsync(username);
    userManager.RemoveFromRoleAsync(unbannedUser, "Muted");
};

Wyjątek, który leci, to System.ObjectDisposedException: 'Cannot access a disposed object.' I rzeczywiście: w debuggerze widzimy, że userManager jest już disposed.

Domyślam się, że dzieje się to: Czas życia huba kończy się, gdy metoda Mute zwraca. Ichni mechanizm dependency injection wywołuje Dispose na wszystkich zależnościach huba natychmiast, gdy jego czas życia się kończy:

The container calls Dispose for the IDisposable types it creates.

Timer jest wołany już potem, zatem leci wyjątek.

Zakładając, że pomysł z timerem jest OK - JAK mam to zrobić?! A może w ogóle pomysł z Timerem jest zły, i trzeba to jakoś inaczej zrobić?

Mam 3 pomysły, ale obawiam się, że wszystkie 3 błędne.

1

Nie prościej zapisać datetime/timespan do kiedy jest zmutowany?
Albo kiedy został zmutowany i na ile za pomocą timespana. Później dodajesz 'od kiedy' do 'czas trwania i porównujesz date do aktualnej.

0
Sunnyline2 napisał(a):

Nie prościej zapisać datetime/timespan do kiedy jest zmutowany?
Albo kiedy został zmutowany i na ile za pomocą timespana. Później dodajesz 'od kiedy' do 'czas trwania i porównujesz date do aktualnej.

No ale ja chcę jeszcze wysłać na chat info, że "XXX's mute has expired"

0

próbowałeś utworzyć lokalną kopię userManagera?

1 użytkowników online, w tym zalogowanych: 0, gości: 1