-
This commit is contained in:
@@ -309,6 +309,30 @@ public class CollaborationHub : Hub
|
||||
Console.WriteLine($"[Collaboration] DataSaved sent to others in room {roomKey}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sincronizza l'intero template con tutti gli altri collaboratori nella room
|
||||
/// Usato per sync efficienti - invia il template completo invece di richiedere reload dal server
|
||||
/// Supporta compressione opzionale per template grandi
|
||||
/// </summary>
|
||||
public async Task BroadcastTemplateSync(string roomKey, string templateJson, int version, bool compressed = false)
|
||||
{
|
||||
var senderId = Context.ConnectionId;
|
||||
Console.WriteLine($"[Collaboration] BroadcastTemplateSync from {senderId} for room {roomKey}, version {version}, size: {templateJson.Length} bytes, compressed: {compressed}");
|
||||
|
||||
UpdateUserActivity(senderId);
|
||||
|
||||
await Clients.OthersInGroup(roomKey).SendAsync("TemplateSync", new TemplateSyncMessage
|
||||
{
|
||||
TemplateJson = templateJson,
|
||||
SenderConnectionId = senderId,
|
||||
Version = version,
|
||||
Compressed = compressed,
|
||||
Timestamp = DateTime.UtcNow
|
||||
});
|
||||
|
||||
Console.WriteLine($"[Collaboration] TemplateSync broadcast complete for room {roomKey}");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Lifecycle
|
||||
@@ -517,6 +541,19 @@ public class DataSavedMessage
|
||||
public DateTime Timestamp { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Message for efficient template sync - sends full template JSON (compressed optional)
|
||||
/// Used for initial sync and full resync requests
|
||||
/// </summary>
|
||||
public class TemplateSyncMessage
|
||||
{
|
||||
public string TemplateJson { get; set; } = string.Empty;
|
||||
public string SenderConnectionId { get; set; } = string.Empty;
|
||||
public int Version { get; set; } // Incrementing version number for conflict detection
|
||||
public bool Compressed { get; set; } // Whether TemplateJson is base64-encoded gzip
|
||||
public DateTime Timestamp { get; set; }
|
||||
}
|
||||
|
||||
public class UserLeftMessage
|
||||
{
|
||||
public string ConnectionId { get; set; } = string.Empty;
|
||||
|
||||
@@ -12,19 +12,50 @@ public class DataHub : Hub
|
||||
/// </summary>
|
||||
public async Task NotifyDataChanged(string entityType, string action, object? data = null)
|
||||
{
|
||||
await Clients.Others.SendAsync("DataChanged", entityType, action, data);
|
||||
try
|
||||
{
|
||||
await Clients.Others.SendAsync("DataChanged", entityType, action, data);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"[DataHub] Error in NotifyDataChanged: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task OnConnectedAsync()
|
||||
{
|
||||
await base.OnConnectedAsync();
|
||||
Console.WriteLine($"Client connected: {Context.ConnectionId}");
|
||||
try
|
||||
{
|
||||
Console.WriteLine($"[DataHub] Client connecting: {Context.ConnectionId}");
|
||||
await base.OnConnectedAsync();
|
||||
Console.WriteLine($"[DataHub] Client connected: {Context.ConnectionId}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"[DataHub] Error in OnConnectedAsync: {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task OnDisconnectedAsync(Exception? exception)
|
||||
{
|
||||
await base.OnDisconnectedAsync(exception);
|
||||
Console.WriteLine($"Client disconnected: {Context.ConnectionId}");
|
||||
try
|
||||
{
|
||||
if (exception != null)
|
||||
{
|
||||
Console.WriteLine($"[DataHub] Client disconnected with error: {Context.ConnectionId} - {exception.Message}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"[DataHub] Client disconnected: {Context.ConnectionId}");
|
||||
}
|
||||
await base.OnDisconnectedAsync(exception);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"[DataHub] Error in OnDisconnectedAsync: {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,20 +19,23 @@ builder.Services.AddScoped<DemoDataService>();
|
||||
builder.Services.AddScoped<ReportGeneratorService>();
|
||||
builder.Services.AddSingleton<DataNotificationService>();
|
||||
|
||||
// SignalR
|
||||
builder.Services.AddSignalR()
|
||||
// SignalR - with increased message size for template sync (default is 32KB)
|
||||
builder.Services.AddSignalR(options =>
|
||||
{
|
||||
options.MaximumReceiveMessageSize = 1024 * 1024; // 1MB max message size
|
||||
})
|
||||
.AddJsonProtocol(options =>
|
||||
{
|
||||
options.PayloadSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles;
|
||||
options.PayloadSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
|
||||
});
|
||||
|
||||
// CORS - Allow credentials for SignalR
|
||||
// CORS - Allow credentials for SignalR (accepts any origin for external access)
|
||||
builder.Services.AddCors(options =>
|
||||
{
|
||||
options.AddPolicy("AllowFrontend", policy =>
|
||||
{
|
||||
policy.SetIsOriginAllowed(origin => new Uri(origin).Host == "localhost")
|
||||
policy.SetIsOriginAllowed(_ => true) // Permette qualsiasi origine
|
||||
.AllowAnyHeader()
|
||||
.AllowAnyMethod()
|
||||
.AllowCredentials();
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user