Problem
The current async strategy for the transport is defined as a named constructor Transport::async() that doesn't depend on another transport.
On a real scenario this is fine as one really wants to make the requests.
But in a testing environment this can't work as the transport will be a fake one built via Transport::via() but insinde innmind/async it will be completely replaced by a concrete one that will make real requests.
The async transport should come from the initial one to keep the same strategy.
Solution
The Transport::async() named constructor must deprecated.
A new, internal, member method toAsync(): self (or asAsync, to avoid a collision with the existing async method). Each implementation will implement this method but decorators such as logger will delegate the call to the underlying implementation until it reaches the concrete implementation.
This way it will infer the correct async strategy from the initial one. Curl will become async curl, the fake one will still be a fake async and any further implementation will have to have an async strategy.
Note
There's still an uncertain part, which is the arguments that toAsync() will accept. Since there's multiple concrete implementations, not all will require the same arguments.
Either:
toAsync($arg1, $arg2, $etc)
toAsync(Async\Curl::of($args), Async\Via::of($args))
The second might be the most expressive.
But in all cases adding a new concrete implementation that requires new arguments for its async strategy can't be added as required arguments to toAsync as it would be a BC break. This means that the arguments must be optional and that the toAsync call must throw a LogicException .
Not great but so far I don't see an alternative 🤔
Problem
The current async strategy for the transport is defined as a named constructor
Transport::async()that doesn't depend on another transport.On a real scenario this is fine as one really wants to make the requests.
But in a testing environment this can't work as the transport will be a fake one built via
Transport::via()but insindeinnmind/asyncit will be completely replaced by a concrete one that will make real requests.The async transport should come from the initial one to keep the same strategy.
Solution
The
Transport::async()named constructor must deprecated.A new, internal, member method
toAsync(): self(orasAsync, to avoid a collision with the existingasyncmethod). Each implementation will implement this method but decorators such as logger will delegate the call to the underlying implementation until it reaches the concrete implementation.This way it will infer the correct async strategy from the initial one. Curl will become async curl, the fake one will still be a fake async and any further implementation will have to have an async strategy.
Note
There's still an uncertain part, which is the arguments that
toAsync()will accept. Since there's multiple concrete implementations, not all will require the same arguments.Either:
toAsync($arg1, $arg2, $etc)toAsync(Async\Curl::of($args), Async\Via::of($args))The second might be the most expressive.
But in all cases adding a new concrete implementation that requires new arguments for its async strategy can't be added as required arguments to
toAsyncas it would be a BC break. This means that the arguments must be optional and that thetoAsynccall must throw aLogicException.Not great but so far I don't see an alternative 🤔