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

Appearance settings

Commit ad00a85

Browse filesBrowse files
authored
Add throttle method to LazyCollection (#51060)
1 parent 8f42dc0 commit ad00a85
Copy full SHA for ad00a85

File tree

Expand file treeCollapse file tree

3 files changed

+125
-0
lines changed
Filter options
Expand file treeCollapse file tree

3 files changed

+125
-0
lines changed

‎src/Illuminate/Collections/LazyCollection.php

Copy file name to clipboardExpand all lines: src/Illuminate/Collections/LazyCollection.php
+50Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1570,6 +1570,28 @@ public function tapEach(callable $callback)
15701570
});
15711571
}
15721572

1573+
/**
1574+
* Throttle the values, releasing them at most once per the given seconds.
1575+
*
1576+
* @return static<TKey, TValue>
1577+
*/
1578+
public function throttle(float $seconds)
1579+
{
1580+
return new static(function () use ($seconds) {
1581+
$microseconds = $seconds * 1_000_000;
1582+
1583+
foreach ($this as $key => $value) {
1584+
$fetchedAt = $this->preciseNow();
1585+
1586+
yield $key => $value;
1587+
1588+
$sleep = $microseconds - ($this->preciseNow() - $fetchedAt);
1589+
1590+
$this->usleep((int) $sleep);
1591+
}
1592+
});
1593+
}
1594+
15731595
/**
15741596
* Flatten a multi-dimensional associative array with dots.
15751597
*
@@ -1781,4 +1803,32 @@ protected function now()
17811803
? Carbon::now()->timestamp
17821804
: time();
17831805
}
1806+
1807+
/**
1808+
* Get the precise current time.
1809+
*
1810+
* @return float
1811+
*/
1812+
protected function preciseNow()
1813+
{
1814+
return class_exists(Carbon::class)
1815+
? Carbon::now()->getPreciseTimestamp()
1816+
: microtime(true) * 1_000_000;
1817+
}
1818+
1819+
/**
1820+
* Sleep for the given amount of microseconds.
1821+
*
1822+
* @return void
1823+
*/
1824+
protected function usleep(int $microseconds)
1825+
{
1826+
if ($microseconds <= 0) {
1827+
return;
1828+
}
1829+
1830+
class_exists(Sleep::class)
1831+
? Sleep::usleep($microseconds)
1832+
: usleep($microseconds);
1833+
}
17841834
}

‎tests/Support/SupportLazyCollectionIsLazyTest.php

Copy file name to clipboardExpand all lines: tests/Support/SupportLazyCollectionIsLazyTest.php
+20Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Illuminate\Support\ItemNotFoundException;
88
use Illuminate\Support\LazyCollection;
99
use Illuminate\Support\MultipleItemsFoundException;
10+
use Illuminate\Support\Sleep;
1011
use Mockery as m;
1112
use PHPUnit\Framework\TestCase;
1213
use stdClass;
@@ -1370,6 +1371,25 @@ public function testTapEachIsLazy()
13701371
});
13711372
}
13721373

1374+
public function testThrottleIsLazy()
1375+
{
1376+
Sleep::fake();
1377+
1378+
$this->assertDoesNotEnumerate(function ($collection) {
1379+
$collection->throttle(10);
1380+
});
1381+
1382+
$this->assertEnumerates(5, function ($collection) {
1383+
$collection->throttle(10)->take(5)->all();
1384+
});
1385+
1386+
$this->assertEnumeratesOnce(function ($collection) {
1387+
$collection->throttle(10)->all();
1388+
});
1389+
1390+
Sleep::fake(false);
1391+
}
1392+
13731393
public function testTimesIsLazy()
13741394
{
13751395
$data = LazyCollection::times(INF);

‎tests/Support/SupportLazyCollectionTest.php

Copy file name to clipboardExpand all lines: tests/Support/SupportLazyCollectionTest.php
+55Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@
22

33
namespace Illuminate\Tests\Support;
44

5+
use Carbon\CarbonInterval as Duration;
6+
use Illuminate\Foundation\Testing\Wormhole;
57
use Illuminate\Support\Carbon;
68
use Illuminate\Support\Collection;
79
use Illuminate\Support\LazyCollection;
10+
use Illuminate\Support\Sleep;
811
use InvalidArgumentException;
912
use Mockery as m;
1013
use PHPUnit\Framework\TestCase;
@@ -223,6 +226,58 @@ public function testTapEach()
223226
$this->assertSame([1, 2, 3, 4, 5], $tapped);
224227
}
225228

229+
public function testThrottle()
230+
{
231+
Sleep::fake();
232+
233+
$data = LazyCollection::times(3)
234+
->throttle(2)
235+
->all();
236+
237+
Sleep::assertSlept(function (Duration $duration) {
238+
$this->assertEqualsWithDelta(
239+
2_000_000, $duration->totalMicroseconds, 1_000
240+
);
241+
242+
return true;
243+
}, times: 3);
244+
245+
$this->assertSame([1, 2, 3], $data);
246+
247+
Sleep::fake(false);
248+
}
249+
250+
public function testThrottleAccountsForTimePassed()
251+
{
252+
Sleep::fake();
253+
Carbon::setTestNow(now());
254+
255+
$data = LazyCollection::times(3)
256+
->throttle(3)
257+
->tapEach(function ($value, $index) {
258+
if ($index == 1) {
259+
// Travel in time...
260+
(new Wormhole(1))->second();
261+
}
262+
})
263+
->all();
264+
265+
Sleep::assertSlept(function (Duration $duration, int $index) {
266+
$expectation = $index == 1 ? 2_000_000 : 3_000_000;
267+
268+
$this->assertEqualsWithDelta(
269+
$expectation, $duration->totalMicroseconds, 1_000
270+
);
271+
272+
return true;
273+
}, times: 3);
274+
275+
$this->assertSame([1, 2, 3], $data);
276+
277+
Sleep::fake(false);
278+
Carbon::setTestNow();
279+
}
280+
226281
public function testUniqueDoubleEnumeration()
227282
{
228283
$data = LazyCollection::times(2)->unique();

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.