Should we have a different cli binary for executing maintenance related tasks?
Background
The main challenge we face with the current state of the typo3
binary is, that it tries to fully bootstrap TYPO3 in the same way a backend request does. In order to make the binary functional in a non installed state, we must change the booting sequence in a way that low level commands can be executed.
While trying to solve this challenge, the suggestion was made to introduce a second binary, which can execute low level tasks. Commands executed with this binary, can then use a stripped down bootstrap that makes them available without a full install. Similar to the install tool web UI. The idea behind this proposal is to have different binaries for different use cases.
Alternative 1: One tool for each use case
Currently we have only one cli binary, which can execute a variety of commands for different use cases.
The question now is, whether it makes sense to have separate binaries for different use cases.
- Maintenance binary, things you would use (and are safe) in your deployment scripts –
typo3ctl cache:flush
,typo3ctl upgrade:all
- Business-Logic binary –
typo3 import:foobar
,typo3 scheduler:run
Very much like the install tool, which is the goto point for a maintenance UI, while the regular backend is for business logic.
Patch is here: https://review.typo3.org/#/c/58300/
Pros
- A clear distinction between different concerns
- These independent tools can be developed independently tailored to the different needs
- Technically easier to implement, as we can define that the
typo3ctl
binary always starts with a stripped down bootstrap
Cons
- Two different entry and goto points for users
- No easy way to list all available tasks
- Maintenance commands are not always low level commands.
upgrade:run
needs a full bootstrap in the end and might still fail in a not set up state of TYPO3 - Convenience commands like
server:run
to start a simple PHP webserver (does not exist for TYPO3 yet) are clearly not maintenance commands, but still need a stripped down bootstrap to work - Some tasks might fall in different categories. Like in which category do the following commands fit?
extension:activate
,extension:deactivate
,backend:lock
,backend:unlock
,language:update
,referenceindex:update
- It is not clear where to put commands use cases that fit into both like
language:update
orreferenceindex:update
Alternative 2: One tool for all use cases
Instead of having two binaries, we keep having one and change the code in a way, that the single binary can execute low level tasks and regular tasks.
Patch is here: https://review.typo3.org/#/c/58298/
Pros
- One goto point for users
- Different types of commands can still be grouped in different namespaces like
maintenance:
to make the intent more clear - Similar to the integration of the install tool in the backend, we have one unified “UI” to accomplish multiple tasks
Cons
- The technical implementation is more challenging. When executing a single binary, we must delay the decision whether to boot up to full extent at a late point in the execution. But convenience commands which are clearly not meant for maintenance are sometimes also useful to have a stripped down bootstrap (see above
server:run
), so we need to accept this challenge anyway.
Further considerations
To be able to cleanly dispatch low level commands AND high level commands within a single binary, we must know which command needs a full boot and which not before we initiate a TYPO3 boot. This means, we need to know which commands are available at all and where to get this information from.
Since commands are defined in active extensions, we currently need to boot TYPO3 up to a point where we can ask the PackageManager which commands are active. For that we need to boot up to at least the point where we can ask the PackageManager. This means with the current code base we need to decide wether we want to boot cached or uncached before we know anything. The consequence is, that in my approach (https://review.typo3.org/#/c/58298/), with the current code base we have, all commands will always be run completely uncached.
This chicken / egg problem can however be overcome at a later point, by using the same strategy as for class loading:
In composer mode we write a compiled file with all (via composer installed) extensions to a know location and in the binary, we can just read that file and the information which commands of which type are available and run a fully cached or uncached bootstrap for each command.
In non composer mode we can also go first with the approach we have for class loading. Write the command list of all required core extension in one place and add an additional command list for all active extensions in a second place when installing TYPO3 and activating/deactivating extensions.
In the long run it is planned anyway to get rid of the active/inactive state anyway and always load all extensions that are present in a (to be defined) location. Then finding commands will be trivial in all cases, as we only need to know the location where extensions reside and load the command definitions from there.
Long story short:
- We need a more flexible booting mechanism for commands
- To achieve that is a solvable technical problem, even if keep one binary
- Would it still be benefitial for users to have two separate binaries for different use cases?
Organizational
Topic Initiator: Helmut Hummel