Skip to content

Commit a91f313

Browse files
committed
feat: move streaming output helps to command base class
Signed-off-by: Robin Appelman <[email protected]>
1 parent a157ba7 commit a91f313

File tree

4 files changed

+61
-60
lines changed

4 files changed

+61
-60
lines changed

apps/files/lib/Command/Object/ListObject.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ public function execute(InputInterface $input, OutputInterface $output): int {
4242
return self::FAILURE;
4343
}
4444
$objects = $objectStore->listObjects();
45-
$this->objectUtils->writeIteratorToOutput($input, $output, $objects, self::CHUNK_SIZE);
45+
$objects = $this->objectUtils->formatObjects($objects, $input->getOption('output') === self::OUTPUT_FORMAT_PLAIN);
46+
$this->writeStreamingTableInOutputFormat($input, $output, $objects, self::CHUNK_SIZE);
4647

4748
return self::SUCCESS;
4849
}

apps/files/lib/Command/Object/ObjectUtil.php

Lines changed: 5 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,14 @@
88

99
namespace OCA\Files\Command\Object;
1010

11-
use OC\Core\Command\Base;
1211
use OCP\DB\QueryBuilder\IQueryBuilder;
1312
use OCP\Files\ObjectStore\IObjectStore;
1413
use OCP\IConfig;
1514
use OCP\IDBConnection;
1615
use OCP\Util;
17-
use Symfony\Component\Console\Input\InputInterface;
1816
use Symfony\Component\Console\Output\OutputInterface;
1917

20-
class ObjectUtil extends Base {
18+
class ObjectUtil {
2119
public function __construct(
2220
private IConfig $config,
2321
private IDBConnection $connection,
@@ -95,36 +93,13 @@ public function objectExistsInDb(string $object): int|false {
9593
return $fileId;
9694
}
9795

98-
public function writeIteratorToOutput(InputInterface $input, OutputInterface $output, \Iterator $objects, int $chunkSize): void {
99-
$outputType = $input->getOption('output');
100-
$humanOutput = $outputType === Base::OUTPUT_FORMAT_PLAIN;
101-
102-
if ($humanOutput) {
103-
// we can't write tables in a streaming way, so we print them in chunks instead
104-
foreach ($this->chunkIterator($objects, $chunkSize) as $chunk) {
105-
$this->outputChunkHuman($input, $output, $chunk);
106-
}
107-
} else {
108-
$first = true;
109-
110-
$output->writeln('[');
111-
foreach ($objects as $object) {
112-
if (!$first) {
113-
$output->writeln(',');
114-
}
115-
$row = $this->formatObject($object, false);
116-
if ($outputType === self::OUTPUT_FORMAT_JSON_PRETTY) {
117-
$output->write(json_encode($row, JSON_PRETTY_PRINT));
118-
} else {
119-
$output->write(json_encode($row));
120-
}
121-
$first = false;
122-
}
123-
$output->writeln("\n]");
96+
public function formatObjects(\Iterator $objects, bool $humanOutput): \Iterator {
97+
foreach ($objects as $object) {
98+
yield $this->formatObject($object, $humanOutput);
12499
}
125100
}
126101

127-
private function formatObject(array $object, bool $humanOutput): array {
102+
public function formatObject(array $object, bool $humanOutput): array {
128103
$row = array_merge([
129104
'urn' => $object['urn'],
130105
], ($object['metadata'] ?? []));
@@ -137,31 +112,4 @@ private function formatObject(array $object, bool $humanOutput): array {
137112
}
138113
return $row;
139114
}
140-
141-
private function outputChunkHuman(InputInterface $input, OutputInterface $output, iterable $chunk): void {
142-
$result = [];
143-
foreach ($chunk as $object) {
144-
$result[] = $this->formatObject($object, true);
145-
}
146-
$this->writeTableInOutputFormat($input, $output, $result);
147-
}
148-
149-
public function chunkIterator(\Iterator $iterator, int $count): \Iterator {
150-
$chunk = [];
151-
152-
for ($i = 0; $iterator->valid(); $i++) {
153-
$chunk[] = $iterator->current();
154-
$iterator->next();
155-
if (count($chunk) == $count) {
156-
// Got a full chunk, yield and start a new one
157-
yield $chunk;
158-
$chunk = [];
159-
}
160-
}
161-
162-
if (count($chunk)) {
163-
// Yield the last chunk even if incomplete
164-
yield $chunk;
165-
}
166-
}
167115
}

apps/files/lib/Command/Object/Orphans.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,9 @@ public function execute(InputInterface $input, OutputInterface $output): int {
6363
$fileId = (int)substr($object['urn'], $prefixLength);
6464
return !$this->fileIdInDb($fileId);
6565
});
66-
$orphans->rewind();
6766

68-
$this->objectUtils->writeIteratorToOutput($input, $output, $orphans, self::CHUNK_SIZE);
67+
$orphans = $this->objectUtils->formatObjects($orphans, $input->getOption('output') === self::OUTPUT_FORMAT_PLAIN);
68+
$this->writeStreamingTableInOutputFormat($input, $output, $orphans, self::CHUNK_SIZE);
6969

7070
return self::SUCCESS;
7171
}

core/Command/Base.php

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,58 @@ protected function writeTableInOutputFormat(InputInterface $input, OutputInterfa
8888
}
8989
}
9090

91+
protected function writeStreamingTableInOutputFormat(InputInterface $input, OutputInterface $output, \Iterator $items, int $tableGroupSize): void {
92+
switch ($input->getOption('output')) {
93+
case self::OUTPUT_FORMAT_JSON:
94+
case self::OUTPUT_FORMAT_JSON_PRETTY:
95+
$this->writeStreamingJsonArray($input, $output, $items);
96+
break;
97+
default:
98+
foreach ($this->chunkIterator($items, $tableGroupSize) as $chunk) {
99+
$this->writeTableInOutputFormat($input, $output, $chunk);
100+
}
101+
break;
102+
}
103+
}
104+
105+
protected function writeStreamingJsonArray(InputInterface $input, OutputInterface $output, \Iterator $items): void {
106+
$first = true;
107+
$outputType = $input->getOption('output');
108+
109+
$output->writeln('[');
110+
foreach ($items as $item) {
111+
if (!$first) {
112+
$output->writeln(',');
113+
}
114+
if ($outputType === self::OUTPUT_FORMAT_JSON_PRETTY) {
115+
$output->write(json_encode($item, JSON_PRETTY_PRINT));
116+
} else {
117+
$output->write(json_encode($item));
118+
}
119+
$first = false;
120+
}
121+
$output->writeln("\n]");
122+
}
123+
124+
public function chunkIterator(\Iterator $iterator, int $count): \Iterator {
125+
$chunk = [];
126+
127+
for ($i = 0; $iterator->valid(); $i++) {
128+
$chunk[] = $iterator->current();
129+
$iterator->next();
130+
if (count($chunk) == $count) {
131+
// Got a full chunk, yield and start a new one
132+
yield $chunk;
133+
$chunk = [];
134+
}
135+
}
136+
137+
if (count($chunk)) {
138+
// Yield the last chunk even if incomplete
139+
yield $chunk;
140+
}
141+
}
142+
91143

92144
/**
93145
* @param mixed $item

0 commit comments

Comments
 (0)