Skip to content

Conversation

@lalinsky
Copy link
Owner

@lalinsky lalinsky commented Aug 24, 2025

Summary

  • Implements JetStream STREAM.PURGE API call functionality
  • Adds support for selective message purging with filter, sequence, and keep options
  • Includes comprehensive test coverage

Changes Made

  • StreamPurgeRequest struct: Added request structure with optional filter, seq, and keep parameters
  • StreamPurgeResponse struct: Added response structure with success and purged fields
  • purgeStream method: Implemented API call to $JS.API.STREAM.PURGE.{stream}
  • Public API: Exported StreamPurgeRequest in root module
  • Tests: Added 3 comprehensive test cases covering basic purge, filtered purge, and sequence-based purge

API Usage

// Basic purge (all messages)
const purge_request = nats.StreamPurgeRequest{};
const result = try js.purgeStream("STREAM_NAME", purge_request);

// Purge with filter
const purge_request = nats.StreamPurgeRequest{ .filter = "subject.pattern" };
const result = try js.purgeStream("STREAM_NAME", purge_request);

// Purge up to sequence
const purge_request = nats.StreamPurgeRequest{ .seq = 100 };
const result = try js.purgeStream("STREAM_NAME", purge_request);

Test Plan

  • Basic stream purge functionality
  • Filtered purge by subject pattern
  • Sequence-based purge (up to specific message)
  • All existing tests continue to pass
  • API follows existing JetStream patterns and conventions

All tests pass successfully.

Summary by CodeRabbit

  • New Features

    • Add stream purge capability: purge all, purge by subject filter, purge up to a sequence, or keep a minimum number of messages. Returns success status and count of removed messages.
    • Expose the purge request type at the library root for easier usage.
  • Tests

    • Added tests covering purge-all, filter, sequence-limit, and keep scenarios and included them in the test suite.

- Add StreamPurgeRequest struct with filter, seq, and keep options
- Add StreamPurgeResponse struct with success and purged count
- Implement purgeStream method in JetStream client
- Export StreamPurgeRequest in public API
- Add comprehensive tests for basic purge, filtered purge, and sequence-based purge

All tests pass successfully.
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 24, 2025

Walkthrough

Adds a JetStream purge API: introduces StreamPurgeRequest, a purgeStream method that sends STREAM.PURGE.{stream} requests and parses responses, re-exports the request at the crate root, and adds dedicated JetStream purge tests.

Changes

Cohort / File(s) Summary
JetStream purge API
src/jetstream.zig
Adds pub const StreamPurgeRequest = struct { filter: ?[]const u8 = null, seq: ?u64 = null, keep: ?u64 = null }, internal StreamPurgeResponse, and pub fn purgeStream(self: *JetStream, stream_name: []const u8, request: StreamPurgeRequest) !Result(StreamPurgeResponse) which builds STREAM.PURGE.{stream}, JSON-encodes the request, sends via existing sendRequest, and parses the JSON response (reusing existing error/parse paths).
Root re-export
src/root.zig
Adds pub const StreamPurgeRequest = @import("jetstream.zig").StreamPurgeRequest to expose the type at the crate root.
Tests — new purge tests
tests/jetstream_stream_purge_test.zig, tests/all_tests.zig
Adds tests/jetstream_stream_purge_test.zig with four tests (purge-all, purge-with-filter, purge-with-seq, purge-with-keep). Adds pub const jetstream_stream_purge_tests = @import("jetstream_stream_purge_test.zig"); to tests/all_tests.zig.
Tests — whitespace/comments
tests/jetstream_test.zig
Inserts a blank line and appends a large block of commented-out JetStream stream management test code (no runtime effect).

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor App as Client
  participant JS as JetStream
  participant NATS as NATS_Server

  App->>JS: purgeStream(stream_name, StreamPurgeRequest)
  JS->>JS: build subject "STREAM.PURGE.{stream}"
  JS->>JS: JSON-encode request (filter / seq / keep)
  JS->>NATS: sendRequest(subject, body)
  NATS-->>JS: JSON response {success, purged} or error
  JS->>JS: maybeParseErrorResponse / parseResponse
  JS-->>App: Result(StreamPurgeResponse)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

I thump my paw—purge time, hooray!
I filter, seq, and keep with care,
Old messages vanish from the lair.
Streams tidy, burrow bright and gay,
A rabbit smiles — bytes hop away. 🥕


📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 299fc8c and 8bbcac4.

📒 Files selected for processing (1)
  • tests/jetstream_stream_purge_test.zig (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/jetstream_stream_purge_test.zig
✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/stream-purge

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@lalinsky
Copy link
Owner Author

@claude add test for the keep parameter as well

@claude
Copy link
Contributor

claude bot commented Aug 24, 2025

Claude finished @lalinsky's task —— View job


Adding test for keep parameter ✅

I've successfully added a test case for the keep parameter in the StreamPurgeRequest functionality.

Todo List:

  • Read repository instructions and understand codebase
  • Examine existing test structure
  • Understand keep parameter implementation
  • Add new test case for keep parameter
  • Run tests to verify functionality
  • Commit and push changes

Summary:

Added a new test "purge stream with keep parameter" in tests/jetstream_test.zig:521 that:

  1. Creates a stream with 5 messages
  2. Uses StreamPurgeRequest with keep = 2 parameter
  3. Verifies that 3 messages are purged (keeping only the 2 most recent)
  4. Confirms the purge operation was successful

The test follows the same pattern as existing purge tests and all tests pass successfully. The changes have been committed and pushed to the feature/stream-purge branch.


- Add test case that verifies keep parameter functionality
- Test publishes 5 messages and uses keep=2 to ensure only 2 messages remain
- Verifies that 3 messages are purged correctly

Co-authored-by: Lukáš Lalinský <[email protected]>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (5)
src/jetstream.zig (2)

191-199: Request shape matches schema; consider documenting mutual exclusivity and null-emission behavior

  • Fields and types align with the JetStream STREAM.PURGE request schema (filter, seq, keep are all optional; seq/keep are u64). However, per the official schema, seq and keep are mutually exclusive, though each can be combined with filter. Please document that here (and enforce in purgeStream). Also, if your Zig version emits nulls for unset optionals by default, the server may receive {"filter":null,...}; better to omit null fields (see purgeStream comment below). (beta-docs.nats.io)

201-208: Fix nit: success comment wording; consider public export for consumers

  • The field comment says “Indicates if this response is an error” but the field is success: bool. Please correct to “Indicates whether the purge operation succeeded”.
  • Optional: If downstream users may want to work with the concrete type (e.g., in signatures), consider making StreamPurgeResponse public like other public response types, though tests can already use the parsed value without importing the type.

Apply this diff to fix the comment:

 /// Response from $JS.API.STREAM.PURGE
 const StreamPurgeResponse = struct {
-    /// Indicates if this response is an error
+    /// Indicates whether the purge operation succeeded
     success: bool,
     /// The number of messages purged
     purged: u64,
 };
tests/jetstream_test.zig (3)

451-485: Filtered purge path is covered; add a post-condition on remaining messages

Great targeted assertions (expect == 2). Optionally, validate that the non-matching subject remains by fetching stream info after purge and asserting state.messages (or by republishing/reading). This strengthens the contract that only the filtered subject was purged.


486-520: Sequence-based purge semantics are correct; consider a negative test for invalid request

Assertions align with “purge up to but not including seq”. Recommend adding:

  • A test that setting both seq and keep returns error.InvalidPurgeRequest (after the proposed guard).
  • A test for keep (e.g., publish 5, keep=2 ⇒ purged==3).

I can draft these tests to fit your utils helpers.


418-449: Prefer flushing over sleeping for test reliability

The Connection type includes a flush(self: *Self) !void method (see src/connection.zig:548–550) that ensures all pending writes are sent to the server. Instead of using an arbitrary sleep:

  • Replace
    std.time.sleep(100 * std.time.ns_per_ms);
    with
    try conn.flush();
    (or try js.connection.flush(); if flushing via the JetStream wrapper).

This guarantees the messages are processed before the purge, reducing test flakiness by relying on protocol acknowledgments rather than fixed delays.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between c1b421c and 9912fee.

📒 Files selected for processing (3)
  • src/jetstream.zig (2 hunks)
  • src/root.zig (1 hunks)
  • tests/jetstream_test.zig (1 hunks)
🔇 Additional comments (2)
src/jetstream.zig (1)

458-470: Validate StreamPurgeRequest parameters and optimize the purge payload

– Enforce mutual exclusivity of seq and keep at the top of purgeStream to catch client‐side errors early.
– Send an empty payload ("") when no filter/seq/keep is set, instead of "{}", to trigger a full‐stream purge more cleanly.
– Omit null optionals when serializing (via emit_null_optional_fields = false, if supported) so you don’t send {"filter":null,"seq":null,"keep":null}.

Suggested diff:

     pub fn purgeStream(self: *JetStream, stream_name: []const u8, request: StreamPurgeRequest) !Result(StreamPurgeResponse) {
+        // Fail fast if both seq and keep are provided
+        if (request.seq != null and request.keep != null) {
+            // Ensure `InvalidPurgeRequest` is defined in your error set, or replace with an existing error
+            return error.InvalidPurgeRequest;
+        }
 
         const subject = try std.fmt.allocPrint(self.allocator, "STREAM.PURGE.{s}", .{stream_name});
         defer self.allocator.free(subject);
 
-        const request_json = try std.json.stringifyAlloc(self.allocator, request, .{});
-        defer self.allocator.free(request_json);
-        const msg = try self.sendRequest(subject, request_json);
+        const has_payload = (request.filter != null) or (request.seq != null) or (request.keep != null);
+        const msg = if (!has_payload) blk: {
+            // Purge-all: empty payload preferred by the server
+            break :blk try self.sendRequest(subject, "");
+        } else blk: {
+            // Exclude null fields if supported
+            const request_json = try std.json.stringifyAlloc(self.allocator, request, .{
+                .emit_null_optional_fields = false,
+            });
+            defer self.allocator.free(request_json);
+            break :blk try self.sendRequest(subject, request_json);
+        };
         defer msg.deinit();
 
         return try self.parseResponse(StreamPurgeResponse, msg);
     }

Please verify:

  • You have an InvalidPurgeRequest error in your error set (or swap in an existing error).
  • Your Zig version’s std.json.stringifyAlloc supports emit_null_optional_fields. If not, you can hand-construct a JSON object with only non-null fields.
src/root.zig (1)

20-20: Good re-export for ergonomics

Re-exporting StreamPurgeRequest at the root keeps the public surface consistent with other JetStream types. LGTM.

@lalinsky
Copy link
Owner Author

@claude please address this:

418-449: Prefer flushing over sleeping for test reliability

The Connection type includes a flush(self: *Self) !void method (see src/connection.zig:548–550) that ensures all pending writes are sent to the server. Instead of using an arbitrary sleep:

Replace
std.time.sleep(100 * std.time.ns_per_ms);
with
try conn.flush();
(or try js.connection.flush(); if flushing via the JetStream wrapper).
This guarantees the messages are processed before the purge, reducing test flakiness by relying on protocol acknowledgments rather than fixed delays.

@claude
Copy link
Contributor

claude bot commented Aug 24, 2025

Claude finished @lalinsky's task —— View job


Replacing sleep with flush for test reliability ✅

Todo List:

  • Read repository instructions and understand the issue
  • Examine current test code to locate sleep usage
  • Check Connection and JetStream types for flush method access
  • Replace sleep calls with flush calls
  • Run tests to verify changes work
  • Commit and push changes

Summary:

Successfully improved test reliability by replacing all 4 std.time.sleep(100 * std.time.ns_per_ms) calls with try conn.flush() in the JetStream purge stream tests at lines 439, 472, 508, and 544.

Changes made:

  • tests/jetstream_test.zig:439: Replaced sleep with flush in basic purge test
  • tests/jetstream_test.zig:472: Replaced sleep with flush in filter-based purge test
  • tests/jetstream_test.zig:508: Replaced sleep with flush in sequence-based purge test
  • tests/jetstream_test.zig:544: Replaced sleep with flush in keep parameter purge test

This ensures messages are properly sent to the server before purge operations, making tests more reliable by relying on protocol acknowledgments rather than arbitrary delays.

All tests continue to pass, confirming the changes work correctly.


Improve test reliability by using connection flush instead of arbitrary
sleep delays. This ensures messages are properly sent to the server
before attempting purge operations, reducing test flakiness.

Co-authored-by: Lukáš Lalinský <[email protected]>
@lalinsky
Copy link
Owner Author

@claude move these tests to jetstream_stream_purge_test.zig and make sure they are imported in jetstream.zig

@claude
Copy link
Contributor

claude bot commented Aug 24, 2025

Claude finished @lalinsky's task —— View job


Moving purge tests to dedicated file ✅

Todo List:

  • Read repository instructions and understand current test structure
  • Examine existing purge tests in jetstream_test.zig
  • Check how tests are imported in jetstream.zig
  • Create new jetstream_stream_purge_test.zig file
  • Move purge tests to new dedicated file
  • Update imports in jetstream.zig
  • Run tests to verify everything works
  • Commit and push changes

Summary:

Successfully refactored the JetStream purge tests into a dedicated test file:

Changes made:

  • Created tests/jetstream_stream_purge_test.zig with all 4 purge-related test cases
  • Removed purge tests from tests/jetstream_test.zig (lines 418-555)
  • Updated tests/all_tests.zig to import the new test module

Test organization:

  • purge stream - Basic purge functionality test
  • purge stream with filter - Filter-based purge test
  • purge stream with sequence limit - Sequence-based purge test
  • purge stream with keep parameter - Keep parameter purge test

All tests continue to pass (26/26 successful), confirming the refactor maintains functionality while improving code organization.


- Create tests/jetstream_stream_purge_test.zig with all purge-related tests
- Remove purge tests from tests/jetstream_test.zig
- Update tests/all_tests.zig to import the new test module
- All existing tests continue to pass

Co-authored-by: Lukáš Lalinský <[email protected]>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (4)
tests/jetstream_test.zig (4)

418-449: Tighten the assertion and clean up the stream (nice use of conn.flush()).

  • Since exactly 3 messages are published, assert the exact purged count for stronger guarantees.
  • Add a best-effort stream cleanup to avoid cross-test contamination if the test runner reuses a server.
   var stream_info = try js.addStream(stream_config);
   defer stream_info.deinit();
+  // Ensure no state is left behind if the test server is reused
+  defer js.deleteStream("TEST_PURGE_STREAM") catch {};

   // Publish some messages to the stream
   try conn.publish("test.purge.msg1", "First message");
   try conn.publish("test.purge.msg2", "Second message");
   try conn.publish("test.purge.msg3", "Third message");
@@
   // Verify purge was successful and messages were removed
   try testing.expect(purge_result.value.success);
-  try testing.expect(purge_result.value.purged > 0);
+  try testing.expect(purge_result.value.purged == 3);

451-485: Add idempotence check and cleanup for the filtered purge.

  • Add deleteStream() for hygiene.
  • Verify idempotence by purging with the same filter again and asserting 0 purged.
   var stream_info = try js.addStream(stream_config);
   defer stream_info.deinit();
+  // Cleanup to prevent residue across test runs
+  defer js.deleteStream("TEST_PURGE_FILTER_STREAM") catch {};
@@
   var purge_result = try js.purgeStream("TEST_PURGE_FILTER_STREAM", purge_request);
   defer purge_result.deinit();
@@
   try testing.expect(purge_result.value.success);
   try testing.expect(purge_result.value.purged == 2);
+
+  // A second purge with the same filter should be a no-op
+  const purge_again = nats.StreamPurgeRequest{
+      .filter = "test.filter.purge",
+  };
+  var purge_result2 = try js.purgeStream("TEST_PURGE_FILTER_STREAM", purge_again);
+  defer purge_result2.deinit();
+  try testing.expect(purge_result2.value.success);
+  try testing.expect(purge_result2.value.purged == 0);

521-556: Strengthen the keep test with idempotence and add cleanup.

  • Add deleteStream() to keep the test environment clean.
  • After keeping 2, purge again with keep=2 to assert no-ops when already at the threshold.
   var stream_info = try js.addStream(stream_config);
   defer stream_info.deinit();
+  defer js.deleteStream("TEST_PURGE_KEEP_STREAM") catch {};
@@
   var purge_result = try js.purgeStream("TEST_PURGE_KEEP_STREAM", purge_request);
   defer purge_result.deinit();
@@
   try testing.expect(purge_result.value.success);
   try testing.expect(purge_result.value.purged == 3);
+
+  // When only 2 messages remain, keep=2 should purge nothing
+  const purge_again = nats.StreamPurgeRequest{ .keep = 2 };
+  var purge_result2 = try js.purgeStream("TEST_PURGE_KEEP_STREAM", purge_again);
+  defer purge_result2.deinit();
+  try testing.expect(purge_result2.value.success);
+  try testing.expect(purge_result2.value.purged == 0);

486-520: Add cleanup and verify exclusive purge semantics

  • After creating the stream, defer its deletion to prevent state leakage:
    var stream_info = try js.addStream(stream_config);
    defer stream_info.deinit();
  • defer js.deleteStream("TEST_PURGE_SEQ_STREAM") catch {};
  • Confirm that seq is exclusive (only messages with sequence < seq are purged) by issuing a second purge with the same seq and expecting zero messages removed (beta-docs.nats.io, nats-io.github.io).
  • Updated diff:
   var stream_info = try js.addStream(stream_config);
   defer stream_info.deinit();
+  defer js.deleteStream("TEST_PURGE_SEQ_STREAM") catch {};
@@
   var purge_result = try js.purgeStream("TEST_PURGE_SEQ_STREAM", purge_request);
   defer purge_result.deinit();
@@
   try testing.expect(purge_result.value.success);
   try testing.expect(purge_result.value.purged == 2);
+
+  // A second purge with the same sequence should remove nothing (< seq semantics)
+  const purge_again = nats.StreamPurgeRequest{ .seq = 3 };
+  var purge_result2 = try js.purgeStream("TEST_PURGE_SEQ_STREAM", purge_again);
+  defer purge_result2.deinit();
+  try testing.expect(purge_result2.value.success);
+  try testing.expect(purge_result2.value.purged == 0);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between a971006 and a2f11e4.

📒 Files selected for processing (1)
  • tests/jetstream_test.zig (1 hunks)

@lalinsky
Copy link
Owner Author

@claude one more thing, in the tests, use the js.streamPurge(name, .{ .foo = 1 }) syntax

@claude
Copy link
Contributor

claude bot commented Aug 24, 2025

Claude finished @lalinsky's task —— View job


Updating test syntax to use concise struct literals ✅

Todo List:

  • Read current test file to understand existing syntax
  • Update purgeStream calls to use .{ .field = value } syntax
  • Run tests to verify changes work correctly
  • Commit and push changes

Summary:

Successfully updated all JetStream purge stream tests to use the more concise anonymous struct literal syntax as requested.

Changes made:

  • tests/jetstream_stream_purge_test.zig:31: Updated basic purge test to use .{}
  • tests/jetstream_stream_purge_test.zig:66: Updated filter-based purge test to use .{ .filter = "test.filter.purge" }
  • tests/jetstream_stream_purge_test.zig:102: Updated sequence-based purge test to use .{ .seq = 3 }
  • tests/jetstream_stream_purge_test.zig:138: Updated keep parameter purge test to use .{ .keep = 2 }

Before:

const purge_request = nats.StreamPurgeRequest{ .filter = "test.filter.purge" };
var purge_result = try js.purgeStream("STREAM_NAME", purge_request);

After:

var purge_result = try js.purgeStream("STREAM_NAME", .{ .filter = "test.filter.purge" });

All tests continue to pass (26/26 successful), confirming the syntax change maintains functionality while making the code cleaner and more idiomatic.


Replace nats.StreamPurgeRequest{} with .{} syntax for cleaner, more idiomatic test code.

Co-authored-by: Lukáš Lalinský <[email protected]>
Copy link
Contributor

@coderabbitai coderabbitai bot left a 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 (5)
tests/jetstream_stream_purge_test.zig (5)

34-37: Strengthen the assertion: check the exact purged count (deterministic).

You publish exactly 3 messages before purging. As the suite’s beforeEach clears streams, asserting == 3 is more precise than > 0.

Apply this diff:

-    // Verify purge was successful and messages were removed
-    try testing.expect(purge_result.value.success);
-    try testing.expect(purge_result.value.purged > 0);
+    // Verify purge was successful and removed exactly 3 messages
+    try testing.expect(purge_result.value.success);
+    try testing.expectEqual(@as(@TypeOf(purge_result.value.purged), 3), purge_result.value.purged);

69-72: Prefer expectEqual for clearer failures.

You already assert equality; expectEqual yields better diagnostics on mismatch.

Apply this diff:

-    try testing.expect(purge_result.value.success);
-    try testing.expect(purge_result.value.purged == 2);
+    try testing.expect(purge_result.value.success);
+    try testing.expectEqual(@as(@TypeOf(purge_result.value.purged), 2), purge_result.value.purged);

105-107: Nit: use expectEqual here as well.

-    try testing.expect(purge_result.value.success);
-    try testing.expect(purge_result.value.purged == 2);
+    try testing.expect(purge_result.value.success);
+    try testing.expectEqual(@as(@TypeOf(purge_result.value.purged), 2), purge_result.value.purged);

141-143: Nit: use expectEqual for consistency and better diffs.

-    try testing.expect(purge_result.value.success);
-    try testing.expect(purge_result.value.purged == 3);
+    try testing.expect(purge_result.value.success);
+    try testing.expectEqual(@as(@TypeOf(purge_result.value.purged), 3), purge_result.value.purged);

1-5: Optional: reduce duplication with a tiny publish helper.

Each test repeats publish+flush. A small local helper keeps tests concise and consistent.

Add near the top of the file:

fn publishMany(conn: *nats.Connection, subject: []const u8, msgs: []const []const u8) !void {
    for (msgs) |m| try conn.publish(subject, m);
    try conn.flush();
}

Then, for example in “purge stream”:

-    // Publish some messages to the stream
-    try conn.publish("test.purge.msg1", "First message");
-    try conn.publish("test.purge.msg2", "Second message");
-    try conn.publish("test.purge.msg3", "Third message");
-
-    // Flush to ensure messages are sent to the server
-    try conn.flush();
+    // Publish some messages to the stream
+    try publishMany(&conn, "test.purge.msg1", &.{ "First message" });
+    try publishMany(&conn, "test.purge.msg2", &.{ "Second message" });
+    try publishMany(&conn, "test.purge.msg3", &.{ "Third message" });

Or, alternatively, group by subject:

try publishMany(&conn, "test.purge.msg1", &.{"First message"});
try publishMany(&conn, "test.purge.msg2", &.{"Second message"});
try publishMany(&conn, "test.purge.msg3", &.{"Third message"});

Use the same pattern in the other tests.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between a2f11e4 and 299fc8c.

📒 Files selected for processing (3)
  • tests/all_tests.zig (1 hunks)
  • tests/jetstream_stream_purge_test.zig (1 hunks)
  • tests/jetstream_test.zig (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • tests/jetstream_test.zig
🔇 Additional comments (3)
tests/all_tests.zig (1)

11-11: Good: purge tests are now included in the test suite.

Importing jetstream_stream_purge_test.zig here ensures the new tests run via refAllDecls. This also addresses the prior request to move these tests into their own file and wire them into the suite.

tests/jetstream_stream_purge_test.zig (2)

26-27: Nice: replaced fixed sleeps with protocol flush() calls.

Using conn.flush() eliminates timing flakiness and aligns with the earlier review guidance.

Also applies to: 59-61, 95-97, 131-133


109-143: Thanks for adding the keep test.

This addresses the reviewer’s request. The expectations look correct for 5 messages with keep = 2 (expecting purged == 3).

@lalinsky lalinsky merged commit 6891053 into main Aug 24, 2025
3 of 4 checks passed
@lalinsky lalinsky deleted the feature/stream-purge branch August 24, 2025 11:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant