Conversation
856ec01 to
6a348ea
Compare
6a348ea to
404c3e0
Compare
Signed-off-by: Maxence Lange <maxence@artificial-owl.com>
404c3e0 to
6d272ff
Compare
|
I don't think loopback requests should be used for this if we want to implement "async". I don't believe they would be reliable enough, they would take up limited slots in the fpm worker queue, create "unusual" traffic that firewalls etc might need to be adjusted for and just seems unexpected behavior of software in general. Moving this to a new request also means we pay the setup overhead of various resources again, and given how often the setup is (among the) most expensive part of the request, this would make it easy to accidentally double (or more) the resource usage of a request. I think in general, running code in the background should be avoided in most instances since it makes it harder to reason about possible failure and can lead to logic issues around other code/requests relying on the async code being executed (or not yet executed). To me it feels that instead of trying to move longer running logic out of the user-initiated request, it would make more sense to have the UI not block on the request in the first place. That way the code can remain linear and easier to reason about, and also do a better job of relaying failure/completion status to the user. I'm sorry for such a negative response on 3k+ lines of work, but we need to make sure that any advantage of "async" code is worth the extra complexity and new potential failure cases. |
|
After some discussion we've decided to work towards improving the background jobs instead to cover the uses cases better. See #52877 for the discussion around that |
|
Please consider adopting https://amphp.org/ before re-implementing the wheel I've worked it it. It works surprisingly well. |
|
Closing in favor of to-be-implemented background job improvements |
AsyncProcess
Using
IAsyncProcessallow the execution of code on a separated process in order to improve the quality of the user experience.Concept
To shorten the hanging time on heavy process that reflect on the user experience and to avoid delay between
instruction and execution, this API allows to prepare instructions to be executed on a parallel thread.
This is obtained by creating a loopback HTTP request, initiating a fresh PHP process that will execute the
prepared instruction after emulating a connection termination, freeing the main process.
Technology
The logic is to:
Setup
The feature require setting a loopback url.
This is done automatically by a background job. The automatic process uses
'overwrite.cli.url'and'trusted_domains'from config/config.php to find a list of domain name to test.It can be initiated via
occ:Or manually set with:
Blocks & Sessions
Interactions
Replayability
Quick example
ProcessExecutionTime
Code is to be executed as soon as defined, with alternative fallback solutions in that order:
::NOW- main process will fork and execute the code in parallel (instantly)::ASAP- process will be executed by an optional live service (a second later)::LATER- process will be executed at the next execution of the cron tasks (within the next 10 minutes)::ON_REQUEST- process needs to be executed manuallyIAsyncProcess
IAsyncProcessis the public interface that contains few methods to prepare the code to be processed on a parallel process.Closure
The code can be directly written in a closure by calling
exec():Invokable
Within the magic method
__invoke()in a configured objectsPHP Class
Via the method
async()from a classIBlockInterface
When storing a new Block via
IAsyncProcess::call(),IAsyncProcess::invoke()orIAsyncProcess::async(), will be returned aIBlockInterfaceto provided details about the Block.name(string)
Identification and/or description of the Block for better understanding when debugging
id(string)
Identification of the Block for future interaction between Blocks within the same Session
As an example,
idare to be used to obtainIBlockInterfacefrom a specific Block:blocker()
Set current Block as Blocker, meaning that further Blocks of the Session are lock until this process does not run successfully
require(string)
Define that the Block can only be executed if set Block, identified by its
id, ran successfully.Multiple Blocks can be set a required.
replayable()
The Block is configured as replayable, meaning that it will be restarted until it runs correctly
The delay is calculated using 6 (six) exponent current retry, capped at 6:
delay(int)
Only try to initiate the process n seconds after current time.
dataset(array)
It is possible to set a list of arguments to be applied to the same Block.
The Block will be executed for each defined set of data
post-execution
Post execution of a Block, its
IBlockInterfacecan be used to get details about it:ProcessExecutionTimethat initiated the process,ISessionInterface
ISessionInterfaceis available to your code viaABlockWrapperand helps interaction between all the Blocks of the same SessiongetAll()
returns all
IBlockInterfacefrom the SessionbyToken(string)
returns a
IBockInterfaceusing its tokenbyId(string)
returns a
IBockInterfaceusing itsidgetGlobalStatus()
return a
BlockStatus(Enum) based on every status of all Blocks of the Session:::PREPif one block is still at prep stage,::BLOCKERif at least one block is set asblockerand is failing,::SUCCESSif all blocks are successful,::ERRORif all process have failed,::STANDBYor::RUNNINGif none of the previous condition are met.::RUNNINGif at least oneBlockis currently processed.ABlockWrapper
This abstract class helps to interface with other Blocks from the same Session.
It will be generated and passed as argument to the defined block if the first parameter is an
AprocessWrapperis expected as first parameter:As a Closure
When using
invoke()Syntax is the same with
call(), when defining theasync()methodAbstract methods
ABlockWrapperis an abstract class with a list of interfaced methods that have different behavior on the BlockWrapper sent by the framework.List of usefull methods:
ISessionInterfacefor the sessionOther tools
Live Service
This will cycle every few seconds to check for any session in stand-by mode and will execute its blocks
Manage sessions and blocks
Get resume about current session still in database.
Get details about a session.
Get details about a block
Get excessive details about a block
Replay a not successful block
Mocking process
./occ async:setupallow an admin to generate fake processes to emulate the feature:Work in Progress
missing element of the feature: