This PR was merged into the 5.2-dev branch.
Discussion
----------
[HttpClient] fix pausing AmpResponse
| Q | A
| ------------- | ---
| Branch? | master
| Bug fix? | yes
| New feature? | no
| Deprecations? | no
| Tickets | None
| License | MIT
| Doc PR | None
This fixes the pause handler while streaming bodies in `AmpHttpClient`.
Needs to be rebased onto the target branch and needs some test fixes. @nicolas-grekas FYI.
Commits
-------
bf2d1cf6e7 Improve pause handler
Few years ago, we have introduced the Lock component. This is a very nice component, but sometime it is not enough. Sometime you need semaphore.
This is why I'm introducing this new component.
From wikipedia:
> In computer science, a semaphore is a variable or abstract data type used to control access to a common resource by multiple processes in a concurrent system such as a multitasking operating system. A semaphore is simply a variable. This variable is used to solve critical section problems and to achieve process synchronization in the multi processing environment. A trivial semaphore is a plain variable that is changed (for example, incremented or decremented, or toggled) depending on programmer-defined conditions.
This new component is more than a variable. This is an abstraction on top of different storage.
To make a quick comparison with a lock:
* A lock allows only 1 process to access a resource;
* A semaphore allow N process to access a resource.
Basically, a lock is a semaphore where `N = 1`.
PHP exposes some `sem_*` functions like [`sem_acquire`](http://php.net/sem_acquire). This module provides wrappers for the System V IPC family of functions. It includes semaphores, shared memory and inter-process messaging (IPC).
The Lock component has a storage that works with theses functions. It uses it with `N = 1`.
Wikipedia has some [examples](https://en.wikipedia.org/wiki/Semaphore_(programming)#Examples)
But I can add one more commun use case.
If you are building an async system that process user data, you may want to priorise all jobs. You can achieve that by running at maximum N jobs per user at the same time. If the user has more resources, you give him more concurrent jobs (so a bigger `N`).
Thanks to semaphores, it's pretty easy to know if a new job can be run.
I'm not saying the following services are using semaphore, but they may solve the previous problematic with semaphores. Here is some examples:
* services like testing platform where a user can test N projects concurrently (travis, circle, appveyor, insight, ...)
* services that ingest lots of data (newrelic, datadog, blackfire, segment.io, ...))
* services that send email in batch (campaign monitor, mailchimp, ...)
* etc...
To do so, since PHP is mono-threaded, you run M PHP workers. And in each worker, you look for for the next job. When you grab a job, you try to acquires a semaphore. If you got it, you process the job. If not you try another job.
FTR in other language, like Go, there are no need to run M workers, one is enough.
```php
<?php
use Symfony\Component\Lock\LockFactory;
use Symfony\Component\Lock\Store\RedisStore as LockRedisStore;
use Symfony\Component\Semaphore\SemaphoreFactory;
use Symfony\Component\Semaphore\Store\RedisStore;
require __DIR__.'/vendor/autoload.php';
$redis = new Redis();
$redis->connect('172.17.0.2');
// Internally, Semaphore needs a lock
$lock = (new LockFactory(new LockRedisStore($redis)))->createLock('test:lock', 1);
// Create a semaphore:
// * name = test
// * limit = 3 (it means only 3 process are allowed)
// * ttl = 10 seconds : Maximum expected semaphore duration in seconds
$semaphore = (new SemaphoreFactory($lock, new RedisStore($redis)))->createSemaphore('test', 3, 10);
if (!$semaphore->acquire()) {
echo "Could not acquire the semaphore\n";
exit(1);
}
// The semaphore has been acquired
// Do the heavy job
for ($i = 0; $i < 100; ++$i) {
sleep(1);
// Before the expiration, refresh the semaphore if the job is not finished yet
if ($i % 9 === 0) {
$semaphore->refresh();
}
}
// Release it when finished
$semaphore->release();
```
I looked at [packagist](https://packagist.org/?query=semaphore) and:
* most of packages are using a semaphore storage for creating a lock. So there are not relevant here;
* some packages need an async framework to be used (amphp for example);
* the only packages really implementing a semaphore, has a really low code quality and some bugs.
1. I initially copied the Lock component since the external API is quite similar;
1. I simplified it a lot for the current use case;
1. I implemented the RedisStorage according the [redis book](https://redislabs.com/ebook/part-2-core-concepts/chapter-6-application-components-in-redis/6-3-counting-semaphores/;)
1. I forced a TTL on the storage.
* 5.1:
Fix typo
Fix deprecated libxml_disable_entity_loader
Add Tagalog translations for validator messages 94, 95, 96 and 99
PHPUnit's assertContains() performs strict comparisons now.
[ClassLoader][Routing] Fix namespace parsing on php 8.
Fix deprecated libxml_disable_entity_loader
Made reference to PHPUnit\Util\XML::loadfile php5-compatible.
[Validator] Add missing translations for german and vietnamese
Modernized deprecated PHPUnit assertion calls
[Console] The message of "class not found" errors has changed in php 8.
The PHPUnit\Util\XML class has been removed in PHPUnit 9.3.
[Console] Make sure we pass a numeric array of arguments to call_user_func_array().
Remove outdated references from base_js.html.twig file
[String] We cannot have a "provides" function in test cases.
Typo: somes styles fixed
[Serializer] Fix that it will never reach DOMNode
[Validator] sync translations
[VarDumper] Improve previous fix on light array coloration
[Cache] Fix#37667
* 4.4:
Fix typo
Fix deprecated libxml_disable_entity_loader
Add Tagalog translations for validator messages 94, 95, 96 and 99
PHPUnit's assertContains() performs strict comparisons now.
[ClassLoader][Routing] Fix namespace parsing on php 8.
Fix deprecated libxml_disable_entity_loader
Made reference to PHPUnit\Util\XML::loadfile php5-compatible.
[Validator] Add missing translations for german and vietnamese
Modernized deprecated PHPUnit assertion calls
[Console] The message of "class not found" errors has changed in php 8.
The PHPUnit\Util\XML class has been removed in PHPUnit 9.3.
[Console] Make sure we pass a numeric array of arguments to call_user_func_array().
[Serializer] Fix that it will never reach DOMNode
[Validator] sync translations
[VarDumper] Improve previous fix on light array coloration
[Cache] Fix#37667
* 3.4:
Add Tagalog translations for validator messages 94, 95, 96 and 99
PHPUnit's assertContains() performs strict comparisons now.
[ClassLoader][Routing] Fix namespace parsing on php 8.
Fix deprecated libxml_disable_entity_loader
Made reference to PHPUnit\Util\XML::loadfile php5-compatible.
[Validator] Add missing translations for german and vietnamese
Modernized deprecated PHPUnit assertion calls
[Console] The message of "class not found" errors has changed in php 8.
The PHPUnit\Util\XML class has been removed in PHPUnit 9.3.
[Console] Make sure we pass a numeric array of arguments to call_user_func_array().
[Serializer] Fix that it will never reach DOMNode
[Validator] sync translations
[VarDumper] Improve previous fix on light array coloration
[Cache] Fix#37667
* 5.1: (28 commits)
[DI] fix
Use "composer/package-versions-deprecated" when possible
Fix
Small update in our internal terminology
Fix support for PHP8 union types
[VarDumper] fix typo
[Lock][Messenger] Fix precedence of DSN options for 5.1
Fix support for PHP8 union types
[FrameworkBundle] preserve dots in query-string when redirecting
[3.4] Fix support for PHP8 union types
[PhpUnitBridge] Streamline ansi/no-ansi of composer according to phpunit --colors option
[3.4] Small update in our internal terminology
[Cache] fix compat with DBAL v3
Remove unnecessary null check
[HttpFoundation] Allow `null` in InputBag@set
[HttpClient] Convert CurlHttpClient::handlePush() to instance method
Fix package rename when releasing
bumped Symfony version to 5.1.3
updated VERSION for 5.1.2
updated CHANGELOG for 5.1.2
...
* 5.1:
[Console] Reset question validator attempts only for actual stdin (bis)
Fix CookieClearingLogoutListener DI configuration
[HttpFoundation] use InputBag for Request::$request only if data is coming from a form
Make PhpDocExtractor compatible with phpDocumentor v5
fixed prototype block prefixes hierarchy of the CollectionType
Reset question validator attempts only for actual stdin
fixed block prefixes hierarchy of the CollectionType
bumped Symfony version to 5.0.11
updated VERSION for 5.0.10
updated CHANGELOG for 5.0.10
bumped Symfony version to 4.4.11
updated VERSION for 4.4.10
updated CHANGELOG for 4.4.10
* 5.0:
Make PhpDocExtractor compatible with phpDocumentor v5
Reset question validator attempts only for actual stdin
bumped Symfony version to 5.0.11
updated VERSION for 5.0.10
updated CHANGELOG for 5.0.10
bumped Symfony version to 4.4.11
updated VERSION for 4.4.10
updated CHANGELOG for 4.4.10
* 4.4:
Make PhpDocExtractor compatible with phpDocumentor v5
Reset question validator attempts only for actual stdin
bumped Symfony version to 4.4.11
updated VERSION for 4.4.10
updated CHANGELOG for 4.4.10
Version 5 of phpDocumentor introduced some changes to the
`getTagsByName()` method that break the `PhpDocExtractor`.
More specific, it now returns an instance of `InvalidTag` instead of
`null` when parsing an invalid tag.
* 4.4: (27 commits)
[Serializer] minor cleanup
fix merge
Run PHP 8 as 7.4.99
Remove calls to deprecated ReflectionParameter::getClass().
[VarDumper] fix PHP 8 support
Add php 8 to travis.
[Cache] Accessing undefined constants raises an Error in php8
[Cache] allow DBAL v3
Skip Doctrine DBAL on php 8 until we have a compatible version.
[DomCrawler] Catch expected ValueError.
Made method signatures compatible with their corresponding traits.
[ErrorHandler] Apply php8 fixes from Debug component.
[DomCrawler] Catch expected ValueError.
[Validator] Catch expected ValueError.
[VarDumper] ReflectionFunction::isDisabled() is deprecated.
[BrowserKit] Raw body with custom Content-Type header
[PropertyAccess] Parse php 8 TypeErrors correctly.
[Intl] Fix call to ReflectionProperty::getValue() for static properties.
[HttpKernel] Prevent calling method_exists() with non-string values.
Fix wrong roles comparison
...
* 5.1:
[PhpUnitBridge] fix leftover
[PhpUnitBridge] fix installing under PHP >= 8
Use ">=" for the "php" requirement
bump icu 67.1
[DI] Remove preload primitive types
[Validator] Add missing translations of nn locale
[HttpKernel] Fix that the `Store` would not save responses with the X-Content-Digest header present
[Intl] bump icu 67.1
[Validator] allow passing a validator to Validation::createCallable()
* 5.0:
[PhpUnitBridge] fix bad test
[4.4] CS fixes
[3.4] CS fixes
Disable phpunit verbosity
Queue name is a required parameter
[FrameworkBundle] display actual target for error in AssetsInstallCommand
Remove patches for Doctrine bugs and deprecations
[Mime] fix bad method call on "EmailAddressContains"
[DI][EventDispatcher] added contract for implementation