|
438 | 438 | # 3. Write a value and confirm the supervisor can read it. |
439 | 439 | # 4. Force a resize by registering a second worker (free list is empty → resize). |
440 | 440 | # 5. Write a new value from the first worker and confirm the supervisor still reads it. |
441 | | - |
| 441 | + |
442 | 442 | initial_size = page_size # gives exactly page_size / segment_size segments |
443 | 443 | segments_per_page = page_size / segment_size |
444 | | - |
| 444 | + |
445 | 445 | small_monitor = subject.new( |
446 | 446 | path: File.join(root, "utilization.shm"), |
447 | 447 | interval: 1, |
448 | 448 | size: initial_size, |
449 | 449 | segment_size: segment_size |
450 | 450 | ) |
451 | | - |
| 451 | + |
452 | 452 | # Fill all but one segment so the free list has exactly one slot left. |
453 | 453 | # (Skip this loop when segments_per_page == 1 — the first worker will itself |
454 | 454 | # consume the only slot and the second will trigger the resize.) |
|
469 | 469 | filler_controllers << filler_controller |
470 | 470 | small_monitor.register(filler_controller) |
471 | 471 | end |
472 | | - |
| 472 | + |
473 | 473 | # Register the worker-under-test — it takes the last free segment and |
474 | 474 | # maps the file at its current (pre-resize) size. |
475 | 475 | small_monitor.register(supervisor_controller) |
476 | 476 | worker_registry.metric(:connections_total).set(42) |
477 | 477 | worker_registry.metric(:connections_active).set(7) |
478 | | - |
| 478 | + |
479 | 479 | status_before = small_monitor.status |
480 | 480 | expect(status_before[:data]).to have_keys("test_service") |
481 | 481 | expect(status_before[:data]["test_service"][:connections_total]).to be == 42 |
482 | | - |
| 482 | + |
483 | 483 | # Now trigger a resize: register one more worker — the free list is empty |
484 | 484 | # so SegmentAllocator#allocate will call resize before handing out a slot. |
485 | 485 | resize_registry = Async::Utilization::Registry.new |
|
494 | 494 | resize_controller.define_singleton_method(:id){999} |
495 | 495 | resize_controller.define_singleton_method(:state){{name: "filler"}} |
496 | 496 | resize_controller.define_singleton_method(:worker){resize_worker} |
497 | | - |
| 497 | + |
498 | 498 | size_before_resize = small_monitor.instance_variable_get(:@allocator).size |
499 | 499 | small_monitor.register(resize_controller) |
500 | 500 | size_after_resize = small_monitor.instance_variable_get(:@allocator).size |
501 | | - |
| 501 | + |
502 | 502 | # Confirm the resize actually happened |
503 | 503 | expect(size_after_resize).to be > size_before_resize |
504 | | - |
| 504 | + |
505 | 505 | # The pre-resize worker must still be able to write through its Observer |
506 | 506 | # and have the supervisor read the updated value. |
507 | 507 | worker_registry.metric(:connections_total).set(99) |
508 | 508 | worker_registry.metric(:connections_active).set(3) |
509 | | - |
| 509 | + |
510 | 510 | status_after = small_monitor.status |
511 | 511 | expect(status_after[:data]).to have_keys("test_service") |
512 | 512 | expect(status_after[:data]["test_service"][:connections_total]).to be == 99 |
513 | 513 | expect(status_after[:data]["test_service"][:connections_active]).to be == 3 |
514 | 514 | end |
515 | | - |
| 515 | + |
516 | 516 | with "#run" do |
517 | 517 | include Sus::Fixtures::Async::SchedulerContext |
518 | 518 |
|
|
0 commit comments