diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..fe1152b --- /dev/null +++ b/.dockerignore @@ -0,0 +1,30 @@ +**/.classpath +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/azds.yaml +**/bin +**/charts +**/docker-compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md +!**/.gitignore +!.git/HEAD +!.git/config +!.git/packed-refs +!.git/refs/heads/** \ No newline at end of file diff --git a/BlazorCanvas/BlazorCanvas.Server/BlazorCanvas.Server.csproj b/BlazorCanvas/BlazorCanvas.Server/BlazorCanvas.Server.csproj index 3d24c4c..b6f9e91 100644 --- a/BlazorCanvas/BlazorCanvas.Server/BlazorCanvas.Server.csproj +++ b/BlazorCanvas/BlazorCanvas.Server/BlazorCanvas.Server.csproj @@ -4,11 +4,15 @@ net8.0 enable enable + ffc728b4-a681-4404-8156-a09f59c957d3 + Linux + ..\.. + diff --git a/BlazorCanvas/BlazorCanvas.Server/Components/Data/CanvasService.cs b/BlazorCanvas/BlazorCanvas.Server/Components/Data/CanvasService.cs index 8142fe1..c7893c0 100644 --- a/BlazorCanvas/BlazorCanvas.Server/Components/Data/CanvasService.cs +++ b/BlazorCanvas/BlazorCanvas.Server/Components/Data/CanvasService.cs @@ -5,7 +5,6 @@ using Microsoft.AspNetCore.Components; using Microsoft.JSInterop; using Newtonsoft.Json.Linq; using Newtonsoft.Json; -using StackExchange.Redis; namespace BlazorCanvas.Server.Components.Data; @@ -14,15 +13,13 @@ namespace BlazorCanvas.Server.Components.Data; public class CanvasService { private Canvas2DContext? _currentCanvasContext; private IJSRuntime _jsRuntime; - private IConnectionMultiplexer _cache; - private ChannelMessageQueue _channel; + private IRedisService _redisService; private CanvasCommand _lastCommand = new(); private bool _is_started = false; - public CanvasService(IJSRuntime jsRuntime, IConnectionMultiplexer cache) { + public CanvasService(IJSRuntime jsRuntime, IRedisService redisService) { _jsRuntime = jsRuntime; - _cache = cache; - _channel = _cache.GetSubscriber().Subscribe(RedisChannel.Literal("lol")); + _redisService = redisService; } public string currentColor { get; set; } = "Black"; @@ -31,12 +28,13 @@ public class CanvasService { public ElementReference divCanvas { get; set; } public BECanvasComponent myCanvas { get; set; } = new(); - public async void Consume() { + /// + /// Version Pub/Sub + /// + public async void Subscribe() { CancellationToken cToken = new(); - while (!cToken.IsCancellationRequested) { - var mess = await _channel.ReadAsync(cToken); - var comm = JsonConvert.DeserializeObject(mess.Message); + var comm = await _redisService.Subscribe(cToken); if (comm is not null) Draw(comm); } @@ -60,7 +58,12 @@ public class CanvasService { _currentCanvasContext = await myCanvas.CreateCanvas2DAsync(); await _currentCanvasContext.ClearRectAsync(0, 0, 1920, 1080); } - await _currentCanvasContext.SetFillStyleAsync(command.Color); + try { + await _currentCanvasContext.SetFillStyleAsync(command.Color); + } catch (JSDisconnectedException e) { + Console.WriteLine(e.ToString()); + return; // Welp. + } await _currentCanvasContext.FillRectAsync(command.X, command.Y, command.PointSize, command.PointSize); } @@ -68,7 +71,7 @@ public class CanvasService { double mouseX = 0, mouseY = 0; if (!_is_started) { - Consume(); + Subscribe(); _is_started = true; } @@ -102,8 +105,8 @@ public class CanvasService { if (command.Equals(_lastCommand)) return; // Pour pas spammer des commandes si c'est pas pertinent. - - _cache.GetSubscriber().Publish(RedisChannel.Literal("lol"), JsonConvert.SerializeObject(command)); + + _redisService.Publish(command); //Draw(command); // Local diff --git a/BlazorCanvas/BlazorCanvas.Server/Components/Data/IRedisService.cs b/BlazorCanvas/BlazorCanvas.Server/Components/Data/IRedisService.cs new file mode 100644 index 0000000..3431d6b --- /dev/null +++ b/BlazorCanvas/BlazorCanvas.Server/Components/Data/IRedisService.cs @@ -0,0 +1,6 @@ +namespace BlazorCanvas.Server.Components.Data; + +public interface IRedisService { + public Task Subscribe(CancellationToken cToken); + public void Publish(CanvasCommand command); +} diff --git a/BlazorCanvas/BlazorCanvas.Server/Components/Data/RedisService.cs b/BlazorCanvas/BlazorCanvas.Server/Components/Data/RedisService.cs new file mode 100644 index 0000000..0993239 --- /dev/null +++ b/BlazorCanvas/BlazorCanvas.Server/Components/Data/RedisService.cs @@ -0,0 +1,36 @@ +using Newtonsoft.Json; +using StackExchange.Redis; + +namespace BlazorCanvas.Server.Components.Data; + +// https://developer.redis.com/develop/dotnet/streams/stream-basics/ + +public class RedisService: IRedisService { + private IConnectionMultiplexer _cache; + private ChannelMessageQueue _channel; + + public RedisService(IConnectionMultiplexer cache) { + _cache = cache; + _channel = _cache.GetSubscriber().Subscribe(RedisChannel.Literal("lol")); + } + + /// + /// Version Pub/Sub + /// + public async Task Subscribe(CancellationToken cToken) { + var mess = await _channel.ReadAsync(cToken); + var comm = JsonConvert.DeserializeObject(mess.Message); + if (comm is not null) + return comm; + else return null; + } + + /// + /// Version Pub/Sub + /// + /// + public async void Publish(CanvasCommand command) { + CanvasCommand cm = new(command); + await _cache.GetSubscriber().PublishAsync(_channel.Channel, JsonConvert.SerializeObject(cm)); + } +} diff --git a/BlazorCanvas/BlazorCanvas.Server/Dockerfile b/BlazorCanvas/BlazorCanvas.Server/Dockerfile new file mode 100644 index 0000000..469b266 --- /dev/null +++ b/BlazorCanvas/BlazorCanvas.Server/Dockerfile @@ -0,0 +1,26 @@ +#See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging. + +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base +USER app +WORKDIR /app +EXPOSE 8080 +EXPOSE 8081 + +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +ARG BUILD_CONFIGURATION=Release +WORKDIR /src +COPY ["BlazorCanvas/BlazorCanvas.Server/BlazorCanvas.Server.csproj", "BlazorCanvas/BlazorCanvas.Server/"] +COPY ["BlazorCanvas/BlazorCanvas.ServiceDefaults/BlazorCanvas.ServiceDefaults.csproj", "BlazorCanvas/BlazorCanvas.ServiceDefaults/"] +RUN dotnet restore "./BlazorCanvas/BlazorCanvas.Server/./BlazorCanvas.Server.csproj" +COPY . . +WORKDIR "/src/BlazorCanvas/BlazorCanvas.Server" +RUN dotnet build "./BlazorCanvas.Server.csproj" -c $BUILD_CONFIGURATION -o /app/build + +FROM build AS publish +ARG BUILD_CONFIGURATION=Release +RUN dotnet publish "./BlazorCanvas.Server.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "BlazorCanvas.Server.dll"] \ No newline at end of file diff --git a/BlazorCanvas/BlazorCanvas.Server/Program.cs b/BlazorCanvas/BlazorCanvas.Server/Program.cs index a3cb9d7..0cc9468 100644 --- a/BlazorCanvas/BlazorCanvas.Server/Program.cs +++ b/BlazorCanvas/BlazorCanvas.Server/Program.cs @@ -10,9 +10,12 @@ builder.AddServiceDefaults(); // Add services to the container. builder.Services.AddRazorComponents() .AddInteractiveServerComponents(); + builder.AddRedis("cache"); -builder.Services.AddScoped(); +builder.Services.AddTransient(); + +builder.Services.AddTransient(); var app = builder.Build(); @@ -27,7 +30,6 @@ if (!app.Environment.IsDevelopment()) } app.UseHttpsRedirection(); - app.UseStaticFiles(); app.UseAntiforgery(); diff --git a/BlazorCanvas/BlazorCanvas.Server/Properties/launchSettings.json b/BlazorCanvas/BlazorCanvas.Server/Properties/launchSettings.json index e907cb7..759a281 100644 --- a/BlazorCanvas/BlazorCanvas.Server/Properties/launchSettings.json +++ b/BlazorCanvas/BlazorCanvas.Server/Properties/launchSettings.json @@ -1,38 +1,49 @@ { - "$schema": "http://json.schemastore.org/launchsettings.json", - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:47589", - "sslPort": 44363 + "profiles": { + "http": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "dotnetRunMessages": true, + "applicationUrl": "http://localhost:5276" + }, + "https": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "dotnetRunMessages": true, + "applicationUrl": "https://localhost:7257;http://localhost:5276" + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" } }, - "profiles": { - "http": { - "commandName": "Project", - "dotnetRunMessages": true, - "launchBrowser": true, - "applicationUrl": "http://localhost:5276", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } + "Container (Dockerfile)": { + "commandName": "Docker", + "launchBrowser": true, + "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}", + "environmentVariables": { + "ASPNETCORE_HTTPS_PORTS": "8081", + "ASPNETCORE_HTTP_PORTS": "8080" }, - "https": { - "commandName": "Project", - "dotnetRunMessages": true, - "launchBrowser": true, - "applicationUrl": "https://localhost:7257;http://localhost:5276", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, - "IIS Express": { - "commandName": "IISExpress", - "launchBrowser": true, - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - } + "publishAllPorts": true, + "useSSL": true + } + }, + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:47589", + "sslPort": 44363 } } +} \ No newline at end of file