-
Notifications
You must be signed in to change notification settings - Fork 0
Bug Fixes #38
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
base: main
Are you sure you want to change the base?
Bug Fixes #38
Conversation
WalkthroughLicense changed from LGPL to AGPL; HTTP/httpz-based server replaced by a new TCP WebSocket server; graceful shutdown propagated via atomic flags; write path refactored to callback-based writer; nostr dependency bumped; log-level config and NIP 2 were added. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant TcpServer
participant Subscriptions
participant Handler
participant WriteQueue
Note over Client,TcpServer: New connection flow (HTTP upgrade → WebSocket)
Client->>TcpServer: HTTP Upgrade / WebSocket handshake
TcpServer->>Subscriptions: register connection (conn_id)
TcpServer->>Handler: spawn per-conn read loop (messages)
Client->>TcpServer: WebSocket Text Message (Nostr)
TcpServer->>Handler: deliver message for processing
Handler->>WriteQueue: enqueue reply (uses WriteFn callback)
WriteQueue->>TcpServer: invoke WriteFn(ctx, data)
TcpServer->>Client: send WebSocket frame
Note over TcpServer,Handler: Shutdown path
alt shutdown signaled
Handler->>TcpServer: stop accepting / cleanup
TcpServer->>Subscriptions: unregister connection
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 inconclusive)
✅ Passed checks (2 passed)
✨ Finishing touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/spider.zig (1)
120-134:closeClientis a no-op - connections won't be interruptedThe
stop()method iterates over relay connections and callscloseClient(), butcloseClient()at lines 956-958 does nothing (_ = self;). This means active websocket connections won't be forcibly closed during shutdown, and threads will only exit when they naturally timeout or encounter an error.🔎 Consider implementing closeClient:
fn closeClient(self: *RelayConn) void { - _ = self; + if (self.active_client) |client| { + client.close() catch {}; + } }Note: This requires the websocket client to support a
close()method. If not available, you may need to use a different approach such as setting a flag that the read loop checks.
🧹 Nitpick comments (6)
src/tcp_server.zig (3)
95-108: Consider using explicit flags for idempotent deinit.The capacity checks are fragile heuristics. A cleaner approach would use explicit boolean flags:
+ deinitialized: bool = false, + pub fn deinit(self: *TcpServer) void { + if (self.deinitialized) return; + self.deinitialized = true; + if (self.listener) |*l| { l.deinit(); self.listener = null; } - // Only deinit limiters if they haven't been freed - // This makes deinit idempotent - if (self.conn_limiter.ip_buckets.capacity() > 0) { - self.conn_limiter.deinit(); - } - if (self.ip_filter.whitelist.capacity() > 0) { - self.ip_filter.deinit(); - } + self.conn_limiter.deinit(); + self.ip_filter.deinit(); }
127-142: Detached threads may cause resource leaks on shutdown.Detached connection threads cannot be joined, and the fixed 200ms sleep may be insufficient for in-flight connections to complete cleanup. Consider using a tracked thread pool or wait group to ensure graceful shutdown:
// Alternative: track active connections with atomic counter active_connections: std.atomic.Value(u32) = std.atomic.Value(u32).init(0), // In handleConnection: _ = self.active_connections.fetchAdd(1, .monotonic); defer _ = self.active_connections.fetchSub(1, .monotonic); // In run() shutdown: while (self.active_connections.load(.acquire) > 0) { std.Thread.sleep(10 * std.time.ns_per_ms); }
337-343: IPv6 addresses will include brackets in the extracted IP.For IPv6 connections like
[2001:db8::1]:8080, this extracts[2001:db8::1](with brackets). This may cause issues with IP-based rate limiting if the same IP connects via different address formats. Consider stripping brackets for consistency:fn extractIp(address: net.Address, buf: []u8) []const u8 { const formatted = std.fmt.bufPrint(buf, "{any}", .{address}) catch return "unknown"; if (std.mem.lastIndexOf(u8, formatted, ":")) |colon| { - return formatted[0..colon]; + const ip = formatted[0..colon]; + if (ip.len > 2 and ip[0] == '[' and ip[ip.len - 1] == ']') { + return ip[1 .. ip.len - 1]; + } + return ip; } return formatted; }src/write_queue.zig (2)
6-11: Naming may be misleading after refactorThe struct is named
WriteQueuewith methods likeenqueue, but the implementation no longer uses a queue - it directly invokes the callback synchronously. Consider renaming toDirectWriteror similar to better reflect the current behavior.
56-58:queueDepthalways returns 0This method no longer reflects any meaningful state since there's no actual queue. It's effectively dead code. Consider removing it or documenting it as deprecated.
src/handler.zig (1)
711-760: Consider consolidating shutdown checks in send methodsAll
send*methods now have identical shutdown checks at the start. While this is safe, it creates repetition. Consider extracting a helper or documenting why each method needs its own check (e.g., if callers might call send methods directly without going throughhandle()).
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (15)
LICENSE(1 hunks)README.md(1 hunks)build.zig(2 hunks)build.zig.zon(1 hunks)src/config.zig(4 hunks)src/connection.zig(4 hunks)src/handler.zig(9 hunks)src/main.zig(5 hunks)src/nostr.zig(1 hunks)src/server.zig(0 hunks)src/spider.zig(26 hunks)src/store.zig(3 hunks)src/subscriptions.zig(1 hunks)src/tcp_server.zig(1 hunks)src/write_queue.zig(1 hunks)
💤 Files with no reviewable changes (1)
- src/server.zig
🔇 Additional comments (27)
README.md (1)
65-65: The commit message explicitly states "memory fixes, WS upgrade, update LICENSE," so the license change from LGPL-2.1-or-later to AGPL-3.0 was already communicated in the title. The scope is transparent and intentional—not misaligned.LICENSE (1)
1-664: AGPL-3.0 is appropriate for network relay software, but this is an initial license addition, not a replacement.This is the first license file explicitly added to the project (commit e64e91b). Git history shows no previous LICENSE file existed. The visible dependencies (websocket.zig under MIT License) are compatible with AGPL-3.0. AGPL-3.0 is specifically designed for network server software like Nostr relays, so this licensing choice aligns well with the project's purpose.
Likely an incorrect or invalid review comment.
src/nostr.zig (1)
34-34: LGTM!The
wsexport aligns with the new TCP/WebSocket implementation intcp_server.zig, providing access to WebSocket handshake and frame handling utilities.build.zig (1)
7-28: LGTM!The build configuration correctly sets up the
nostrandwebsocketdependencies and imports them into the executable module.src/config.zig (1)
48-49: LGTM!The
log_levelconfiguration field is properly integrated:
- Default value of
"info"is sensible- Config file parsing uses
allocStringfor proper memory management- Environment variable handling follows the existing pattern
Also applies to: 91-91, 233-236, 298-298
src/store.zig (2)
506-531: LGTM!The filter cloning logic correctly addresses potential lifetime issues where input filters could be freed while the iterator is in use. The error handling properly:
- Returns an empty-filter iterator on allocation failure
- Cleans up partially cloned filters on clone failure before returning
- Sets both
filtersandowned_filtersto the owned slice for consistent usage
684-691: LGTM!The
deinitproperly cleans up owned filters by deinitializing each filter before freeing the array, preventing memory leaks.src/subscriptions.zig (1)
59-86: LGTM!The new helper methods are well-designed:
withConnectionsafely executes a callback while holding the shared locksendToConnectionprovides a convenient wrapper for sending datacloseIdleConnectioncorrectly uses the shared lock to protect map access while relying on the connection's internal synchronization for write operationssrc/tcp_server.zig (3)
15-56: LGTM!The
WsWritercorrectly implements WebSocket frame encoding per RFC 6455, with proper handling for all payload length cases (7-bit, 16-bit extended, and 64-bit extended). The mutex ensures thread-safe writes.
306-331: LGTM!The HTTP handler correctly serves NIP-11 relay information for clients requesting
application/nostr+jsonand provides a simple HTML landing page for browsers.
229-247: Retract: no use-after-free risk exists withws_writer.The WriteQueue is not a background thread—it synchronously calls the write function via
enqueue(). WhenstopWriteQueue()executes, it nullifieswrite_fnandwrite_ctxunder mutex protection. Similarly,clearDirectWriter()nullifies the direct write pointers. By the time the defer block completes and the stack frame is destroyed, no code path can accessws_writer. Any concurrent calls tosend()from other threads will either fail to find the connection (afterremoveConnection()) or encounter null pointers and return without dereferencing the stack variable.The suggested heap allocation is unnecessary.
Likely an incorrect or invalid review comment.
src/connection.zig (3)
27-29: LGTM - Mutex-protected direct write mechanismThe introduction of
direct_write_fn,direct_write_ctx, andwrite_mutexis a clean approach for decoupling from the websocket dependency. The mutex ensures thread-safe access to the callback.
104-112: Consider null check order consistencyThe nested
ifchecks fordirect_write_fnthendirect_write_ctxwork correctly but could be simplified. IfsetDirectWriteralways sets both atomically (which it does), the context should never be null when the function is set.However, the current defensive approach is acceptable for robustness.
114-126: LGTM - Proper mutex protection for writer lifecycleBoth
setDirectWriterandclearDirectWritercorrectly acquire the mutex before modifying the callback state, ensuring thread-safe transitions.src/write_queue.zig (1)
37-50: Synchronous write under mutex may block other operationsThe
enqueuemethod now holds the mutex while invokingwrite_fn, which could block if the write operation is slow. This differs from a true queue pattern where enqueueing is fast and writing happens asynchronously.This is acceptable if write operations are expected to be fast, but be aware this could cause contention under high load.
src/main.zig (3)
4-9: LGTM - Log level configurationThe
std_optionsconfiguration sets a reasonable default log level and suppresses verbose websocket logging to error level only.
104-104: Good fix for config file parsingThe check
!std.mem.endsWith(u8, arg, ".toml")correctly prevents TOML config files from being interpreted as commands.
217-236: LGTM - Improved cleanup thread with responsive shutdownThe new implementation with 1-second check intervals allows the cleanup thread to respond to shutdown signals quickly while still performing hourly cleanup. This is a good pattern for graceful shutdown.
src/handler.zig (3)
151-172: LGTM - Shutdown flag integrationThe addition of the shutdown flag to Handler and its initialization in
init()is clean. This enables graceful shutdown throughout the handler.
376-386: Good fix - Subscription ID buffer copyCopying
sub_id_rawintosub_id_bufensures the subscription ID remains valid throughout the function, even if the original message is deallocated. This prevents potential use-after-free issues.
437-444: LGTM - Consistent shutdown-aware iteration patternThe pattern of checking
shutdown.load(.acquire)before each iteration and usingiter.next() catch null orelse breakis applied consistently across all query loops. This ensures responsive shutdown without leaving operations half-complete.Also applies to: 453-460, 470-477
src/spider.zig (6)
106-118: LGTM - Clean shutdown helpers
shouldRun()elegantly combines both local and global shutdown flags.interruptibleSleep()breaks long sleeps into 100ms chunks, enabling responsive shutdown while maintaining the intended delay.
380-381: Good pattern - Track active client for shutdownStoring the client in
conn.active_clientduring connection allows the shutdown path to potentially close it. This is the right approach, but it requirescloseClient()to be implemented (see other comment).
425-493: LGTM - Catch-up with proper error propagationThe
performCatchupfunction now returnsboolto indicate success/failure, allowing the caller to handle connection loss appropriately. Theread_errortracking and early return on connection loss is correct.
507-511: Good defensive limit for negentropy syncLimiting negentropy sync to 100 pubkeys prevents potential performance issues or protocol limitations. Setting
negentropy_supported = falseensures the relay falls back to catch-up sync.
584-604: LGTM - Graceful negentropy fallbackThe logic correctly handles both timeout (no response) and explicit rejection (NEG-ERR) by disabling negentropy for the relay and allowing the connection to continue with regular sync.
789-814: Consider WouldBlock handling in readLoopThe read loop handles
WouldBlockby continuing, which is correct for non-blocking reads. However, thereadTimeout(1000)at line 792 should make the client block for up to 1 second, soWouldBlockshould be less common. The handling is still correct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (5)
src/tcp_server.zig (3)
98-111: Consider a more explicit idempotency mechanism.The capacity checks to prevent double-free are fragile and rely on internal implementation details of
conn_limiterandip_filter. If the underlying HashMap implementation changes, this could break.Consider using a boolean flag or making the underlying types'
deinitmethods idempotent instead.🔎 Alternative approach using a flag
pub fn deinit(self: *TcpServer) void { + if (self.deinitialized) return; + self.deinitialized = true; + if (self.listener) |*l| { l.deinit(); self.listener = null; } - // Only deinit limiters if they haven't been freed - // This makes deinit idempotent - if (self.conn_limiter.ip_buckets.capacity() > 0) { - self.conn_limiter.deinit(); - } - if (self.ip_filter.whitelist.capacity() > 0) { - self.ip_filter.deinit(); - } + self.conn_limiter.deinit(); + self.ip_filter.deinit(); }Note: This would require adding a
deinitialized: bool = falsefield to the struct.
130-135: Thread-per-connection model has scalability limits.The current design spawns a detached thread for each connection. Under high connection load, this can exhaust system thread limits and degrade performance. Consider documenting the expected connection limits or evaluating alternative approaches (thread pool, async I/O) for future improvements.
232-238: Both direct writer and write queue use the same writer callback.Lines 237-238 set up both a direct writer and a write queue pointing to the same
WsWriter.writecallback. This creates two code paths to the same underlying writer, which could be confusing for maintenance. Consider documenting why both paths are needed or consolidating to a single write path.src/connection.zig (1)
102-108: Consider enforcing write_fn and write_ctx as a pair.The nested checks allow
write_fnandwrite_ctxto be set independently, but they should always be set or cleared together. If they get out of sync (e.g.,write_fnset butwrite_ctxis null), the write is silently skipped, which could hide bugs.Consider asserting they're both set or both null, or using a single optional tuple/struct.
🔎 Example with assertion
pub fn sendDirect(self: *Connection, data: []const u8) void { if (self.direct_write_fn) |write_fn| { if (self.direct_write_ctx) |ctx| { write_fn(ctx, data); + } else { + std.debug.assert(false); // write_fn set but ctx null - invariant violation } } }src/write_queue.zig (1)
48-50: Misleading name: WriteQueue doesn't actually queue.The
WriteQueuestruct name andenqueuemethod suggest queuing behavior, butqueueDepth()returns 0 andenqueue()calls the write function immediately. This is essentially a write dispatcher, not a queue.Consider renaming to
WriteDispatcherorWriterto better reflect the actual behavior, or document why "queue" terminology is used despite direct execution.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
build.zig.zonsrc/connection.zigsrc/handler.zigsrc/tcp_server.zigsrc/write_queue.zig
⏰ 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: benchmark
🔇 Additional comments (18)
build.zig.zon (2)
3-3: LGTM: Version bump aligns with the bug fixes.The patch version increment is appropriate for the changes in this PR.
12-13: The nostr v0.1.8 update is safe to deploy. Release notes confirm no breaking changes, and all APIs used in the codebase (WebSocket handling, negentropy, filters) remain compatible. The update includes a bug fix for the negentropy buffer check in encodeVarInt, which improves stability.src/tcp_server.zig (5)
26-58: WebSocket frame encoding looks correct.The implementation properly follows RFC 6455 for WebSocket text frame encoding with appropriate length handling for all size ranges. The use of
writevis efficient.
76-96: LGTM: Clean initialization with proper error handling.The initialization properly sets up all components and propagates errors from IP filter loading.
147-171: LGTM: Idle timeout handling with proper shutdown awareness.The implementation properly checks for shutdown and cleans up idle connections. The frequent shutdown checks ensure responsive teardown.
180-212: LGTM: Connection handling with proper filtering.The connection handling properly checks IP filtering and rate limits before processing. The shutdown checks ensure resources aren't accessed after teardown.
259-307: LGTM: WebSocket frame handling follows protocol correctly.The frame parsing, ping/pong handling, and close handshake properly implement the WebSocket protocol with appropriate error handling.
src/connection.zig (3)
27-28: LGTM: Clean separation of writer callback from WebSocket implementation.The new fields properly decouple the connection from specific transport implementations using a generic callback mechanism.
Also applies to: 59-60
68-70: LGTM: Updated signature properly delegates to WriteQueue.The method correctly passes the writer callback and context to the underlying write queue.
110-118: LGTM: Proper writer lifecycle management.These methods correctly set and clear both the function pointer and context together, maintaining the invariant.
src/write_queue.zig (2)
4-4: LGTM: Clean callback type definition.The
WriteFntype and struct fields properly implement a generic write callback mechanism.Also applies to: 7-8
31-42: LGTM: Proper error tracking for missing writer.The method correctly tracks dropped messages when the writer isn't available and returns success status to the caller.
src/handler.zig (6)
151-151: LGTM: Shutdown flag properly integrated.The atomic shutdown flag enables coordinated graceful shutdown across all handler methods.
Also applies to: 161-161, 171-171
175-176: LGTM: Early shutdown check prevents processing during teardown.The shutdown check at the entry point ensures the handler doesn't process messages after shutdown begins.
430-430: LGTM: Shutdown checks prevent long-running queries during teardown.The shutdown checks before each query path ensure that expensive database operations don't start after shutdown is initiated.
Also applies to: 444-444, 459-459
700-749: LGTM: Consistent shutdown guards across all send methods.All send methods properly check the shutdown flag before attempting to send, preventing writes to connections during teardown.
680-698: LGTM: Multiple shutdown checks in long-running reconciliation.The strategically placed shutdown checks ensure that expensive negentropy reconciliation can be interrupted promptly.
377-386: The stack-allocatedsub_idbuffer is safe in this context. TheaddSubscription()method explicitly copies the subscription ID viaalloc.dupe(u8, sub_id)before storing it, andsendClosed()uses the ID immediately without storing a reference. No changes needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
♻️ Duplicate comments (1)
src/tcp_server.zig (1)
139-148: Fixed 200ms cleanup delay remains insufficient.This is the same issue flagged in the previous review. Detached threads cannot be joined, and the 200ms sleep is arbitrary—it may be too short if connections are processing long operations or have queued writes.
🧹 Nitpick comments (3)
src/tcp_server.zig (2)
24-27: Partial improvement: write failures now set a flag but remain invisible.Setting the
failedflag is better than the previous silent swallow, but write failures still have no diagnostic visibility. This makes debugging connection issues difficult.Consider adding debug logging as previously suggested to aid troubleshooting.
🔎 Proposed enhancement
fn write(ctx: *anyopaque, data: []const u8) void { const self: *WsWriter = @ptrCast(@alignCast(ctx)); self.mutex.lock(); defer self.mutex.unlock(); if (self.failed) return; - self.writeWsFrame(data) catch { + self.writeWsFrame(data) catch |err| { + std.log.debug("WebSocket write failed: {}", .{err}); self.failed = true; }; }
109-114: Fragile idempotency check via capacity inspection.Checking
capacity() > 0to determine whether a resource has been deinitialized is fragile and relies on internal implementation details. If the hash map implementation changes or if capacity can legitimately be zero, this logic breaks.Consider an explicit boolean flag or state enum to track initialization status.
src/main.zig (1)
73-74: Allocator switched from GPA to c_allocator—loses leak detection.Changing from
GeneralPurposeAllocatortoc_allocatorimproves runtime characteristics but disables memory leak detection. In production this is often acceptable, but during development or testing you lose visibility into memory issues.Consider making this configurable via build mode (e.g., GPA for debug, c_allocator for release).
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/main.zigsrc/tcp_server.zig
⏰ 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: benchmark
🔇 Additional comments (5)
src/tcp_server.zig (1)
66-66: Unused allocator field.The
allocatorfield is stored in theTcpServerstruct but never used in any of the methods. Onlyself.allocator.create(Connection)at line 242 andself.allocator.destroy(connection)at line 257 use it, which are valid uses.Actually, reviewing more carefully: line 165 uses
self.allocator.free(idle_conn_ids), line 242 usesself.allocator.create(Connection), and line 257 usesself.allocator.destroy(connection). So the allocator IS used.src/main.zig (4)
4-9: Log configuration added for noise reduction.The new
std_optionsconfiguration suppresses verbose websocket logs while keeping info-level logs for the application. This is a sensible default for production use.
104-104: Command parsing fix prevents misinterpreting config files.The
!std.mem.endsWith(u8, arg, ".toml")guard prevents TOML configuration filenames from being treated as commands. This is a sensible fix for the argument parsing logic.
209-218: Cleanup thread now responsive to shutdown signals.Replacing the fixed 1-hour sleep with a 1-second check interval and hour counter makes the cleanup thread respond to shutdown within 1 second instead of waiting up to an hour. This significantly improves shutdown latency.
166-176: Verify Handler, TcpServer, and Spider accept the shutdown parameter.The code passes
&g_shutdowntoHandler.init,TcpServer.init, andSpider.init. All three functions have been updated to accept the shutdown parameter:
- Handler.init accepts
shutdown: *std.atomic.Value(bool)- TcpServer.init accepts
shutdown: *std.atomic.Value(bool)- Spider.init accepts
global_shutdown: *std.atomic.Value(bool)Each function stores the parameter as a field for graceful shutdown coordination.
dcdd542 to
afbfdc2
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/main.zig (1)
73-74: Clarify the allocator comment.The comment "better memory behavior than GPA" is misleading.
c_allocatordoesn't necessarily have better memory behavior—it has different trade-offs:
- GPA: Memory leak detection, double-free detection, safety checks, slight overhead
- c_allocator: Direct malloc/free, no safety checks, no overhead
For production deployments where performance is prioritized over debugging,
c_allocatoris reasonable, but the comment should reflect this trade-off rather than implying superiority.🔎 Suggested clarification
- // Use c_allocator for production - better memory behavior than GPA + // Use c_allocator for production - lower overhead, no safety checks const allocator = std.heap.c_allocator;
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/main.zigsrc/tcp_server.zig
🚧 Files skipped from review as they are similar to previous changes (1)
- src/tcp_server.zig
🔇 Additional comments (6)
src/main.zig (6)
15-15: LGTM: TcpServer migration.The import update from
server.zigtotcp_server.zigaligns with the architectural change described in the PR summary.
20-20: LGTM: Global server type updated.The global server variable type correctly updated to match the TcpServer migration.
104-104: Good fix for TOML file handling.The added check prevents TOML configuration files from being incorrectly parsed as commands, which fixes a command-line parsing bug.
166-166: LGTM: Graceful shutdown propagation.The addition of
&g_shutdowntoHandler.init,TcpServer.init, andSpider.initimplements consistent graceful shutdown signaling across all major components, as described in the PR objectives.Also applies to: 168-168, 176-176
203-203: LGTM: Server run call simplified.The removal of the
&g_shutdownparameter fromserver.run()is appropriate since the shutdown reference is now passed duringTcpServer.initand stored internally.
209-218: Good refactor for responsive shutdown.The cleanup thread now checks every second instead of sleeping for an entire hour, which significantly improves shutdown responsiveness (from potentially 1 hour to 1 second maximum wait) while still performing cleanup hourly. The logic correctly implements this with
3600 checks * 1 second = 1 hour.
| pub const std_options = std.Options{ | ||
| .log_level = .info, | ||
| .log_scope_levels = &[_]std.log.ScopeLevel{ | ||
| .{ .scope = .websocket, .level = .err }, | ||
| }, | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
# Find the main.zig file and check lines 4-9
find . -name "main.zig" -type fRepository: privkeyio/wisp
Length of output: 72
🏁 Script executed:
# Also search for config.zig
find . -name "config.zig" -type fRepository: privkeyio/wisp
Length of output: 74
🏁 Script executed:
# Check the repository structure
git ls-files | head -20Repository: privkeyio/wisp
Length of output: 408
🏁 Script executed:
# Check the size of src/main.zig
wc -l src/main.zigRepository: privkeyio/wisp
Length of output: 74
🏁 Script executed:
# Check the size of src/config.zig
wc -l src/config.zigRepository: privkeyio/wisp
Length of output: 76
🏁 Script executed:
# Read src/main.zig
cat -n src/main.zigRepository: privkeyio/wisp
Length of output: 13940
🏁 Script executed:
# Read src/config.zig
cat -n src/config.zigRepository: privkeyio/wisp
Length of output: 15801
🏁 Script executed:
# Search for any usage of config.log_level or log_level field access
rg "log_level" --type zigRepository: privkeyio/wisp
Length of output: 348
config.log_level is parsed but never used; logging is controlled only by hardcoded std_options.log_level.
The config.zig file parses log_level from TOML files and environment variables (including WISP_LOG_LEVEL), but config.log_level is never referenced in the code. Meanwhile, std_options at compile time is hardcoded to .info, which is what actually controls the application's logging behavior. Users who attempt to configure logging through the config file or environment variables will find it has no effect.
Since std_options must be compile-time constant in Zig, the configurable log_level field is dead code. Either remove the field and its parsing logic, or implement runtime logging configuration through a different mechanism if dynamic log level control is needed.
🤖 Prompt for AI Agents
In src/main.zig around lines 4–9, std_options.log_level is hardcoded to .info
while config.log_level (parsed from TOML/env) is never used; this makes the
config value dead code. Fix by either (A) removing the log_level field and any
parsing/env handling in config.zig and related code paths so config no longer
exposes an unused option, or (B) keep the config field but apply it at runtime
instead of as a compile-time const: build std_options without a hardcoded
compile-time log level and, during program initialization, read config.log_level
and set the runtime logger/handler levels accordingly (use the std.log runtime
APIs to translate the parsed string/enum into the logger scope/global level and
apply it). Ensure all places that referenced the removed field are updated or
replaced with the runtime setter approach.
Summary by CodeRabbit
New Features
Improvements
Chores
✏️ Tip: You can customize this high-level summary in your review settings.