Hatalar için düzenleme
This commit is contained in:
parent
bbd2f338b6
commit
879a54fcea
5 changed files with 58 additions and 36 deletions
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
using Volo.Abp.Domain.Entities.Auditing;
|
using Volo.Abp.Domain.Entities.Auditing;
|
||||||
|
|
||||||
namespace Kurs.Platform.Entities;
|
namespace Kurs.Platform.Entities;
|
||||||
|
|
@ -20,6 +21,7 @@ public class Classroom : FullAuditedEntity<Guid>
|
||||||
public int ParticipantCount { get; set; }
|
public int ParticipantCount { get; set; }
|
||||||
public string SettingsJson { get; set; }
|
public string SettingsJson { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
public virtual ICollection<ClassroomParticipant> Participants { get; set; }
|
public virtual ICollection<ClassroomParticipant> Participants { get; set; }
|
||||||
public virtual ICollection<ClassroomAttandance> AttendanceRecords { get; set; }
|
public virtual ICollection<ClassroomAttandance> AttendanceRecords { get; set; }
|
||||||
public virtual ICollection<ClassroomChat> ChatMessages { get; set; }
|
public virtual ICollection<ClassroomChat> ChatMessages { get; set; }
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
using Volo.Abp.Domain.Entities.Auditing;
|
using Volo.Abp.Domain.Entities.Auditing;
|
||||||
|
|
||||||
namespace Kurs.Platform.Entities;
|
namespace Kurs.Platform.Entities;
|
||||||
|
|
@ -12,7 +13,7 @@ public class ClassroomAttandance : FullAuditedEntity<Guid>
|
||||||
public DateTime? LeaveTime { get; set; }
|
public DateTime? LeaveTime { get; set; }
|
||||||
public int TotalDurationMinutes { get; set; }
|
public int TotalDurationMinutes { get; set; }
|
||||||
|
|
||||||
// Navigation properties
|
[JsonIgnore]
|
||||||
public virtual Classroom Session { get; set; }
|
public virtual Classroom Session { get; set; }
|
||||||
|
|
||||||
protected ClassroomAttandance()
|
protected ClassroomAttandance()
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
using Volo.Abp.Domain.Entities.Auditing;
|
using Volo.Abp.Domain.Entities.Auditing;
|
||||||
|
|
||||||
namespace Kurs.Platform.Entities;
|
namespace Kurs.Platform.Entities;
|
||||||
|
|
@ -15,7 +16,7 @@ public class ClassroomChat : FullAuditedEntity<Guid>
|
||||||
public bool IsTeacher { get; set; }
|
public bool IsTeacher { get; set; }
|
||||||
public string MessageType { get; set; }
|
public string MessageType { get; set; }
|
||||||
|
|
||||||
// Navigation properties
|
[JsonIgnore]
|
||||||
public virtual Classroom Session { get; set; }
|
public virtual Classroom Session { get; set; }
|
||||||
|
|
||||||
protected ClassroomChat()
|
protected ClassroomChat()
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
using Volo.Abp.Domain.Entities.Auditing;
|
using Volo.Abp.Domain.Entities.Auditing;
|
||||||
|
|
||||||
namespace Kurs.Platform.Entities;
|
namespace Kurs.Platform.Entities;
|
||||||
|
|
@ -17,7 +18,7 @@ public class ClassroomParticipant : FullAuditedEntity<Guid>
|
||||||
public DateTime JoinTime { get; set; }
|
public DateTime JoinTime { get; set; }
|
||||||
public string ConnectionId { get; set; }
|
public string ConnectionId { get; set; }
|
||||||
|
|
||||||
// Navigation properties
|
[JsonIgnore]
|
||||||
public virtual Classroom Session { get; set; }
|
public virtual Classroom Session { get; set; }
|
||||||
|
|
||||||
protected ClassroomParticipant()
|
protected ClassroomParticipant()
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ using Volo.Abp.Guids;
|
||||||
using Volo.Abp.Users;
|
using Volo.Abp.Users;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
using Volo.Abp.Uow;
|
||||||
|
|
||||||
namespace Kurs.Platform.Classrooms;
|
namespace Kurs.Platform.Classrooms;
|
||||||
|
|
||||||
|
|
@ -22,6 +23,7 @@ public class ClassroomHub : Hub
|
||||||
private readonly ILogger<ClassroomHub> _logger;
|
private readonly ILogger<ClassroomHub> _logger;
|
||||||
private readonly IGuidGenerator _guidGenerator;
|
private readonly IGuidGenerator _guidGenerator;
|
||||||
private readonly ICurrentUser _currentUser;
|
private readonly ICurrentUser _currentUser;
|
||||||
|
private readonly UnitOfWorkManager _unitOfWorkManager;
|
||||||
|
|
||||||
public ClassroomHub(
|
public ClassroomHub(
|
||||||
IRepository<Classroom, Guid> classSessionRepository,
|
IRepository<Classroom, Guid> classSessionRepository,
|
||||||
|
|
@ -30,7 +32,8 @@ public class ClassroomHub : Hub
|
||||||
IRepository<ClassroomAttandance, Guid> attendanceRepository,
|
IRepository<ClassroomAttandance, Guid> attendanceRepository,
|
||||||
ILogger<ClassroomHub> logger,
|
ILogger<ClassroomHub> logger,
|
||||||
IGuidGenerator guidGenerator,
|
IGuidGenerator guidGenerator,
|
||||||
ICurrentUser currentUser)
|
ICurrentUser currentUser,
|
||||||
|
UnitOfWorkManager unitOfWorkManager)
|
||||||
{
|
{
|
||||||
_classSessionRepository = classSessionRepository;
|
_classSessionRepository = classSessionRepository;
|
||||||
_participantRepository = participantRepository;
|
_participantRepository = participantRepository;
|
||||||
|
|
@ -39,6 +42,7 @@ public class ClassroomHub : Hub
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_guidGenerator = guidGenerator;
|
_guidGenerator = guidGenerator;
|
||||||
_currentUser = currentUser;
|
_currentUser = currentUser;
|
||||||
|
_unitOfWorkManager = unitOfWorkManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Helper Methods
|
#region Helper Methods
|
||||||
|
|
@ -392,7 +396,15 @@ public class ClassroomHub : Hub
|
||||||
|
|
||||||
// yalnızca diğer katılımcılar görebilsin
|
// yalnızca diğer katılımcılar görebilsin
|
||||||
await Clients.Group(sessionId.ToString())
|
await Clients.Group(sessionId.ToString())
|
||||||
.SendAsync("AttendanceUpdated", attendance);
|
.SendAsync("AttendanceUpdated", new {
|
||||||
|
attendance.Id,
|
||||||
|
attendance.SessionId,
|
||||||
|
attendance.StudentId,
|
||||||
|
attendance.StudentName,
|
||||||
|
attendance.JoinTime,
|
||||||
|
attendance.LeaveTime,
|
||||||
|
attendance.TotalDurationMinutes
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Participant bul
|
// 2. Participant bul
|
||||||
|
|
@ -512,7 +524,7 @@ public class ClassroomHub : Hub
|
||||||
.SendAsync("ReceiveIceCandidate", _currentUser.Id?.ToString(), candidate);
|
.SendAsync("ReceiveIceCandidate", _currentUser.Id?.ToString(), candidate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnitOfWork]
|
||||||
public override async Task OnDisconnectedAsync(Exception exception)
|
public override async Task OnDisconnectedAsync(Exception exception)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
@ -524,9 +536,11 @@ public class ClassroomHub : Hub
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.LogInformation("🔴 OnDisconnectedAsync: User={UserId}, ConnId={ConnId}, Exception={Exception}", userId, Context.ConnectionId, exception?.Message);
|
_logger.LogInformation("🔴 OnDisconnectedAsync: User={UserId}, ConnId={ConnId}, Exception={Exception}",
|
||||||
|
userId, Context.ConnectionId, exception?.Message);
|
||||||
|
|
||||||
// 🔑 Aynı anda birden fazla session olabilir (tab senaryosu)
|
// 🔑 Yeni scope aç (her disconnect için ayrı UoW)
|
||||||
|
using var uow = _unitOfWorkManager.Begin(requiresNew: true, isTransactional: true);
|
||||||
var participants = await _participantRepository
|
var participants = await _participantRepository
|
||||||
.GetListAsync(x => x.UserId == userId.Value && x.ConnectionId == Context.ConnectionId);
|
.GetListAsync(x => x.UserId == userId.Value && x.ConnectionId == Context.ConnectionId);
|
||||||
|
|
||||||
|
|
@ -537,17 +551,16 @@ public class ClassroomHub : Hub
|
||||||
|
|
||||||
foreach (var participant in participants)
|
foreach (var participant in participants)
|
||||||
{
|
{
|
||||||
_logger.LogInformation("OnDisconnectedAsync: User {UserId}, Session {SessionId} bağlantısı koptu.", userId, participant.SessionId);
|
_logger.LogInformation("OnDisconnectedAsync: User {UserId}, Session {SessionId} bağlantısı koptu.",
|
||||||
|
userId, participant.SessionId);
|
||||||
|
|
||||||
// 🔑 Attendance kapat
|
// 🔑 Attendance güncelle
|
||||||
var attendances = await _attendanceRepository.GetListAsync(
|
var attendances = await _attendanceRepository.GetListAsync(
|
||||||
x => x.SessionId == participant.SessionId &&
|
x => x.SessionId == participant.SessionId &&
|
||||||
x.StudentId == userId.Value &&
|
x.StudentId == userId.Value &&
|
||||||
x.LeaveTime == null
|
x.LeaveTime == null
|
||||||
);
|
);
|
||||||
|
|
||||||
if (attendances != null)
|
|
||||||
{
|
|
||||||
foreach (var attendance in attendances)
|
foreach (var attendance in attendances)
|
||||||
{
|
{
|
||||||
attendance.LeaveTime = DateTime.UtcNow;
|
attendance.LeaveTime = DateTime.UtcNow;
|
||||||
|
|
@ -557,6 +570,7 @@ public class ClassroomHub : Hub
|
||||||
);
|
);
|
||||||
await _attendanceRepository.UpdateAsync(attendance, autoSave: true);
|
await _attendanceRepository.UpdateAsync(attendance, autoSave: true);
|
||||||
|
|
||||||
|
// DTO gönder (entity yerine)
|
||||||
await Clients.Group(participant.SessionId.ToString())
|
await Clients.Group(participant.SessionId.ToString())
|
||||||
.SendAsync("AttendanceUpdated", new
|
.SendAsync("AttendanceUpdated", new
|
||||||
{
|
{
|
||||||
|
|
@ -569,9 +583,8 @@ public class ClassroomHub : Hub
|
||||||
attendance.TotalDurationMinutes
|
attendance.TotalDurationMinutes
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Eğer kullanıcı kick edilmemişse pasifleştir
|
// Eğer kick edilmemişse → pasif et
|
||||||
if (!participant.IsKicked)
|
if (!participant.IsKicked)
|
||||||
{
|
{
|
||||||
participant.IsActive = false;
|
participant.IsActive = false;
|
||||||
|
|
@ -579,10 +592,16 @@ public class ClassroomHub : Hub
|
||||||
await _participantRepository.UpdateAsync(participant, autoSave: true);
|
await _participantRepository.UpdateAsync(participant, autoSave: true);
|
||||||
|
|
||||||
await Clients.Group(participant.SessionId.ToString())
|
await Clients.Group(participant.SessionId.ToString())
|
||||||
.SendAsync("ParticipantLeft", new { UserId = userId.Value, SessionId = participant.SessionId });
|
.SendAsync("ParticipantLeft", new
|
||||||
|
{
|
||||||
|
UserId = userId.Value,
|
||||||
|
SessionId = participant.SessionId
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
// 🔑 Scope commit
|
||||||
|
await uow.CompleteAsync();
|
||||||
}
|
}
|
||||||
catch (TaskCanceledException)
|
catch (TaskCanceledException)
|
||||||
{
|
{
|
||||||
|
|
@ -597,8 +616,6 @@ public class ClassroomHub : Hub
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public class SignalingMessageDto
|
public class SignalingMessageDto
|
||||||
{
|
{
|
||||||
public string Type { get; set; } // offer, answer, ice-candidate
|
public string Type { get; set; } // offer, answer, ice-candidate
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue