Forgetting jobs can release a lot of memory and perform a lot of destructors. Since this happens in synchronous code, it can stall the event loop, which can lead to e.g. missing worker heartbeats and other problems. We thus return the forgotten jobs, so that we can drop them later in a separate thread.
(
state_ref: &StateRef,
senders: &Senders,
selector: &IdSelector,
allowed_statuses: Vec<Status>,
)
| 790 | /// |
| 791 | /// We thus return the forgotten jobs, so that we can drop them later in a separate thread. |
| 792 | fn handle_job_forget( |
| 793 | state_ref: &StateRef, |
| 794 | senders: &Senders, |
| 795 | selector: &IdSelector, |
| 796 | allowed_statuses: Vec<Status>, |
| 797 | ) -> (ToClientMessage, Vec<Job>) { |
| 798 | let mut state = state_ref.get_mut(); |
| 799 | let job_ids: Vec<JobId> = get_job_ids(&state, selector); |
| 800 | let mut forgotten: usize = 0; |
| 801 | |
| 802 | let mut forgotten_jobs = Vec::with_capacity(job_ids.len()); |
| 803 | for &job_id in &job_ids { |
| 804 | let can_be_forgotten = state |
| 805 | .get_job(job_id) |
| 806 | .map(|j| { |
| 807 | j.is_terminated() && allowed_statuses.contains(&job_status(&j.make_job_info(false))) |
| 808 | }) |
| 809 | .unwrap_or(false); |
| 810 | if can_be_forgotten { |
| 811 | if let Some(job) = state.forget_job(job_id) { |
| 812 | forgotten_jobs.push(job); |
| 813 | } |
| 814 | forgotten += 1; |
| 815 | } |
| 816 | } |
| 817 | state.try_release_memory(); |
| 818 | senders.server_control.try_release_memory(); |
| 819 | |
| 820 | let ignored = job_ids.len() - forgotten; |
| 821 | |
| 822 | ( |
| 823 | ToClientMessage::ForgetJobResponse(ForgetJobResponse { forgotten, ignored }), |
| 824 | forgotten_jobs, |
| 825 | ) |
| 826 | } |
| 827 | |
| 828 | fn handle_get_list(state_ref: &StateRef, workers: bool) -> ToClientMessage { |
| 829 | let state = state_ref.get(); |
no test coverage detected