|
13 | 13 | #include "rmutil/alloc.h" |
14 | 14 | #include "rmutil/rm_assert.h" |
15 | 15 | #include "redismodule.h" |
| 16 | +#include "info/global_stats.h" |
| 17 | +#include "common.h" |
16 | 18 | #include <unistd.h> |
| 19 | +#include <atomic> |
17 | 20 |
|
18 | 21 | // Test callback for queue operations |
19 | 22 | static void testCallback(void *privdata) { |
@@ -187,3 +190,55 @@ TEST_F(IORuntimeCtxCommonTest, ShutdownWithPendingRequests) { |
187 | 190 | // Verify all requests were processed despite shutdown |
188 | 191 | ASSERT_EQ(counter, 11); |
189 | 192 | } |
| 193 | + |
| 194 | +TEST_F(IORuntimeCtxCommonTest, ActiveIoThreadsMetric) { |
| 195 | + // Test that the active_io_threads metric is tracked correctly |
| 196 | + |
| 197 | + // Phase 1: Verify metric starts at 0 |
| 198 | + MultiThreadingStats stats = GlobalStats_GetMultiThreadingStats(); |
| 199 | + ASSERT_EQ(stats.active_io_threads, 0) << "active_io_threads should start at 0"; |
| 200 | + |
| 201 | + // Phase 2: Schedule a callback that sleeps, and verify metric increases |
| 202 | + struct CallbackFlags { |
| 203 | + std::atomic<bool> started{false}; |
| 204 | + std::atomic<bool> should_finish{false}; |
| 205 | + }; |
| 206 | + |
| 207 | + CallbackFlags flags; |
| 208 | + |
| 209 | + auto slowCallback = [](void *privdata) { |
| 210 | + auto *flags = (CallbackFlags *)privdata; |
| 211 | + flags->started.store(true); |
| 212 | + |
| 213 | + // Wait until test tells us to finish |
| 214 | + while (!flags->should_finish.load()) { |
| 215 | + usleep(100); // 100us |
| 216 | + } |
| 217 | + }; |
| 218 | + |
| 219 | + // Schedule the slow callback - this will start the IO runtime automatically |
| 220 | + IORuntimeCtx_Schedule(ctx, slowCallback, &flags); |
| 221 | + |
| 222 | + // Mark the IO runtime as ready to process callbacks |
| 223 | + ctx->uv_runtime.loop_th_ready = true; |
| 224 | + |
| 225 | + // Wait for callback to start |
| 226 | + while (!flags.started.load()) { |
| 227 | + usleep(100); // 100us |
| 228 | + } |
| 229 | + |
| 230 | + // Now the callback is executing - check that active_io_threads > 0 |
| 231 | + stats = GlobalStats_GetMultiThreadingStats(); |
| 232 | + ASSERT_EQ(stats.active_io_threads, 1) << "active_io_threads should be > 0 while callback is executing"; |
| 233 | + |
| 234 | + // Tell callback to finish |
| 235 | + flags.should_finish.store(true); |
| 236 | + |
| 237 | + // Phase 3: Wait for metric to return to 0 with timeout |
| 238 | + bool success = RS::WaitForCondition([&]() { |
| 239 | + stats = GlobalStats_GetMultiThreadingStats(); |
| 240 | + return stats.active_io_threads == 0; |
| 241 | + }); |
| 242 | + |
| 243 | + ASSERT_TRUE(success) << "Timeout waiting for active_io_threads to return to 0, current value: " << stats.active_io_threads; |
| 244 | +} |
0 commit comments