Skip to content

v1.10.0

Latest
Compare
Choose a tag to compare
@gmazzap gmazzap released this 03 Sep 12:51
· 1 commit to master since this release
2119d0e

What's Changed

New generic "init" hook

Before this release, the only way to act on the container to register services and such was a package-scoped init hook, a hook whose name is composed of a prefix plus the package's slug.
That meant one would need an instance of the package to be able to register services to that package.
As highlighted in #47, this was limiting when wanting to act "programmatically" act on multiple packages, e.g., all packages belonging to a specific project.
Moreover, even if the package creates a function to access its main Package instance, we can never be sure the package is available (e.g., a plugin could be deactivated), so we need to rely on function_exists and still always rely on other packages' developers to declare the function in the first place.

The newly introduced "static" Package::ACTION_MODULARITY_INIT action hook allows developers to access all Modularity package initialization. It is up to consumers to determine whether they need to interact with that package or not. The hook passes the package slug as the first parameter to make it as easy and "cheap" as possible.

Package statuses and action hooks refactoring for completeness and consistency

Since the addition of Package::build() (version 1.7.0), we have a pretty clear separation of two "phases" in the Package lifecycle: the "building" and the "booting" phase.

However, the Package statuses did not describe the phases in detail. For example, we had no status to describe when the "building" phase was completed, which is relevant because, at that point, it was already safe to access the container.

Besides that, we did not have enough hooks to access the container at relevant statuses.

For this reason, we decided to have a complete status list, plus actions at any relevant point. Some of the statuses and some of the action hooks were renamed (in a backward-compatible way) to ensure better consistency and a consistent "mapping" of statuses with related action hooks.

Now, we have a status to represent all relevant milestones of the Package lifecycle and a way to hook at the most convenient place for different scopes. Moreover, we have a much more consistent naming of statuses and action hooks.

Status Description Action hook
STATUS_IDLE The package is just created. No action hook
STATUS_INITIALIZING The "building" phase is started. ACTION_INIT hook can be used to register and extend services.
STATUS_INITIALIZED The "building" phase is completed. ACTION_INITIALIZED hook can be used to access services.
STATUS_BOOTING The "booting" phase is started. No action hook
STATUS_BOOTED The "booting" phase is completed. ACTION_BOOTED hook can be used to act on container after all executables services have been executed.
STATUS_DONE Package lifecycle has completed successfully. No action hook

More flexible status checking and additional Package API

Before this release, the only way to check a Package's status was the Package::statusIs() method. Often, even internally to Modularity, we wanted to check whether the Package was at least at a given status. That meant checking the status at hand plus all the previous statuses and the "failed" status.

The new Package::hasReachedStatus() and Package::hasFailed() methods make these sorts of checks much easier and more reliable.
Moreover, the new Package::hasContainer() method makes it possible and easy to determine if a Container is already available.

Package::boot() and Package::build() idempotency

Starting from this release, calling Package::build() or Package::boot() multiple times is eventless. We don't expect package authors to do that on their Package instance. However, when holding an instance of another package, e.g. a connected package, it might be desirable to ensure it is built or booted. In such cases, an error was raised in previous versions. Now, there's no error, making it easy and safe to call, for example, Package::build() to ensure a Package is built doing nothing in the case it already was.

Improvements around package connection

This release does nothing regarding how package connection works. However, due to the abovementioned changes, package connection has become more effective.

The PackageProxyContainer was used when a package to connect was not "ready" yet was used more than needed. That was because it was impossible to precisely check the status of the Package or if a container was already created. With the new Package API and the new statuses, that is now possible, so the PackageProxyContainer is not used only when strictly necessary.

Finally, when a package connection failed, an exception was immediately thrown. It is common to connect packages early in the application flow, but often, services from connected packages are accessed enough time later. It might have happened that an exception for a failed connection was raised early, even if, in that request, no services from connected packages were accessed. For example, because of a redirect, a hook removed, or any other reason. With this release, no immediate failure happens on a failed connection (a failure action hook is fired). Then, when a service from the expectedly connected package is accessed, that will fail because of the failed connection, and so an error will be thrown at the latest possible time when there is no alternative.

With all the changes above, plus the Package::boot() and Package::build() idempotency, using package connections to build cross-package relations is easier, safer, and more efficient.

Tests

Many new tests have been added to cover all newly added or updated functionalities.

Documentation

Even if there's still room for improvement, some effort has been made to improve documentation, especially in the range of the application flow and of the Package class API and lifecycle.

Besides the user documentation, extensive inline documentation has been added to explain why many parts of the code are they way they are. This should be very useful for future maintainers as well as for integrators.

Deprecations

  • The Package::STATUS_MODULES_ADDED constant has been deprecated and replaced by Package::STATUS_BOOTING
  • The Package::ACTION_READY constant has been deprecated and replaced by Package::ACTION_BOOTED
  • The Package::ACTION_FAILED_CONNECTION constant has been deprecated and replaced by Package::ACTION_FAILED_CONNECT

Full Changelog: 1.9.0...1.10.0