diff --git a/pageserver/src/tenant.rs b/pageserver/src/tenant.rs index bc4656e60c945..67f155ed834c0 100644 --- a/pageserver/src/tenant.rs +++ b/pageserver/src/tenant.rs @@ -2618,6 +2618,9 @@ impl Tenant { for (timeline_id, timeline, (can_compact, can_offload)) in &timelines_to_compact_or_offload { + // pending_task_left == None: cannot compact, maybe still pending tasks + // pending_task_left == Some(true): compaction task left + // pending_task_left == Some(false): no compaction task left let pending_task_left = if *can_compact { let has_pending_l0_compaction_task = timeline .compact(cancel, EnumSet::empty(), ctx) @@ -2637,12 +2640,18 @@ impl Tenant { .fail(&CIRCUIT_BREAKERS_BROKEN, e); } })?; - if !has_pending_l0_compaction_task { + if has_pending_l0_compaction_task { + Some(true) + } else { + let has_pending_scheduled_compaction_task; let next_scheduled_compaction_task = { let mut guard = self.scheduled_compaction_tasks.lock().unwrap(); if let Some(tline_pending_tasks) = guard.get_mut(timeline_id) { - tline_pending_tasks.pop_front() + let next_task = tline_pending_tasks.pop_front(); + has_pending_scheduled_compaction_task = !tline_pending_tasks.is_empty(); + next_task } else { + has_pending_scheduled_compaction_task = false; None } }; @@ -2654,7 +2663,6 @@ impl Tenant { .contains(CompactFlags::EnhancedGcBottomMostCompaction) { warn!("ignoring scheduled compaction task: scheduled task must be gc compaction: {:?}", next_scheduled_compaction_task.options); - Some(true) } else { let _ = timeline .compact_with_options( @@ -2668,13 +2676,9 @@ impl Tenant { // TODO: we can send compaction statistics in the future tx.send(()).ok(); } - Some(true) } - } else { - None } - } else { - Some(true) + Some(has_pending_scheduled_compaction_task) } } else { None diff --git a/test_runner/regress/test_compaction.py b/test_runner/regress/test_compaction.py index 497f9c0a46696..e8c5f7c0d750d 100644 --- a/test_runner/regress/test_compaction.py +++ b/test_runner/regress/test_compaction.py @@ -117,13 +117,19 @@ def test_pageserver_compaction_smoke(neon_env_builder: NeonEnvBuilder): def test_pageserver_gc_compaction_smoke(neon_env_builder: NeonEnvBuilder): - env = neon_env_builder.init_start(initial_tenant_conf=AGGRESIVE_COMPACTION_TENANT_CONF) + SMOKE_CONF = { + # Run both gc and gc-compaction. + "gc_period": "5s", + "compaction_period": "5s", + } + + env = neon_env_builder.init_start(initial_tenant_conf=SMOKE_CONF) tenant_id = env.initial_tenant timeline_id = env.initial_timeline row_count = 1000 - churn_rounds = 10 + churn_rounds = 20 ps_http = env.pageserver.http_client() @@ -133,40 +139,25 @@ def test_pageserver_gc_compaction_smoke(neon_env_builder: NeonEnvBuilder): log.info("Writing initial data ...") workload.write_rows(row_count, env.pageserver.id) - # schedule a gc-compaction in advance, it will be triggered along with L0 compaction - ps_http.timeline_compact( - tenant_id, - timeline_id, - enhanced_gc_bottom_most_compaction=True, - body={ - "scheduled": True, - "compact_range": { - "start": "000000000000000000000000000000000000", - "end": "030000000000000000000000000000000000", - }, - }, - ) - for i in range(1, churn_rounds + 1): if i % 10 == 0: log.info(f"Running churn round {i}/{churn_rounds} ...") - workload.churn_rows(row_count, env.pageserver.id) - # Force L0 compaction to ensure the number of layers is within bounds, so that gc-compaction can run. - ps_http.timeline_compact(tenant_id, timeline_id, force_l0_compaction=True) - assert ps_http.perf_info(tenant_id, timeline_id)[0]["num_of_l0"] <= 1 ps_http.timeline_compact( tenant_id, timeline_id, enhanced_gc_bottom_most_compaction=True, body={ + "scheduled": True, "compact_range": { "start": "000000000000000000000000000000000000", "end": "030000000000000000000000000000000000", - } + }, }, ) + workload.churn_rows(row_count, env.pageserver.id) + env.pageserver.assert_log_contains("scheduled_compaction") log.info("Validating at workload end ...")