feat(cpp): add functions related to system#3102
Conversation
|
This PR is ready for review |
|
This pull request has been automatically marked as stale because it has not had recent activity. It will be closed in 7 days if no further activity occurs. If you need a review, please ensure CI is green and the PR is rebased on the latest master. Don't hesitate to ping the maintainers - either @core on Discord or by mentioning them directly here on the PR. Thank you for your contribution! |
c6be262 to
4e2082a
Compare
|
/ready |
|
@hubcio i still need to completely address the review for this pr maybe /author is better? |
|
@slbotbm I know. EDIT: you are right! this should be /author... |
|
/author |
|
/ready |
| RUNTIME.block_on(async { self.inner.heartbeat_interval().await.as_micros() }) | ||
| } | ||
|
|
||
| pub fn snapshot( |
There was a problem hiding this comment.
empty snapshot_types vec → server loops zero times in core/server/src/shard/system/snapshot/mod.rs:71 and returns an empty zip with Ok(()). silent no-op. duplicate types collide on the {snapshot_type}.txt filename at line 80, so the second entry quietly overwrites the first. reject empty vec at the ffi boundary and dedup before passing to the sdk.
| /// Internally, each selected value is passed across the Rust FFI as a string. | ||
| /// Values outside the supported set are rejected by the Rust client. | ||
| /// Some Rust-side aliases may also be accepted for compatibility. | ||
| class SnapshotType final : private detail::StringTag<SnapshotType> { |
There was a problem hiding this comment.
rust calls this SystemSnapshotType (core/common/src/types/snapshot/mod.rs:36) and c# preserves the prefix in foreign/csharp/Iggy_SDK/Enums/SystemSnapshotType.cs. c++ binding drops System. rename to SystemSnapshotType while pre-release to stop the divergence.
| /// | ||
| /// Internally, this value is passed across the Rust FFI as a string. | ||
| /// Values outside the supported set are rejected by the Rust client. | ||
| /// Some Rust-side aliases may also be accepted for compatibility. |
There was a problem hiding this comment.
this "Some Rust-side aliases may also be accepted for compatibility." line is repeated on SnapshotCompression at line 78 and SnapshotType at line 107. only MaxTopicSize::from_str accepts genuine token aliases ("0" ≡ "server_default"). the other three only do s.to_lowercase() then exact-match (core/common/src/types/compression/compression_algorithm.rs:45-51, core/common/src/types/snapshot/mod.rs:129-141, 171-181). drop the alias claim from the three inaccurate docs, keep on MaxTopicSize only.
| @@ -67,14 +67,14 @@ impl TryFrom<ffi::Identifier> for RustIdentifier { | |||
| // preserves the C++ ABI used by every test and downstream binding. | |||
| #[allow(clippy::wrong_self_convention)] | |||
There was a problem hiding this comment.
follow-up on the earlier rename thread: from_string → set_string and from_numeric → set_numeric landed but the #[allow(clippy::wrong_self_convention)] here is now dead (set_* doesn't trigger that lint) and the comment above about "keeping the names preserves the C++ ABI used by every test and downstream binding" directly contradicts the rename in this same pr. delete both.
| memory_usage: u64, | ||
| total_memory: u64, | ||
| available_memory: u64, | ||
| run_time: u64, |
There was a problem hiding this comment.
run_time and start_time are both bare u64 but carry different semantics - client.rs:107-108 fills them as stats.run_time.as_micros() (IggyDuration, micros since boot) and stats.start_time.as_micros() (IggyTimestamp, unix-epoch micros). consumers cannot tell them apart without reading the rust source. rename to run_time_micros and start_time_epoch_micros, or doc-comment the bridge struct.
| ffi::ClientInfo { | ||
| client_id: client.client_id, | ||
| has_user_id, | ||
| user_id: client.user_id.unwrap_or(0), |
There was a problem hiding this comment.
follow-up on the earlier unwrap_or(u32::MAX) thread: switching to unwrap_or(0) here and at line 60 trades one collision for another - root user has id 0 (core/common/src/http/users/defaults.rs:26, applied at core/server/src/streaming/users/user.rs:96), so (has_user_id=true, user_id=0) for a root login is indistinguishable from (has_user_id=false, user_id=0) for an unauthenticated session whenever a consumer reads user_id without first checking the bool. wire encoding already uses u32::MAX as the none sentinel (core/server/src/binary/handlers/system/get_me_handler.rs:64, decoder at core/common/src/wire_conversions.rs:258-261). either doc the has_user_id contract on the bridge structs (lib.rs:123-130, 132-140), or align ffi to the wire sentinel with unwrap_or(u32::MAX).
|
|
||
| // TODO(slbotbmR): add a test to create some streams, topics, partitions, and segments, send messages, and create | ||
| // consumer groups and verify it. | ||
| TEST(LowLevelE2E_Client, GetStatsReturnsServerStats) { |
There was a problem hiding this comment.
tests/common/test_helpers.hpp:18 already has a TODO(slbotbm): create fixture for setup/teardown covering the broader cleanup story, but this specific test has two extra fragilities not implicit in that todo: (1) fixed stream/topic/group names (cpp-get-stats-stream-1 etc) - any failing ASSERT_NO_THROW before the inline cleanup at lines 266-272 leaks streams and the next run collides on create_stream; (2) clients_count == empty + 2u (line 260) compares deltas against empty_stats taken seconds earlier on a shared server - any other client connecting in between invalidates the assertion. once the fixture lands, randomize names and switch the count assertions to EXPECT_GE so this test stops being order-dependent. add a TODO here if the fix isn't landing in this pr.
| EXPECT_FALSE(static_cast<std::string>(empty_stats.os_version).empty()); | ||
| EXPECT_FALSE(static_cast<std::string>(empty_stats.kernel_version).empty()); | ||
| EXPECT_FALSE(static_cast<std::string>(empty_stats.iggy_server_version).empty()); | ||
| EXPECT_TRUE(!empty_stats.has_server_semver || empty_stats.iggy_server_semver > 0u); |
There was a problem hiding this comment.
!has_server_semver || iggy_server_semver > 0u is unfalsifiable. wire decoder at core/binary_protocol/src/responses/system/get_stats.rs:204 sets Some(raw) iff raw != 0, so has_server_semver=true already implies iggy_server_semver > 0. use EXPECT_EQ(empty_stats.has_server_semver, empty_stats.iggy_server_semver != 0u) or drop the assertion.
| kernel_version: stats.kernel_version, | ||
| iggy_server_version: stats.iggy_server_version, | ||
| has_server_semver, | ||
| iggy_server_semver: stats.iggy_server_semver.unwrap_or(0), |
There was a problem hiding this comment.
same unwrap_or(0) shape as the user_id follow-up. wire decoder at core/binary_protocol/src/responses/system/get_stats.rs:204 forbids Some(0) from a conforming server so the collision is unreachable today, but the pattern is fragile - if anyone ever changes the wire format to allow Some(0), this silently degrades to the same shape as None. doc the invariant on the bridge struct, or align to a sentinel that cannot collide.
| format!( | ||
| "Could not get consumer group '{}' for topic '{}' on stream '{}': {error}", | ||
| rust_group_id, rust_topic_id, rust_stream_id | ||
| "Could not get consumer group '{rust_group_id}' for topic '{rust_topic_id}' on stream '{rust_stream_id}': {error}" |
There was a problem hiding this comment.
follow-up on the earlier clippy::uninlined_format_args thread: the sweep landed here and at line 627, but missed two callers - join_consumer_group at lines 656-657 and leave_consumer_group at 741-742 still use the old positional {} style with separate args. unify to named captures.
| template <typename Tag> | ||
| class StringTag { | ||
| protected: | ||
| explicit StringTag(std::string value) : value_(std::move(value)) {} | ||
|
|
||
| std::string_view value() const { return value_; } | ||
|
|
||
| private: | ||
| std::string value_; | ||
| }; |
There was a problem hiding this comment.
StringTag should be marked final and have a destructor to satisfy the C++ ABI.
| static SnapshotCompression stored() { return SnapshotCompression("stored"); } | ||
| /// Use standard deflate compression. | ||
| static SnapshotCompression deflated() { return SnapshotCompression("deflated"); } | ||
| /// Use bzip2 for a higher compression ratio at the cost of slower processing. | ||
| static SnapshotCompression bzip2() { return SnapshotCompression("bzip2"); } | ||
| /// Use Zstandard for fast compression and decompression. | ||
| static SnapshotCompression zstd() { return SnapshotCompression("zstd"); } | ||
| /// Use LZMA for high compression, especially for larger files. | ||
| static SnapshotCompression lzma() { return SnapshotCompression("lzma"); } | ||
| /// Use XZ, which is similar to LZMA and often faster to decompress. | ||
| static SnapshotCompression xz() { return SnapshotCompression("xz"); } | ||
|
|
||
| std::string_view snapshot_compression_value() const { return value(); } |
There was a problem hiding this comment.
Shouldn't this be in a trait type instead?
amlel-el-mahrouss
left a comment
There was a problem hiding this comment.
Requesting the following changes for:
- StringType
- SnapshotCompression
See the comments for more info.
Which issue does this PR close?
Works toward completion of #2100
Rationale
This PR adds functions related to the system, and tests for previously untested functions.
What changed?
This PR adds:
The places labelled TODO will be completed after merging of #3046.
Local Execution
AI Usage
If AI tools were used, please answer: