Spawn the GC task and return a [`JoinHandle`]. `array_snapshot_hlcs` is the shared map that `ArrayFanout`'s `snapshot_trigger` reads to know the current GC boundary per array. The GC task writes the updated `snapshot_hlc` after each successful compaction run.
(
op_log: Arc<OriginOpLog>,
snapshots: Arc<OriginSnapshotStore>,
ack_registry: Arc<ArrayAckRegistry>,
array_snapshot_hlcs: Arc<RwLock<HashMap<String, Hlc>>>,
shutdown: Arc<Shutdown
| 40 | /// The GC task writes the updated `snapshot_hlc` after each successful |
| 41 | /// compaction run. |
| 42 | pub fn spawn( |
| 43 | op_log: Arc<OriginOpLog>, |
| 44 | snapshots: Arc<OriginSnapshotStore>, |
| 45 | ack_registry: Arc<ArrayAckRegistry>, |
| 46 | array_snapshot_hlcs: Arc<RwLock<HashMap<String, Hlc>>>, |
| 47 | shutdown: Arc<ShutdownWatch>, |
| 48 | interval: Duration, |
| 49 | ) -> Option<JoinHandle<()>> { |
| 50 | let Ok(handle) = tokio::runtime::Handle::try_current() else { |
| 51 | debug!("array_gc_task: no tokio runtime; skipping spawn (test or non-async context)"); |
| 52 | return None; |
| 53 | }; |
| 54 | Some(handle.spawn(async move { |
| 55 | let mut shutdown_rx: ShutdownReceiver = shutdown.subscribe(); |
| 56 | loop { |
| 57 | tokio::select! { |
| 58 | _ = tokio::time::sleep(interval) => { |
| 59 | run_gc( |
| 60 | &op_log, |
| 61 | &snapshots, |
| 62 | &ack_registry, |
| 63 | &array_snapshot_hlcs, |
| 64 | ); |
| 65 | } |
| 66 | _ = shutdown_rx.wait_cancelled() => { |
| 67 | debug!("array_gc_task: shutdown received — exiting"); |
| 68 | return; |
| 69 | } |
| 70 | } |
| 71 | } |
| 72 | })) |
| 73 | } |
| 74 | |
| 75 | /// Execute one GC pass across all known arrays. |
| 76 | fn run_gc( |