Phase 8a-1: migrate health server to ASP.NET Core / Kestrel#14
Conversation
Phase 8a-1 of the file-relay feature (foundation for the upload/download web endpoints). No behavior change to /health — same JSON + status codes. - Add Microsoft.AspNetCore.App FrameworkReference (console app hosts Kestrel). - Replace HttpListener HealthService with a Kestrel WebService (WebApplication minimal API); maps GET /health (200 connected / 503 starting). Bind host '+'/'*' -> all interfaces for the container; 'localhost' for dev. - Dockerfile runtime base dotnet/runtime -> dotnet/aspnet (ASP.NET Core runtime). - Update CLAUDE.md. Next (8a-2): /upload slash command + uploads DB schema + link minting.
There was a problem hiding this comment.
Code review is billed via overage credits. To resume reviews, an organization admin can raise the monthly limit at claude.ai/admin-settings/claude-code.
Once credits are available, reopen this pull request to trigger a review.
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughSummary by CodeRabbit
WalkthroughReplaces the custom HttpListener-based HealthService with an ASP.NET Core Kestrel WebService started from Bot.StartBot; adds Microsoft.AspNetCore.App framework reference, switches Docker runtime to aspnet:10.0, and updates docs to describe the new WebService and image/runtime details. ChangesHealthService → WebService Migration
Sequence Diagram(s)sequenceDiagram
participant Bot
participant WebService
participant WebApp
participant HealthEndpoint
participant DiscordClient
participant Client
Bot->>WebService: Start()
WebService->>WebApp: Build and configure host binding
WebService->>WebApp: StartAsync()
Client->>HealthEndpoint: GET /health
HealthEndpoint->>DiscordClient: Read connection state and metrics
HealthEndpoint-->>Client: Return JSON with 200 or 503
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@Services/WebService.cs`:
- Around line 23-42: The Start method's catch currently only logs a warning and
nulls out app, leaving failures silent to orchestrators; update the Start method
(in class/method Start) to escalate startup bind/start errors: log at Error with
exception details and then fail fast by either rethrowing the exception or
terminating the process (e.g., set nonzero exit code / Environment.Exit) so
misconfiguration is observable; keep ConsoleLifetime behavior unchanged (do not
attempt to suppress it).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 249e89e0-db9f-4c71-a8d3-dcee20a2958d
📒 Files selected for processing (6)
Bot.csCLAUDE.mdDockerfileServices/HealthService.csServices/WebService.csWisbot.csproj
💤 Files with no reviewable changes (1)
- Services/HealthService.cs
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build
🧰 Additional context used
📓 Path-based instructions (3)
**/*.cs
📄 CodeRabbit inference engine (CLAUDE.md)
Use the
fieldkeyword for properties with logic to avoid manual backing fields in C# 14Use null-conditional assignment operator
?.=for defensive assignmentsUse the new
extensionkeyword for grouping extension members (properties, methods, and static members)Use primary constructors for classes and structs unless complex initialization logic is required
Always use
[]collection expression syntax for empty or populated collections/spans in C# 14Use file-scoped namespaces with
namespace MyProject.Models;syntax (no curly braces)Rely on implicit usings and do not include standard system imports unless unique
Use
varkeyword only when the type is obvious from the right side of the assignment; use explicit types for method returns or literalsUse expression-bodied members with
=>for simple one-line methods and propertiesPrefer
ReadOnlySpan<char>for string parsing and slicing to optimize performanceUse the
requiredkeyword for properties that must be initialized via object initializersUse raw string literals with
"""for multi-line strings or JSON to avoid escaping quotesUse PascalCase for Classes, Methods, Properties, and Public Fields
Use camelCase for local variables and method arguments
Avoid underscore prefixes for private fields (use the
fieldkeyword orthis.prefix if absolutely necessary)Use
Task.Run()fire-and-forget pattern after immediateRespondAsync()followed byFollowupAsync()for long Discord operations to avoid 3-second interaction timeoutUse
ConcurrentDictionaryandConcurrentQueuefor thread-safe data structures; uselockfor background service listsAll configuration settings must resolve via
Config.Load()from environment variable, local.envfile, or default—never hardcode site-specific values
Files:
Services/WebService.csBot.cs
Services/**/*.cs
📄 CodeRabbit inference engine (CLAUDE.md)
Use manual constructor Dependency Injection without a DI container
Each service should live in its own file under
Services/directory with Bot.cs owning instances and wiring events
Files:
Services/WebService.cs
Bot.cs
📄 CodeRabbit inference engine (CLAUDE.md)
Register slash commands idempotently on
OnReadyby checking if they already exist before creating
Files:
Bot.cs
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
Repo: uhstray-io/WisBot
Timestamp: 2026-06-02T13:44:10.404Z
Learning: Use `dotnet build` to validate changes after completing modifications
Learnt from: CR
Repo: uhstray-io/WisBot
Timestamp: 2026-06-02T13:44:10.404Z
Learning: Ensure code is well-structured, follows best practices, and includes appropriate error handling when making changes
Learnt from: CR
Repo: uhstray-io/WisBot
Timestamp: 2026-06-02T13:44:10.404Z
Learning: Update CLAUDE.md and/or README.md after completing changes to reflect modifications and provide clear documentation
Learnt from: CR
Repo: uhstray-io/WisBot
Timestamp: 2026-06-02T13:44:10.404Z
Learning: Read `.claude/memory/MEMORY.md` at the start of every session to load project context
Learnt from: CR
Repo: uhstray-io/WisBot
Timestamp: 2026-06-02T13:44:10.404Z
Learning: Use `.claude/memory/` for storing architectural decisions, team conventions, external references, and domain knowledge
🔇 Additional comments (6)
Dockerfile (1)
15-15: LGTM!CLAUDE.md (2)
18-18: LGTM!
41-41: LGTM!Services/WebService.cs (1)
48-59: LGTM!Wisbot.csproj (1)
9-14: LGTM!Bot.cs (1)
18-18: LGTM!Also applies to: 34-34, 46-46
Register a no-op IHostLifetime so the embedded web host doesn't grab SIGINT/ SIGTERM or drive process shutdown — the bot process (Program.cs) owns the lifetime. Prevents the web host's ConsoleLifetime from interfering with the bot's signal handling in the container.
Escalate the start-failure log Warn -> Error and rethrow, so a bind failure propagates to StartBot/Program (fatal exit) instead of silently running without the health/upload endpoint. The web endpoint is now essential to the service.
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
Phase 8a-1 — Kestrel foundation for the file-relay feature
First sub-phase of Phase 8 (the
/uploadfile relay, plan §9). Lays the web foundation by moving offHttpListener; no behavior change to/health.Changes
Wisbot.csproj— add<FrameworkReference Include="Microsoft.AspNetCore.App" />(the supported way for a console app to host Kestrel).Services/WebService.cs(replacesHealthService.cs) — KestrelWebApplicationminimal API;GET /healthreturns the same JSON (status,uptimeSeconds,latencyMs,guilds) with 200 (connected) / 503 (starting). Bind host+/*→ all interfaces (container);localhostfor dev. Ready to host the upload/download endpoints next.Bot.cs—webService = new WebService(...);await webService.Start()inStartBot.Dockerfile— runtime basedotnet/runtime:10.0→dotnet/aspnet:10.0.CLAUDE.mdupdated.Why now
Kestrel is the prerequisite for real web serving (multipart upload, 500MB streaming, routes) that
HttpListeneris poorly suited to. Doing it as an isolated, behavior-preserving step keeps the diff reviewable.Verification
dotnet build— succeeds, 0 warnings, 0 errors.docker-buildCI on this PR validates the newaspnetimage builds./healthruntime check happens in the container/deploy (as in Phase 2/3) — it requires a Discord token to reachWebService.Start().Next: 8a-2 (
/uploadcommand +uploadsDB schema + link minting), then 8a-3 (MinIO + streamed upload/download).