Repository navigation
Iterable file readers keep their state after a complete iteration: FolderBrowserTask, InputFolderBrowserTask, CsvReaderTask, LineReaderTask #208
Description
Description
FolderBrowserTask, CsvReaderTask and LineReaderTask (and their Input* variants) do not reset their internal iterator or file once an iteration is finished. If the task runs again, for example because it receives a second input from an upstream iterable task, it does not start over:
FolderBrowserTask/InputFolderBrowserTask, same folder twice: the second pass logs a false "No item found" and outputs nothing.InputFolderBrowserTask, two different folders: throwsLogicException: Folder path '…/dB' already initialized with a different value …/dA, the folder path being only cleared onflush().CsvReaderTask/InputCsvReaderTask, same path twice: the second pass outputs nothing (skipped).LineReaderTask/InputLineReaderTask, same path twice: the second pass outputsfalse.
JsonStreamReaderTask, CsvSplitterTask and AbstractIterableOutputTask already release their state at the end of the iteration.
Reproduction
clever_age_process:
configurations:
demo.readers_reset.folder:
tasks:
folders:
service: '@CleverAge\ProcessBundle\Task\ConstantIterableOutputTask'
options:
output: ['/var/www/var/readers-reset/dA', '/var/www/var/readers-reset/dA', '/var/www/var/readers-reset/dB']
outputs: [browse]
browse:
service: '@CleverAge\ProcessBundle\Task\File\InputFolderBrowserTask'
outputs: [debug_folder]
debug_folder:
service: '@CleverAge\ProcessBundle\Task\Debug\DebugTask'
demo.readers_reset.csv:
tasks:
csv_files:
service: '@CleverAge\ProcessBundle\Task\ConstantIterableOutputTask'
options:
output: ['/var/www/var/readers-reset/a.csv', '/var/www/var/readers-reset/a.csv']
outputs: [read_csv]
read_csv:
service: '@CleverAge\ProcessBundle\Task\File\Csv\InputCsvReaderTask'
outputs: [debug_csv]
debug_csv:
service: '@CleverAge\ProcessBundle\Task\Debug\DebugTask'
demo.readers_reset.line:
tasks:
text_files:
service: '@CleverAge\ProcessBundle\Task\ConstantIterableOutputTask'
options:
output: ['/var/www/var/readers-reset/a.txt', '/var/www/var/readers-reset/a.txt']
outputs: [read_lines]
read_lines:
service: '@CleverAge\ProcessBundle\Task\File\InputLineReaderTask'
outputs: [debug_line]
debug_line:
service: '@CleverAge\ProcessBundle\Task\Debug\DebugTask'Data: dA/f1.txt, dB/f2.txt, a.csv = id;name\n1;foo\n2;bar\n, a.txt = l1\nl2\n.
Output on main (c1a2804, PHP 8.5, Symfony 7.4):
Starting process 'demo.readers_reset.folder'...
"/var/www/var/readers-reset/dA/f1.txt"
WARNING [cleverage_process_task] No item found in path /var/www/var/readers-reset/dA
CRITICAL [cleverage_process_task] Folder path '/var/www/var/readers-reset/dB' already initialized with a different value /var/www/var/readers-reset/dA
Starting process 'demo.readers_reset.csv'...
array:2 [ "id" => "1" "name" => "foo" ]
array:2 [ "id" => "2" "name" => "bar" ]
Process 'demo.readers_reset.csv' executed successfully <- second input produced nothing
Starting process 'demo.readers_reset.line'...
"l1\n"
"l2\n"
false <- second input
Process 'demo.readers_reset.line' executed successfully
Expected: dA/f1.txt, dA/f1.txt, dB/f2.txt; the two CSV rows twice; "l1\n", "l2\n" twice.
Cause
FolderBrowserTask::next()returns$this->files->valid()but never resets the exhausted iterator: the nextexecute()finds$files !== null, skips the re-initialization and logs "No item found".InputFolderBrowserTask::getOptions()keeps$folderPathuntilflush(), so a different folder received afterwards throws.CsvReaderTask::execute()only re-opens the file when the path changes, andCsvReaderTask::next()never releases it at end of file.- Same for
LineReaderTask::execute()andLineReaderTask::next().
Proposed fix
Release the state in next() once the iteration is over, as JsonStreamReaderTask::next() already does:
FolderBrowserTask: reset$filestonull;InputFolderBrowserTask: overridenext()to also reset$folderPath(a different path received mid-iteration still throws);CsvReaderTask: close the CSV file and reset it tonull;LineReaderTask: reset theSplFileObjecttonull.
The Input* variants inherit the fix: each new input, same path or not, is read from its beginning. Update the reference documentation, add unit tests.
Requirements
- Documentation updates
- Reference
- Cookbooks
- Changelog
- Unit tests
Breaking changes
None.
Activity
Merge pull request #219 from cleverage/208