Build fast, concurrent applications with PHP
Benefit from concurrency by replacing your blocking I/O with non-blocking I/O,
or designing your system with non-blocking I/O from the ground up.
We shipped fibers in PHP 8.1 to extend its capabilities for concurrent applications.
The PHP standard library has already provided everything else we needed for years now, but it only ships the low-level building blocks. AMPHP provides higher-level libraries using non-blocking I/O under the hood. Fibers allow these libraries to just work, no matter whether they're used in concurrent or traditional contexts.
Latest Releases
-
amphp/file 3.0.0
Stable release compatible with AMPHP v3 and fibers! 🎉
As with other libraries compatible with AMPHP v3, most cases of parameters or returns of
Promise<ResolutionType>
have been replaced withResolutionType
.- Renamed
BlockingDriver
toBlockingFilesystemDriver
- Renamed
EioDriver
toEioFilesystemDriver
- Renamed
ParallelDriver
toParallelFilesystemDriver
- Renamed
StatusCachingDriver
toStatusCachingFilesystemDriver
- Renamed
UvDriver
toUvFilesystemDriver
- Renamed
Amp\File\Sync\AsyncFileMutex
toAmp\File\FileMutex
- Added
?Cancellation
as first parameter ofFile::read()
- Added
File::isSeekable()
- Removed
File::SEEK_SET
,File::SEEK_CUR
, andFile::SEEK_END
- Added
Amp\File\Whence
for seeking instead
- Renamed
-
amphp/http-server 2.1.8
- Fixed the first chunk read from the response body being duplicated when the content-length header was not set on the response (#342)
-
amphp/parallel 2.0.0
Stable release compatible with AMPHP v3 and fibers! 🎉
As with other libraries compatible with AMPHP v3, most cases of parameters or returns of
Promise<ResolutionType>
have been replaced withResolutionType
.All classes related to
ext-pthreads
have been removed as this extension does not have releases on PHP 8.x.Classes in the
Amp\Parallel\Sync
namespace have been moved toamphp/sync
.Context
Process
renamed toProcessContext
Parallel
renamed toThreadContext
Context::isRunning()
andContext::kill()
replaced byContext::isClosed()
andContext::close()
- Context related functions:
run
→startContext
factory
→contextFactory
create
has been removed, usestartContext
- Xdebug ini settings are forwarded to processes created by
ProcessContext
(including workers executing tasks), allowing step debugging through IDEs such as PhpStorm. - Improved UX of uncaught exceptions in child processes and task runs. The full stack trace in the context is displayed when converting the
ContextPanicError
orTaskFailureThrowable
to a string, i.e., when the exception is uncaught in the parent and is written to STDERR - Added an optional
Cancellation
argument toContextFactory::start()
Worker
Pool
renamed toWorkerPool
andDefaultPool
renamed toContextWorkerPool
TaskWorker
has been marked as internal. Use aWorkerFactory
to createWorker
instances or useWorkerPool::getWorker()
to get a worker from a poolTaskRunner
has been removed- Removed deprecated
TaskException
andTaskError
Worker::enqueue()
renamed toWorker::submit()
, which now returns anExecution
objectExecution::getFuture()
returns a future that resolves to the eventual return value of theTask
Execution::await()
awaits the result of theTask
, it is a shortcut to callingExecution::getFuture()->await()
Execution::getChannel()
returns aChannel
that can be used to communicate with theChannel
provided toTask::run()
- The arguments to
Task::run()
have changed toChannel
andCancellation
IpcHub
Inter-process communication is now exposed as part of the public API for potential use outside of the context and worker components.
-
amphp/http 1.7.1
- Fixed header validation regex to allow names containing
*
,+
, and.
(#19)
- Fixed header validation regex to allow names containing
-
amphp/byte-stream 2.0.1
- Fixed
ReadableResourceStream
callingSuspension::resume()
when destroyed, which could throw an exception when suspending from{main}
and an uncaught exception was thrown from the event loop.
- Fixed
-
amphp/log 1.2.0
- Increased minimum PHP version to 7.2.
- Added support for Monolog v3.x.
-
amphp/socket 2.0.0
Stable release compatible with AMPHP v3 and fibers! 🎉
As with other libraries compatible with AMPHP v3, most cases of parameters or returns of
Promise<ResolutionType>
have been replaced withResolutionType
.See some of the changes in
v2.0
ofamphp/byte-stream
since this library extends several of the interfaces in that library, particularlyReadableStream
andWritableStream
.- Moved methods from the
EncryptableSocket
interface toSocket
and removedEncryptableSocket
- Changed
SocketAddress
to an interface with two implementations:InternetAddress
andUnixAddress
- These implementations can be differentiated using
SocketAddress::getType()
, which returns an enumSocketAddressType
with casesUnix
andInternet
SocketAddress
static constructors have been relocated as functions in theAmp\Socket\SocketAddress
namespace.
- These implementations can be differentiated using
- Added
connectTls
function - Added
bindUdpSocket
function - Added
ResourceUdpSocket
andUdpSocket
interface - Added
ServerSocketFactory
interface for creatingServerSocket
instances along with an implementationResourceServerSocketFactory
- Renamed
createPair
function tocreateSocketPair
- Renamed
connector
tosocketConnector
- Renamed
Server
toResourceServerSocket
and introducedServerSocket
interfaceResourceServerSocket::__construct()
requires aBindContext
instance
- Renamed
Connector
toSocketConnector
- Renamed
DnsConnector
toDnsSocketConnector
- Renamed
StaticConnector
toStaticSocketConnector
- Removed chunk size from
BindContext
, use chunk size parameters onlisten
/bindUdpSocket
instead - Max attempts has been removed from
ConnectContext
in favor of a constructor parameter toRetrySocketConnector
DnsSocketConnector
now tries each host returned from a DNS query a single time before failing. Retrying the list is accomplished through a new connector implementation,RetrySocketConnector
that can be configured to retry a given number of times with an exponential backoff between attempts.- Default required TLS version is now 1.2+ instead of 1.0+
Changes from 2.0.0 Beta 9
- Moved methods from the
EncryptableSocket
interface toSocket
and removedEncryptableSocket
- Renamed
SocketServer
toServerSocket
- Renamed
SocketServerFactory
toServerSocketFactory
- Moved methods from the
-
amphp/dns 2.0.1
What’s Changed
- Fix fallback to blocking resolver by @danog and @kelunik in https://github.com/amphp/dns/pull/108 and https://github.com/amphp/dns/pull/109
- Try entire search list when resolve type is restricted by @trowski:
9d988e31
- Improve static analysis with more specific DnsResolver return types by @trowski:
7344cceb
Full Changelog: https://github.com/amphp/dns/compare/v2.0.0…v2.0.1
-
amphp/windows-registry 1.0.0
Stable release compatible with AMPHP v3 and fibers! 🎉
As with other libraries compatible with AMPHP v3, most cases of parameters or returns of
Promise<ResolutionType>
have been replaced withResolutionType
.WindowsRegistry
offers the methods as static methods now instead of instance methods.
-
amphp/process 2.0.0
Stable release compatible with AMPHP v3 and fibers! 🎉
As with other libraries compatible with AMPHP v3, most cases of parameters or returns of
Promise<ResolutionType>
have been replaced withResolutionType
.Process::__construct()
is now private in favor ofProcess::start()
Process::start()
is now static instead of an instance methodProcess::start()
no longer returns the PID, useProcess::getPid()
Process::kill()
no longer causes an exception to be thrown fromProcess::join()
Process::getEnv()
has been renamed toProcess::getEnvironment()
- Improved handling if the
Process
object is destructed, but the process streams (STDIN, STDOUT, STDERR) are still used - Renamed
escapeArguments
toescapeArgument
- Removed custom stream implementations
- Removed
StatusError
- Fixed and improved wrapper copy if running inside of PHARs on Windows
- Removed nullability of
Process::getWorkingDirectory()
- Avoid calling
join()
insidekill()
to avoid suspensions in destructors - Added an optional
Cancellation
parameter toProcess::join()
- Fixed ended processes sometimes leaving zombie processes on *nix systems (requires
ext-pcntl
, an optional dependency)
-
amphp/cache 2.0.0
Stable release compatible with AMPHP v3 and fibers! 🎉
As with other libraries compatible with AMPHP v3, most cases of parameters or returns of
Promise<ResolutionType>
have been replaced withResolutionType
.- Renamed
ArrayCache
toLocalCache
, swapping the constructor argument order - Modified
LocalCache
to implementIteratorAggregate
andCountable
, acting as an LRU cache now (#20) - Support arbitrary values in
LocalCache
,NullCache
, andPrefixCache
- Changed
Cache
to support arbitrary values - Introduced separate
StringCache
interface for caching only strings - Added
StringCacheAdapter
to use anyCache
in place of aStringCache
- Removed
FileCache
(will be available inamphp/file
instead)
- Renamed
-
amphp/postgres 1.4.5
- Fixed cancelling an active query if a connection is closed when using
ext-pgsql
(#54)
- Fixed cancelling an active query if a connection is closed when using
-
amphp/sql-common 1.1.4
- Fixed potential double deferred resolve when a connection pool is full.
-
amphp/sync 2.0.0
Stable release compatible with AMPHP v3 and fibers! 🎉
As with other libraries compatible with AMPHP v3, most cases of parameters or returns of
Promise<ResolutionType>
have been replaced withResolutionType
.Changes from 1.x
ConcurrentIterator
functions have been removed are now available as methods onPipeline
inamphp/pipeline
FileMutex
has been removed, as a better implementation ships as part ofamphp/file
- Removed
ThreadedMutex
andThreadedSemaphore
- Removed
Lock::getId()
Barrier::await
supports cancellation nowsynchronized
accepts anySemaphore
now instead of aMutex
only- Added
Channel
fromamphp/parallel
, which allows two way communicate between execution contexts, such as two coroutines or two processes.Channel
has been modified to extendClosable
- Also added
Parcel
fromamphp/parallel
, which allows sharing a value across execution contexts with mutually-exclusive access to modifying that value usingParcel::synchronized()
. - Added
createChannelPair()
function which returns a pair of connectedChannel
objects. - Added
RateLimitingSemaphore
which releases locks after a given time elapses. - Added
StaticKeySemaphore
, analogous toStaticKeyMutex
Changes from 2.0.0 Beta 6
- Added
RateLimitingSemaphore
which releases locks after a given time elapses. - Added
StaticKeySemaphore
, analogous toStaticKeyMutex
-
amphp/parser 1.1.0
- PHP 7.4 now required
- Improved performance of the parser when requesting small chunks of data and when yielding an integer length delimiter
-
amphp/pipeline 1.0.0
Initial stable release 🎉
Changes from 1.0.0 Beta 7
- Marked
ConcurrentArrayIterator
,ConcurrentChainedIterator
, andConcurrentIterableIterator
as@internal
. Instead of these classes, usePipeline::fromIterable()
orPipeline::concat()
Pipeline::concat()
now accepts an array of anyiterable
, not only otherPipeline
objects
- Marked
-
amphp/sql 1.0.2
- Fix a deprecation notice on PHP 8.1 if a configuration key does not have a value.
-
amphp/phpunit-util 3.0.0
This package has been redesigned for compatibility with AMPHP v3 and fibers.
AsyncTestCase
serves a similar purpose as before, providing helper methods for unit testing within an async context. Each test case is run within a unique fiber to allow suspending during the test run.AsyncTestCase::setUpAsync()
andtearDownAsync()
have been removed. UseAsyncTestCase::setUp()
andtearDown()
instead, as both of these methods are now able to execute async using fibers.AsyncTestCase::createCallback()
now returns aClosure
. Additionally, an optional parameter for expected arguments upon invocation have been added (usesInvocationMocker::with(...)
to set expected arguments).
-
amphp/amp 3.0.0
Event Loop
Amp no longer ships its own event loop. It’s now based on Revolt.
Revolt\EventLoop
is quite similar to Amp’s previousAmp\Loop
. A very important difference is usingfloat $seconds
instead ofint $milliseconds
for timers though!Promises
Future
is a replacement for the previousPromise
. There’s no need for callbacks oryield
anymore! Itsawait()
method is based on fibers and replaces generator based coroutines /Amp\Promise\wait()
.- Renamed
Amp\Deferred
toAmp\DeferredFuture
. - Removed
Amp\Promise\wait()
: UseAmp\Future::await()
instead, which can be called in any (nested) context unlike before. - Removed
Amp\call()
: Remove the passed closure boilerplate and allyield
keywords, interruption is handled via fibers now instead of generator coroutines. - Removed
Amp\asyncCall()
: Replace invocations withAmp\async()
, which starts a new fiber instead of using generators. - Removed
Amp\coroutine()
: There’s no direct replacement. - Removed
Amp\asyncCoroutine()
: There’s no direct replacement. - Removed
Amp\Promise\timeout()
:Future::await()
accepts an optionalCancellation
, which can be used as a replacement. - Removed
Amp\Promise\rethrow()
: Unhandled errors are now automatically thrown into the event loop, so there’s no need for that function anymore. - Unhandled errors can be ignored using
Future::ignore()
if needed, but should usually be handled in some way. - Removed
Amp\Promise\wrap()
: UseFuture::finally()
instead. - Renamed
Amp\getCurrentTime()
toAmp\now()
returning the time in seconds instead of milliseconds. - Changed
Amp\delay()
to accept the delay in seconds now instead of milliseconds. - Added
Amp\weakClosure()
to allow a class to hold a self-referencing Closure without creating a circular reference that prevents automatic garbage collection. - Added
Amp\trapSignal()
to await one or multiple signals.
Promise Combinators
Promise combinators have been renamed:
Amp\Promise\race()
has been renamed toAmp\Future\awaitFirst()
Amp\Promise\first()
has been renamed toAmp\Future\awaitAny()
Amp\Promise\some()
has been renamed toAmp\Future\awaitAnyN()
Amp\Promise\any()
has been renamed toAmp\Future\awaitAll()
Amp\Promise\all()
has been renamed toAmp\Future\await()
CancellationToken
CancellationToken
has been renamed toCancellation
.CancellationTokenSource
has been renamed toDeferredCancellation
.NullCancellationToken
has been renamed toNullCancellation
.TimeoutCancellationToken
has been renamed toTimeoutCancellation
.CombinedCancellationToken
has been renamed toCompositeCancellation
.SignalCancellation
has been added.
Iterators
Iterators have been removed from
amphp/amp
as normal PHP iterators can be used with fibers now and there’s no need for a separate API. However, there’s still some need for concurrent iterators, which is covered by the newamphp/pipeline
library now.Closable
Amp\Closable
has been added as a new basic interface for closable resources such as streams or sockets.Strict Types
Strict types now declared in all library files. This will affect callbacks invoked within this library’s code which use scalar types as parameters. Functions used with
Amp\async()
are the most likely to be affected by this change — these functions will now be invoked within a strict-types context. - Renamed
-
amphp/php-cs-fixer-config 2.0.0
- Common code style for all packages based on Amp v3.
- Now includes
strict_types
and several other minor updates.
-
amphp/http-server-session 2.0.0
Changes from 2.0.0 Beta 4
- Removed the
Serializer
interface and implementations in favor of using those inamphp/seraliziation
- Removed the
-
amphp/http-server-form-parser 1.1.5
- Added methods
parseBody
,parseUrlEncodedBody
, andparseMultipartBody
toBufferingParser
to parse request bodies that have already been buffered (#10) - Added
parseContentBoundary
function that returns the content boundary from a multipart header.
- Added methods
-
amphp/websocket 1.0.3
- Added
GOING_AWAY
to the list of normal close codes, which will causeClient::receive()
to return null instead of throwing an exception if a browser sends this code when navigating away from a page - Fixed undefined array access in rare case where the event loop is exited after receiving a message on the websocket and then re-entered at a later time (amphp/websocket-client#39)
- Added
-
amphp/http-server-static-content 1.0.7
- Compatibility with
amphp/file
@2.x
- Compatibility with
-
amphp/websocket-client 1.0.1
- Ignore
/docs
in.gitattributes
to avoid broken symlink (#38)
Full Changelog: https://github.com/amphp/websocket-client/compare/v1.0.0…v1.0.1
- Ignore
-
amphp/parallel-functions 1.1.0
What’s Changed
- Update to
laravel/serializable-closure
instead ofopis/closure
by @owenvoke - Increase minimum PHP version to PHP 7.4 by @owenvoke
New Contributors
- @sci3ma made their first contribution in https://github.com/amphp/parallel-functions/pull/24
- @owenvoke made their first contribution in https://github.com/amphp/parallel-functions/pull/31
Full Changelog: https://github.com/amphp/parallel-functions/compare/v1.0.0…v1.1.0
- Update to
-
amphp/rpc 1.0.0
Initial release.
-
amphp/redis 1.0.7
- Fixed a case where an exception may be thrown to the event loop when a
Subscriber
lost connection to the Redis server.
- Fixed a case where an exception may be thrown to the event loop when a
-
amphp/cluster 1.0.1
Update to use
amphp/file
v2.x
. -
amphp/mysql 2.1.2
- Fixed a bug when decoding a JSON field (#113)
-
amphp/http-client-cookies 1.2.0
- Added compatibility with
amphp/file
v2 - Updated public suffix list
- Added compatibility with
-
amphp/http-client 4.6.2
- Fixed
setBodySizeLimit(0)
with HTTP/2 protocol (#297)
- Fixed
-
amphp/hpack 3.1.1
- Work around https://bugs.php.net/bug.php?id=79749
- Fixed deprecation warning in PHP 8.1 (#11)
-
amphp/beanstalk 0.3.2
- Added support for Symfony YAML library v4 and v5. (#34)
-
amphp/websocket-server 2.0.0
Changes since RC3
- Renamed
Endpoint
toGateway
. An alias toEndpoint
is provided for compatibility. - Renamed
WebsocketObserver
toWebsocketServerObserver
.
Upgrading from v1.x to v2.0
This library has been refactored to use the new
amphp/websocket
library containing components that can be shared between server and clients.Websocket
is now a final class that requires an instance ofClientHandler
, which has two methods to handle client handshakes and the client connection.handleHandshake()
: This method is invoked when a WebSocket connection attempt is made. The application may alter the given Response to deny the connection attempt or set application-specific headers.handleClient()
: This method is invoked upon a successful WebSocket connection. This method should use a loop to receive messages from the WebSocket connection.
use Amp\Http\Server\Request; use Amp\Http\Server\Response; use Amp\Http\Status; use Amp\Success; use Amp\Websocket\Client; use Amp\Websocket\Server\ClientHandler; use Amp\Websocket\Server\Gateway; use Amp\Websocket\Server\Websocket; $websocket = new Websocket(new class implements ClientHandler { public function handleHandshake(Gateway $gateway, Request $request, Response $response): Promise { if (!\in_array($request->getHeader('origin'), ['http://localhost:1337', 'http://127.0.0.1:1337', 'http://[::1]:1337'], true)) { return $gateway->getErrorHandler()->handleError(Status::FORBIDDEN, 'Origin forbidden', $request); } return new Success($response); } public function handleClient(Gateway $gateway, Client $client, Request $request, Response $response): Promise { return Amp\call(function () use ($gateway, $client) { while ($message = yield $client->receive()) { \assert($message instanceof Message); $gateway->broadcast(\sprintf('%d: %s', $client->getId(), yield $message->buffer())); } }); } });
WebSocket clients are now represented by a
Client
object. This object contains several methods for getting information about the client and for sending messages to a single client.Servers can send to multiple clients using
Gateway::broadcast()
andGateway::multicast()
(plus binary versions,Gateway::broadcastBinary()
andGateway::multicastBinary()
). AGateway
instance is provided toClientHandler::handleHandshake()
andClientHandler::handleClient()
. - Renamed
-
amphp/serialization 1.0.0
Initial release.
-
amphp/http-tunnel 1.0.0
Initial release.
-
amphp/http-client-cache 1.0.0
Initial release.
-
amphp/react-adapter 2.1.0
React\EventLoop\Factory
is now automatically replaced with another implementation that throws on each usage to prevent two loops existing concurrently by accident. SetAMP_REACT_ADAPTER_DISABLE_FACTORY_OVERRIDE=1
as environment variable or constant to disable this protection.
-
amphp/http-server-router 1.0.2
Allow
amphp/[email protected]^2
-
amphp/react-stream-adapter 0.1.0
Initial release.