fix(controller): size the config-push barrier for loaded hosts and admit its wait (bug-1914)
The configAck byte-delivery barrier waited 500 ms, below scheduling delay on an oversubscribed host, so a push to a healthy majority was rejected with -110 while its already-appended marker still committed. CONF_PUSH_TIMEOUT_MS is now 2000 ms, the wait holds a commit-wait admission slot (new commit_blocking_admit/release; a full budget fails fast with not-ready), and the timeout reply no longer claims the change was not committed. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
431a6d709e
commit
06e99b9081
6 changed files with 101 additions and 4 deletions
|
|
@ -1185,6 +1185,50 @@ static void test_configack_self_plus_one_covering_is_majority_of_three(void)
|
|||
printf("test_configack_self_plus_one_covering_is_majority_of_three: PASS\n");
|
||||
}
|
||||
|
||||
|
||||
/* bug-1914: under heavy CPU load (40 busy loops on 32 cores) a standby's
|
||||
* config ACK arrives a few hundred ms late; the 500 ms barrier rejected a push
|
||||
* whose marker then committed anyway (client told -110, cluster activated
|
||||
* it). An ACK landing 700 ms in must still meet the production barrier
|
||||
* bound, and while it waits the barrier holds a commit-wait admission slot
|
||||
* (bounded blocking on a vtask is allowed only under that reservation). */
|
||||
static atomic_int g_1914_inflight_seen;
|
||||
|
||||
static void* b1914_late_config_ack(void* arg)
|
||||
{
|
||||
(void)arg;
|
||||
usleep(100 * 1000);
|
||||
pthread_mutex_lock(&g_bce.lock);
|
||||
atomic_store(&g_1914_inflight_seen, g_bce.inflight_waits);
|
||||
pthread_mutex_unlock(&g_bce.lock);
|
||||
usleep(600 * 1000);
|
||||
repl_on_config_ack(&g_bp.repl, &g_bep_a, 0x100);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void test_configack_late_ack_under_load_meets_barrier(void)
|
||||
{
|
||||
pthread_t th;
|
||||
int rc;
|
||||
|
||||
barrier_setup(3, 2, 0);
|
||||
atomic_store(&g_1914_inflight_seen, -1);
|
||||
TEST_ASSERT_EQUAL_INT(0, pthread_create(&th, NULL, b1914_late_config_ack,
|
||||
NULL));
|
||||
rc = repl_wait_majority_ack(&g_bp.repl, 0x100, CONF_PUSH_TIMEOUT_MS,
|
||||
(uint8_t)OPCode_upgradeConfigAck);
|
||||
pthread_join(th, NULL);
|
||||
|
||||
TEST_ASSERT_EQUAL_INT_MESSAGE(0, rc,
|
||||
"bug-1914: a config ACK 700 ms late (CPU-oversubscribed standby) must "
|
||||
"still meet the config-push barrier");
|
||||
TEST_ASSERT_EQUAL_INT_MESSAGE(1, atomic_load(&g_1914_inflight_seen),
|
||||
"bug-1914: the configAck wait must hold a commit-wait admission slot");
|
||||
TEST_ASSERT_EQUAL_INT(0, g_bce.inflight_waits);
|
||||
|
||||
barrier_teardown();
|
||||
printf("test_configack_late_ack_under_load_meets_barrier: PASS\n");
|
||||
}
|
||||
/* n_peers=1: single-member cluster — immediate success without consuming
|
||||
* the timeout. PIN: green today (via the n_active == 0 short-circuit) and
|
||||
* green after task 5.2 (explicit n_peers <= 1 rule). */
|
||||
|
|
@ -2530,6 +2574,7 @@ void test_commit_barrier_rollout(void)
|
|||
RUN_TEST(test_configack_previous_tag_ack_does_not_count);
|
||||
RUN_TEST(test_configack_no_active_standbys_times_out);
|
||||
RUN_TEST(test_configack_self_plus_one_covering_is_majority_of_three);
|
||||
RUN_TEST(test_configack_late_ack_under_load_meets_barrier);
|
||||
RUN_TEST(test_configack_single_member_immediate_success);
|
||||
RUN_TEST(test_push_config_withheld_acks_returns_etimedout);
|
||||
RUN_TEST(test_push_config_majority_acks_returns_zero_and_commits);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue