Skip to content

Commit 1b46c96

Browse files
committed
Fixes bug when many requests to a page are made and multiple streams request to build the same merged css or js file sometimes results in serving incomplete files to the client if a second request came in and truncated the part of the work from the first request.
1 parent 9d231d1 commit 1b46c96

File tree

2 files changed

+38
-11
lines changed

2 files changed

+38
-11
lines changed

lib/internal/Magento/Framework/View/Asset/MergeStrategy/Direct.php

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,23 @@ class Direct implements \Magento\Framework\View\Asset\MergeStrategyInterface
3030
*/
3131
private $cssUrlResolver;
3232

33+
/**
34+
* @var \Magento\Framework\Math\Random
35+
*/
36+
protected $mathRandom;
37+
3338
/**
3439
* @param \Magento\Framework\Filesystem $filesystem
3540
* @param \Magento\Framework\View\Url\CssResolver $cssUrlResolver
3641
*/
3742
public function __construct(
3843
\Magento\Framework\Filesystem $filesystem,
39-
\Magento\Framework\View\Url\CssResolver $cssUrlResolver
44+
\Magento\Framework\View\Url\CssResolver $cssUrlResolver,
45+
\Magento\Framework\Math\Random $mathRandom
4046
) {
4147
$this->filesystem = $filesystem;
4248
$this->cssUrlResolver = $cssUrlResolver;
49+
$this->mathRandom = $mathRandom;
4350
}
4451

4552
/**
@@ -49,17 +56,18 @@ public function merge(array $assetsToMerge, Asset\LocalInterface $resultAsset)
4956
{
5057
$mergedContent = $this->composeMergedContent($assetsToMerge, $resultAsset);
5158
$filePath = $resultAsset->getPath();
59+
$tmpFilePath = $filePath . $this->mathRandom->getUniqueHash('_');
5260
$staticDir = $this->filesystem->getDirectoryWrite(DirectoryList::STATIC_VIEW);
5361
$tmpDir = $this->filesystem->getDirectoryWrite(DirectoryList::TMP);
54-
$tmpDir->writeFile($filePath, $mergedContent);
55-
$tmpDir->renameFile($filePath, $filePath, $staticDir);
62+
$tmpDir->writeFile($tmpFilePath, $mergedContent);
63+
$tmpDir->renameFile($tmpFilePath, $filePath, $staticDir);
5664
}
5765

5866
/**
5967
* Merge files together and modify content if needed
6068
*
6169
* @param \Magento\Framework\View\Asset\MergeableInterface[] $assetsToMerge
62-
* @param \Magento\Framework\View\Asset\LocalInterface $resultAsset
70+
* @param \Magento\ Framework\View\Asset\LocalInterface $resultAsset
6371
* @return string
6472
* @throws \Magento\Framework\Exception\LocalizedException
6573
*/

lib/internal/Magento/Framework/View/Test/Unit/Asset/MergeStrategy/DirectTest.php

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@
1212

1313
class DirectTest extends \PHPUnit\Framework\TestCase
1414
{
15+
/**
16+
* @var \Magento\Framework\Math\Random|\PHPUnit_Framework_MockObject_MockObject
17+
*/
18+
protected $mathRandomMock;
1519
/**
1620
* @var \Magento\Framework\View\Asset\MergeStrategy\Direct
1721
*/
@@ -50,30 +54,42 @@ protected function setUp()
5054
[DirectoryList::TMP, \Magento\Framework\Filesystem\DriverPool::FILE, $this->tmpDir],
5155
]);
5256
$this->resultAsset = $this->createMock(\Magento\Framework\View\Asset\File::class);
53-
$this->object = new Direct($filesystem, $this->cssUrlResolver);
57+
$this->mathRandomMock = $this->getMockBuilder(\Magento\Framework\Math\Random::class)
58+
->disableOriginalConstructor()
59+
->getMock();
60+
$this->object = new Direct($filesystem, $this->cssUrlResolver, $this->mathRandomMock);
5461
}
5562

5663
public function testMergeNoAssets()
5764
{
65+
$uniqId = '_b3bf82fa6e140594420fa90982a8e877';
5866
$this->resultAsset->expects($this->once())->method('getPath')->will($this->returnValue('foo/result'));
5967
$this->staticDir->expects($this->never())->method('writeFile');
60-
$this->tmpDir->expects($this->once())->method('writeFile')->with('foo/result', '');
61-
$this->tmpDir->expects($this->once())->method('renameFile')->with('foo/result', 'foo/result', $this->staticDir);
68+
$this->mathRandomMock->expects($this->once())
69+
->method('getUniqueHash')
70+
->willReturn($uniqId);
71+
$this->tmpDir->expects($this->once())->method('writeFile')->with('foo/result' . $uniqId, '');
72+
$this->tmpDir->expects($this->once())->method('renameFile')->with('foo/result' . $uniqId, 'foo/result', $this->staticDir);
6273
$this->object->merge([], $this->resultAsset);
6374
}
6475

6576
public function testMergeGeneric()
6677
{
78+
$uniqId = '_be50ccf992fd81818c1a2645d1a29e92';
6779
$this->resultAsset->expects($this->once())->method('getPath')->will($this->returnValue('foo/result'));
6880
$assets = $this->prepareAssetsToMerge([' one', 'two']); // note leading space intentionally
6981
$this->staticDir->expects($this->never())->method('writeFile');
70-
$this->tmpDir->expects($this->once())->method('writeFile')->with('foo/result', 'onetwo');
71-
$this->tmpDir->expects($this->once())->method('renameFile')->with('foo/result', 'foo/result', $this->staticDir);
82+
$this->mathRandomMock->expects($this->once())
83+
->method('getUniqueHash')
84+
->willReturn($uniqId);
85+
$this->tmpDir->expects($this->once())->method('writeFile')->with('foo/result' . $uniqId, 'onetwo');
86+
$this->tmpDir->expects($this->once())->method('renameFile')->with('foo/result' . $uniqId, 'foo/result', $this->staticDir);
7287
$this->object->merge($assets, $this->resultAsset);
7388
}
7489

7590
public function testMergeCss()
7691
{
92+
$uniqId = '_f929c374767e00712449660ea673f2f5';
7793
$this->resultAsset->expects($this->exactly(3))
7894
->method('getPath')
7995
->will($this->returnValue('foo/result'));
@@ -86,9 +102,12 @@ public function testMergeCss()
86102
->method('aggregateImportDirectives')
87103
->with('12')
88104
->will($this->returnValue('1020'));
105+
$this->mathRandomMock->expects($this->once())
106+
->method('getUniqueHash')
107+
->willReturn($uniqId);
89108
$this->staticDir->expects($this->never())->method('writeFile');
90-
$this->tmpDir->expects($this->once())->method('writeFile')->with('foo/result', '1020');
91-
$this->tmpDir->expects($this->once())->method('renameFile')->with('foo/result', 'foo/result', $this->staticDir);
109+
$this->tmpDir->expects($this->once())->method('writeFile')->with('foo/result' . $uniqId, '1020');
110+
$this->tmpDir->expects($this->once())->method('renameFile')->with('foo/result' . $uniqId, 'foo/result', $this->staticDir);
92111
$this->object->merge($assets, $this->resultAsset);
93112
}
94113

0 commit comments

Comments
 (0)