Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit9b6dba1

Browse files
committed
feature#46242 [Console] Add support for resuming a ProgressBar (yivi)
This PR was squashed before being merged into the 6.2 branch.Discussion----------[Console] Add support for resuming a ProgressBarAdd an `(int) $resumeAt` argument for `ProgressBar#start()`, so that the progress bar is initialized at a specific progress level, with a new property so that `getEstimated()` and `getRemaining()` report the right number.| Q | A| ------------- | ---| Branch? | 6.1| Bug fix? | no| New feature? | yes| Deprecations? | no| License | MITAs pointed out on a recently posted [SO question](https://stackoverflow.com/q/72097256/1426539)), when working on a longish task one may want to create a progress bar for a _resumed_ task.Calling `advance()` works to increase the progress bar counter, but the results of `getRemaining()` and `getEstimated()` will be "broken", since whatever steps one "skipped" will be considered to have taken 0 seconds. For a longer running task, the estimation will be **very** inaccurate, and will remain so for a long while. Using the example code from the linked question:```php$itemCount = 1_000_000;$startItem = 150_000;$progressBar = new ProgressBar($output, $itemCount);$progressBar->setFormat( $progressBar->getFormatDefinition(ProgressBar::FORMAT_DEBUG));$progressBar->start();if ($startItem !== 0) { // unfortunately taken into account in ETA calculation $progressBar->advance($startItem);}for ($i = $startItem; $i < $itemCount; $i++) { usleep(50_000); $progressBar->advance();}```This will output this to begin with:```none150038/1000000 [====>-----------------------] 15% 2 secs/13 secs 20.0 MiB```The estimated time will keep growing as the tasks progresses, but the estimation won't be remotely useful for a long while.This PR adds a `$resumeAt` parameter to `ProgresBar#start()`, so that's possible to write:```php$bar = new ProgressBar($output, 1_200_000, 0);$bar->start(null, 300_000);```And calls to `$bar->getEstimated()` and `$bar->getRemaining()` will return sane results (and calling the initial `->advance()` would be no longer necessary).### TODO:- [ ] submit changes to the documentation (if the PR is well received)Commits-------8e1596e [Console] Add support for resuming a ProgressBar
2 parents7f7d839 +8e1596e commit9b6dba1

File tree

3 files changed

+76
-7
lines changed

3 files changed

+76
-7
lines changed

‎src/Symfony/Component/Console/CHANGELOG.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ CHANGELOG
1414
* Add method`__toString()` to`InputInterface`
1515
* Deprecate`Command::$defaultName` and`Command::$defaultDescription`, use the`AsCommand` attribute instead
1616
* Add suggested values for arguments and options in input definition, for input completion
17+
* Add`$resumeAt` parameter to`ProgressBar#start()`, so that one can easily 'resume' progress on longer tasks, and still get accurate`getEstimate()` and`getRemaining()` results.
1718

1819
6.0
1920
---

‎src/Symfony/Component/Console/Helper/ProgressBar.php‎

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ final class ProgressBar
4949
privatefloat$maxSecondsBetweenRedraws =1;
5050
privateOutputInterface$output;
5151
privateint$step =0;
52+
privateint$resumedStep =0;
5253
private ?int$max =null;
5354
privateint$startTime;
5455
privateint$stepWidth;
@@ -199,11 +200,11 @@ public function getBarOffset(): float
199200

200201
publicfunctiongetEstimated():float
201202
{
202-
if (!$this->step) {
203+
if (0 ===$this->step ||$this->step ===$this->resumedStep) {
203204
return0;
204205
}
205206

206-
returnround((time() -$this->startTime) /$this->step *$this->max);
207+
returnround((time() -$this->startTime) /($this->step -$this->resumedStep) *$this->max);
207208
}
208209

209210
publicfunctiongetRemaining():float
@@ -212,7 +213,7 @@ public function getRemaining(): float
212213
return0;
213214
}
214215

215-
returnround((time() -$this->startTime) /$this->step * ($this->max -$this->step));
216+
returnround((time() -$this->startTime) /($this->step -$this->resumedStep) * ($this->max -$this->step));
216217
}
217218

218219
publicfunctionsetBarWidth(int$size)
@@ -302,13 +303,17 @@ public function iterate(iterable $iterable, int $max = null): iterable
302303
/**
303304
* Starts the progress output.
304305
*
305-
* @param int|null $max Number of steps to complete the bar (0 if indeterminate), null to leave unchanged
306+
* @param int|null $max Number of steps to complete the bar (0 if indeterminate), null to leave unchanged
307+
* @param int $resumeAt when restarting a previously started progress, set on what step we are restarting so that time estimations are calculated correctly, and the
308+
* progress is automatically set to the appropriate step
306309
*/
307-
publicfunctionstart(int$max =null)
310+
publicfunctionstart(int$max =null,int$resumeAt =0):void
308311
{
309312
$this->startTime =time();
310-
$this->step =0;
311-
$this->percent =0.0;
313+
$this->step =$resumeAt;
314+
$this->resumedStep =$resumeAt;
315+
316+
$resumeAt >0 ?$this->setProgress($resumeAt) :$this->percent =0.0;
312317

313318
if (null !==$max) {
314319
$this->setMaxSteps($max);

‎src/Symfony/Component/Console/Tests/Helper/ProgressBarTest.php‎

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,69 @@ public function testAdvance()
6666
);
6767
}
6868

69+
publicfunctiontestResumeNoMax()
70+
{
71+
$bar =newProgressBar($output =$this->getOutputStream(),0,0);
72+
$bar->start(null,15);
73+
$bar->advance();
74+
75+
rewind($output->getStream());
76+
77+
$this->assertEquals(
78+
' 15 [--------------->------------]'.
79+
$this->generateOutput(' 16 [---------------->-----------]'),
80+
stream_get_contents($output->getStream())
81+
);
82+
}
83+
84+
publicfunctiontestResumeWithMax()
85+
{
86+
$bar =newProgressBar($output =$this->getOutputStream(),5000,0);
87+
$bar->start(null,1000);
88+
89+
rewind($output->getStream());
90+
91+
$this->assertEquals(
92+
' 1000/5000 [=====>----------------------] 20%',
93+
stream_get_contents($output->getStream())
94+
);
95+
}
96+
97+
publicfunctiontestRegularTimeEstimation()
98+
{
99+
$bar =newProgressBar($output =$this->getOutputStream(),1_200,0);
100+
$bar->start();
101+
102+
$bar->advance();
103+
$bar->advance();
104+
105+
sleep(1);
106+
107+
$this->assertEquals(
108+
600.0,
109+
$bar->getEstimated()
110+
);
111+
}
112+
113+
publicfunctiontestResumedTimeEstimation()
114+
{
115+
$bar =newProgressBar($output =$this->getOutputStream(),1_200,0);
116+
$bar->start(null,599);
117+
$bar->advance();
118+
119+
sleep(1);
120+
121+
$this->assertEquals(
122+
1_200.0,
123+
$bar->getEstimated()
124+
);
125+
126+
$this->assertEquals(
127+
600.0,
128+
$bar->getRemaining()
129+
);
130+
}
131+
69132
publicfunctiontestAdvanceWithStep()
70133
{
71134
$bar =newProgressBar($output =$this->getOutputStream(),0,0);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp