Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Review debug reaction #155

Open
wants to merge 44 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 41 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
eeaa85a
wip
ruokun-niu Feb 7, 2025
cb98f9f
nit
ruokun-niu Feb 12, 2025
2de8ba0
react
ruokun-niu Feb 12, 2025
b497020
wip
ruokun-niu Feb 13, 2025
d0fb6fd
basic working
ruokun-niu Feb 17, 2025
c76b4ce
event stream adn query status
ruokun-niu Feb 18, 2025
f7efcf1
event stream done and added basic css
ruokun-niu Feb 18, 2025
5f3d793
updated file structure
ruokun-niu Feb 18, 2025
e72af17
Revert "updated file structure"
ruokun-niu Feb 18, 2025
4394cc9
updated file structure
ruokun-niu Feb 18, 2025
c46e8d1
sdk working
ruokun-niu Feb 19, 2025
2fec744
final
ruokun-niu Feb 19, 2025
5e613cc
updated reaction provider
ruokun-niu Feb 19, 2025
ec2d2de
nit and license
ruokun-niu Feb 19, 2025
ce914b2
Merge branch 'main' into review-debug-reaction
ruokun-niu Feb 19, 2025
fd70a9c
updated makefile and github workflows
ruokun-niu Feb 19, 2025
f7ae01b
rebase
ruokun-niu Feb 19, 2025
a458f80
css for sidebar and eventstream
ruokun-niu Feb 19, 2025
b8c7eb1
updated webapplication in debug reaction and SDK
ruokun-niu Feb 20, 2025
7399050
logging update
ruokun-niu Feb 20, 2025
c0705db
updated GET for the queries
ruokun-niu Feb 20, 2025
b06abaa
use resutlviewclient from the sdk
ruokun-niu Feb 21, 2025
6b4f8db
query container id update
ruokun-niu Feb 21, 2025
7936591
updated to use strongly typed models
ruokun-niu Feb 21, 2025
31e3559
interface for broadcaster
ruokun-niu Feb 21, 2025
22198b1
nit
ruokun-niu Feb 21, 2025
da796c3
remove comments
ruokun-niu Feb 21, 2025
5e59489
updated source rust dockerfiles
ruokun-niu Feb 21, 2025
380ba98
dotnet format
ruokun-niu Feb 28, 2025
0f70a2b
moved classes to separate files
ruokun-niu Mar 2, 2025
86dcb38
removed unused ExecuteAsync
ruokun-niu Mar 3, 2025
ae5842c
moved the stream state to the frontend
ruokun-niu Mar 3, 2025
8bf1c6a
moved queryreslt state to frontend;
ruokun-niu Mar 3, 2025
5ffb8f4
updated the mechanism for clearing the query reselt
ruokun-niu Mar 3, 2025
917a363
created websocketcontroller
ruokun-niu Mar 3, 2025
499521b
combined frontend and backend into one container
ruokun-niu Mar 4, 2025
007ccea
updated the logic for update and delete in the frontend
ruokun-niu Mar 4, 2025
d29a7e3
updated serialization
ruokun-niu Mar 4, 2025
84d6ecc
updated image ame
ruokun-niu Mar 4, 2025
2330f48
nit
ruokun-niu Mar 4, 2025
984c2ff
Merge branch 'main' into review-debug-reaction
ruokun-niu Mar 4, 2025
14f8ab8
updated build-test
ruokun-niu Mar 4, 2025
9f48ef4
Merge branch 'review-debug-reaction' of https://github.com/ruokun-niu…
ruokun-niu Mar 4, 2025
38f53db
removed the unused list for raw events in the backend
ruokun-niu Mar 10, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions .github/workflows/build-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -273,9 +273,14 @@ jobs:
name: 'reaction-debezium'
},
{
label: 'Debug',
path: './reactions/platform/debug-reaction',
name: 'reaction-debug'
label: 'Debug Frontend',
path: './reactions/platform/debug-reaction/debug-reaction.client',
name: 'reaction-debug-frontend'
},
{
label: 'Debug Backend',
path: './reactions/platform/debug-reaction/debug-reaction.Server',
name: 'reaction-debug-backend'
},
{
label: 'EventGrid',
Expand Down
2 changes: 1 addition & 1 deletion cli/service/resources/default-reaction-providers.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ spec:
services:
reaction:
image: reaction-result
dapr:
dapr:
app-port: "8080"
endpoints:
gateway:
Expand Down
32 changes: 7 additions & 25 deletions reactions/platform/debug-reaction/.dockerignore
Original file line number Diff line number Diff line change
@@ -1,25 +1,7 @@
**/.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
**/.classpath
**/.dockerignore
**/.env
**/.git
**/.gitignore
**/bin
**/obj
4 changes: 2 additions & 2 deletions reactions/platform/debug-reaction/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
bin
obj
/appsettings.Development.json
.vs
12 changes: 0 additions & 12 deletions reactions/platform/debug-reaction/App.razor

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Copyright 2025 The Drasi Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

namespace Drasi.Reactions.Debug.Server.Controllers;
using Microsoft.AspNetCore.Mvc;
using Drasi.Reactions.Debug.Server.Services;

[ApiController]
[Route("api/queries")]
public class QueryController : ControllerBase
{
private readonly IQueryDebugService _debugService;

private readonly string _configDirectory;

public QueryController(IQueryDebugService debugService, IConfiguration configuration)
{
_debugService = debugService;
_configDirectory = configuration.GetValue<string>("QueryConfigPath", "/etc/queries")!;
}

// GET queries
// This endpoint returns a list of active queries.
[HttpGet]
public IEnumerable<string> GetQueries()
{
var queryList = new List<string>();
foreach (var qpath in Directory.GetFiles(_configDirectory))
{
var queryId = Path.GetFileName(qpath);
queryList.Add(queryId);
}
return queryList;
}


// GET queries/{queryId}
// This endpoint returns the current result of a specific query.
[HttpGet("{queryId}")]
public async Task<IActionResult> GetQueryResult(string queryId)
{
var result = await _debugService.GetQueryResult(queryId);
return Ok(result);
}

// GET queries/{queryId}/debug-information
// This endpoint returns the debug information for a specific query.
[HttpGet("{queryId}/debug-information")]
public async Task<IActionResult> GetDebugInfo(string queryId)
{
var result = await _debugService.GetDebugInfo(queryId);
return Ok(result);
}
}
115 changes: 115 additions & 0 deletions reactions/platform/debug-reaction/Controllers/WebSocketController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// Copyright 2025 The Drasi Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.


using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System.Net.WebSockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Drasi.Reactions.Debug.Server.Models;
using Drasi.Reactions.Debug.Server.Services;


[Route("api/ws")]
public class WebSocketController : ControllerBase
{
private readonly IChangeBroadcaster _webSocketService;
private readonly ILogger<WebSocketController> _logger;

public WebSocketController(IChangeBroadcaster webSocketService, ILogger<WebSocketController> logger)
{
_webSocketService = webSocketService;
_logger = logger;
}

[Route("query/{queryId?}")]
public async Task Query(string? queryId)
{
if (!HttpContext.WebSockets.IsWebSocketRequest)
{
HttpContext.Response.StatusCode = StatusCodes.Status400BadRequest;
return;
}

if (string.IsNullOrEmpty(queryId))
{
using var webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync();
await webSocket.CloseAsync(WebSocketCloseStatus.InvalidPayloadData, "Invalid queryId", CancellationToken.None);
return;
}

using var webSocketQuery = await HttpContext.WebSockets.AcceptWebSocketAsync();
_webSocketService.AddConnection(queryId, webSocketQuery);
_logger.LogInformation($"WebSocket connected for queryId: {queryId}");

var buffer = new byte[1024 * 4];
var lastPingTime = DateTime.Now;

try
{
while (webSocketQuery.State == WebSocketState.Open)
{
var result = await webSocketQuery.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
if (result.MessageType == WebSocketMessageType.Close)
{
_logger.LogInformation($"WebSocket closing for queryId: {queryId}");
await webSocketQuery.CloseAsync(WebSocketCloseStatus.NormalClosure, "Client closed connection", CancellationToken.None);
return;
}
}
}
catch (Exception ex)
{
_logger.LogError(ex, $"WebSocket error for queryId: {queryId}");
await webSocketQuery.CloseAsync(WebSocketCloseStatus.InternalServerError, "Server error", CancellationToken.None);
}
}

[Route("stream")]
public async Task Stream()
{
if (!HttpContext.WebSockets.IsWebSocketRequest)
{
HttpContext.Response.StatusCode = StatusCodes.Status400BadRequest;
return;
}

using var webSocketStream = await HttpContext.WebSockets.AcceptWebSocketAsync();
_webSocketService.AddConnection("stream", webSocketStream);
_logger.LogInformation($"WebSocket connected for Event Stream");

var buffer = new byte[1024 * 4];

try
{
while (webSocketStream.State == WebSocketState.Open)
{
var result = await webSocketStream.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
if (result.MessageType == WebSocketMessageType.Close)
{
_logger.LogInformation($"WebSocket closing for Event Stream");
await webSocketStream.CloseAsync(WebSocketCloseStatus.NormalClosure, "Client closed connection", CancellationToken.None);
return;
}
}
}
catch (Exception ex)
{
_logger.LogError(ex, "WebSocket error for Event Stream");
await webSocketStream.CloseAsync(WebSocketCloseStatus.InternalServerError, "Server error", CancellationToken.None);
}
}
}
48 changes: 25 additions & 23 deletions reactions/platform/debug-reaction/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,28 @@
# See the License for the specific language governing permissions and
# limitations under the License.

#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.

FROM --platform=$TARGETPLATFORM mcr.microsoft.com/dotnet/aspnet@sha256:22414f335b79654fb42257326e7f17f18edf8f912578fc33a55c5dd609bd022e AS base
# mcr.microsoft.com/dotnet/aspnet:6.0
WORKDIR /app
EXPOSE 80

FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk@sha256:6df1177e48b55272316d08f19cb383483af82aca5cdc67a76c414bc200847624 AS build
# mcr.microsoft.com/dotnet/sdk:6.0
WORKDIR /src
COPY ["debug-reaction.csproj", "."]
RUN dotnet restore "./debug-reaction.csproj"
COPY . .
WORKDIR "/src/."
RUN dotnet build "debug-reaction.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "debug-reaction.csproj" -c Release -o /app/publish /p:UseAppHost=false

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "debug-reaction.dll"]
#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.

# Stage 1: Build React frontend
FROM node:18 AS frontend
WORKDIR /app/debug-reaction.client
COPY ./debug-reaction.client/package.json ./debug-reaction.client/package-lock.json ./
RUN npm install
COPY ./debug-reaction.client/ ./
RUN npm run build

# Stage 2: Build .NET backend
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS backend
WORKDIR /app/debug-reaction.Server
COPY ./debug-reaction.Server.csproj ./
RUN dotnet restore
COPY . ./
COPY --from=frontend /app/debug-reaction.client/dist ./wwwroot/
RUN dotnet publish -c Release -o /app/publish

# Stage 3: Run the app
FROM mcr.microsoft.com/dotnet/aspnet:8.0
WORKDIR /app
COPY --from=backend /app/publish .
EXPOSE 5195
ENTRYPOINT ["dotnet", "debug-reaction.Server.dll"]
9 changes: 7 additions & 2 deletions reactions/platform/debug-reaction/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.PHONY: default docker-build kind-load
.PHONY: default docker-build kind-load generate-types

CLUSTER_NAME ?= kind
IMAGE_PREFIX ?= drasi-project
Expand All @@ -17,4 +17,9 @@ test:
@echo "No tests to run yet"

lint-check:
@echo "No lint checks to run yet"
@echo "No lint checks to run yet"

generate-types:
npm run clean --prefix ../../../../typespec
npm run build ./output-unpacked --prefix ../../../../typespec
quicktype --src-lang schema -l cs -o Models/Unpacked.generated.cs ../../../../typespec/output-unpacked/_generated/@typespec/json-schema/*.yaml --framework SystemTextJson --namespace Drasi.Reactions.Debug.Servers.Models.Unpacked
Loading
Loading