Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Latest
* [#483](https://github.com/cleverage/process-bundle/issues/483) Documentation: an exception thrown by `IterableTaskInterface::next()` makes the process fail right away with this exception, the `error_strategy` and the `error_outputs` of the task do not apply.

## Fixes
* [#499](https://github.com/cleverage/process-bundle/issues/499) `process_launcher`: a process stopped by a `StopTask` no longer waits for the end of the running sub-processes in the flush of the task, they are stopped together when the task is finalized, as documented (the process ended after its longest sub-process). Update documentation, add tests.
* [#481](https://github.com/cleverage/process-bundle/issues/481) A stop without error (`StopTask`, `ProcessState::stop()`) only stops the flow it happened in, as documented: the outputs of another root task, of a blocking task proceeded or of a flushable task flushed after the stop go on through the tasks of the stopped flow, which stayed stopped and dropped them silently. An iterable task whose iteration has been interrupted by the stop, and a task whose initialization has failed (deprecated), stay stopped. Update documentation, add tests.
* [#475](https://github.com/cleverage/process-bundle/issues/475) Generic transformers: restore, deprecated, the former names (with underscores instead of dashes) of their transformer codes and contextual options, which no longer worked since 5.9 ([#438](https://github.com/cleverage/process-bundle/issues/438)): a transformer code with a dash that is only registered with underscores (`array-first` for `array_first`), and a contextual option with a dash given or used by its former name (`the_prefix`, `{{ the_prefix }}` for `the-prefix`). Update documentation, add tests.
* [#491](https://github.com/cleverage/process-bundle/issues/491) `CounterTask`: `flush_every: 0` is rejected when the options are resolved, with a clear message, instead of failing on the first execution with `Modulo by zero`; a negative `flush_every`, which works as its absolute value, is deprecated. Update documentation, add tests.
Expand Down
3 changes: 2 additions & 1 deletion docs/reference/tasks/process_launcher_task.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ stopped and a `RuntimeException` is thrown.

When the process fails or is stopped (stop request, [StopTask](stop_task.md)) while sub-processes are still running,
they are stopped when the task is finalized (a warning is logged), and the JSON stream files not output yet are removed:
the sub-processes no longer go on with their side effects after the end of the process.
the sub-processes no longer go on with their side effects after the end of the process. A process stopped by a
[StopTask](stop_task.md) does not wait for them in the flush of the task.

The sub-processes are stopped together: `SIGTERM` is sent to all of them, then `SIGKILL` to the ones still running
after 5 seconds, whatever their number (within the grace period of `docker stop` or Kubernetes).
Expand Down
12 changes: 12 additions & 0 deletions src/Task/Process/ProcessLauncherTask.php
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,13 @@ public function execute(ProcessState $state): void

public function flush(ProcessState $state): void
{
// A stopped process does not wait for its sub-processes: they are stopped when the task is finalized
if ($state->getProcessHistory()->isStopped()) {
$this->flushMode = false;
$state->setSkipped(true);

return;
}
$this->flushMode = true;
if (!$this->finishedBuffers->isEmpty()) {
$state->setOutput($this->finishedBuffers->dequeue());
Expand All @@ -127,6 +134,11 @@ public function flush(ProcessState $state): void

public function next(ProcessState $state): bool
{
if ($state->getProcessHistory()->isStopped()) {
$this->flushMode = false;

return false;
}
$this->handleProcesses($state);

// if there is some data waiting, handle it in priority
Expand Down
25 changes: 25 additions & 0 deletions tests/Task/Process/ProcessLauncherTaskTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,31 @@ public function testTheSubprocessesAreStoppedWhenTheTaskIsFinalized(): void
$this->assertFalse($task->next($state));
}

/**
* A process stopped by a StopTask does not wait for the running sub-processes in the flush of the task: they are
* stopped when the task is finalized.
*/
public function testAStoppedProcessDoesNotWaitForTheSubprocesses(): void
{
[$task, $state] = $this->launch('sleep', wait: false);
$launchedProcesses = (new \ReflectionProperty($task, 'launchedProcesses'))->getValue($task);
$this->assertIsArray($launchedProcesses);
$runningSubprocess = reset($launchedProcesses);
$this->assertInstanceOf(SubprocessInstance::class, $runningSubprocess);

$state->getProcessHistory()->setStopped();
$state->reset(true);
$task->flush($state);

$this->assertTrue($state->isSkipped());
$this->assertFalse($task->next($state));
$this->assertTrue($runningSubprocess->getProcess()->isRunning());

$task->finalize($state);

$this->assertFalse($runningSubprocess->getProcess()->isRunning());
}

/**
* The buffers of the terminated sub-processes, not output yet when the process fails, are removed too: they were
* left in the temporary directory.
Expand Down
Loading