Today we released another Neos 9 Beta.
An astonishing amount of work was done at the Neos sprint in Dresden as well as around the sprint and on the train
Thanks to all who contributed <3.
- Bernhard Schmitt
- Thomas Heilmann
- Denny Lubitz
- Martin Ficzel
- Bastian Waidelich
- Christian Müller
- Sebastian Kurfürst
- Wilhelm Behncke
- Marc Henry Schultz
Upgrade instructions from Beta 14
previous beta → Neos 9 Beta-14 Release
In your composer.json you should require 9.0.0-beta15
for all Neos packages from the development distribution and for the NeosUi as well as Flow:
"neos/flow": "9.0.0-beta15",
"neos/neos": "9.0.0-beta15",
"neos/neos-ui": "9.0.0-beta15"
Maybe its necessary to flush the code cache due to changes in Flow itself:
./flow flow:cache:flush --force
The database can be migrated the following way:
A setup to apply the latest schema adjustments:
./flow doctrine:migrate
./flow cr:setup
Additionally, PRs marked with ⛁ need a dedicated migration
- ⛁¹ Migration to adjust serialization to multiple references per event / command
./flow migrateevents:migratesetreferencestomultinameformat
- ⛁² Migration to prune “lying” events from temporary content streams and further cleanup for a replay
Note that pruning from the event stream is to be used with care because of its implications see: Note regarding pruning from the event stream below.
# 0.) backup the events (cr_default_events)
./flow migrateevents:backup
# 1.) mark dangling content streams as removed (temporary ones and ones that are no longer in use)
./flow contentStream:removeDangling
# 2.) prune removed content streams that are not required for a full replay to work
./flow contentStream:pruneRemovedFromEventStream
# 3.) replay all projections
./flow cr:projectionReplayAll
Features
1.) Highlight Refactored, stabilised and faster publishing
- ⛁² !!! FEATURE: Publishing Version 3
- FEATURE: Integrate conflict resolution with publish/discard dialog workflow
The last beta uncovered a fundamental problem with the new workspace based publishing.
A partial publish / rebase could break the change and uri path projection.
You might have been faced with this error: “Changes in document test could not be published”:
Exception while catching up to sequence number drölf
or
Rebase failed
Bugfixes in publishing
- publish workspace will now behave exactly like partially publish and won’t throw an exception if the workspace is outdated but will attempt a rebase
- preserve always the initiating timestamp of nodes
- we repoint the workspace via
WorkspaceWasPartiallyPublished
before applying the applying remaining events - no dangling content streams that are not used but bloat up the projections
Neos Ui conflict resolution after failed publish
The new conflict resolution of the Neos Ui from Beta 10 was further polished so that a possible conflict after publishing can be solved directly without syncing explicitly.
Performance optimisations
- we do not rebase explicitly before the publishing but the publishing itself is a rebase (reducing the need of one fork)
- we run the partially publishing in simulation (reducing the need of one fork)
- a partial publish will be interpreted as full publish if all nodes are to be published
Excerpt of the new internal workings
With the new conceptualised publishing we only emit events to the other projections and catchup hooks if they are indeed to be published.
The constraint checks during the rebase / publish are done in simulation now:
We start a database transaction with later rollback for the content graph projection and then handle the rebased commands to see if they would pass today again.
The events to publish are first written into an in memory event store and later applied to the real content stream and fully catch up’d.
That means no projection or catchup hook has to deal with the complexity of temporary events that were partially a lie.
2.) Overhaul content stream pruner
As migration strategy for the in 1.) mentioned publishing problem we advise to use the content stream pruner.
It was reworked to operate fully on the event store instead of relying on projections to be up-to-date.
This also allowed us to remove lots of logic from the content stream projection like soft removal and also trying to track the in use status of a content stream.
In result the following commands can also be used in case the projection was not well, either to clean up or fully prune your system:
./flow cr:prune
./flow contentStream:removeDangling
(previously./flow contentStream:prune
)./flow contentStream:pruneRemovedFromEventStream
The need of removing dangling content streams should be an issue of the past after the new publishing.
But to check for integrity ./flow contentstream:status
can be used.
It detects if dangling content streams exists and which content streams could be pruned from the event stream.
A note regarding pruning from the event stream
Content streams that were removed ContentStreamWasRemoved
e.g. after publishing, and are not required for a full replay to reconstruct the current projections state.
That’s why we detect those and offer to prune them.
The ability to reconstitute a previous user workspace or shared workspace state will be lost.
Only the event stream for the root workspace (live) and for pending changes is untouched.
Dangling content streams: Content streams that are not removed via the event ContentStreamWasRemoved
and are not in use by a workspace.
!!! 3.) One main stable content graph core projection
- !!! TASK: Add workspace content stream mapping to content graph projection & Neos Ui Adjustments
- !!! TASK: Introduce first level content repository projection
- TASK: Cleanup projection catch-up trigger extensibility
- TASK: Remove references to
CommandResult
in return types - TASK: Yield events to publish in workspace command handler
The workspace and content stream projections (which were just one table each) are now moved into the content graph projection.
This stabilizes the behaviour as we don’t have to deal with one projection not being up-to-date
Also this change was long planned so the getContentGraph
call doesn’t have to look up foreign tables to fetch the workspace content stream id.
With this change the deprecated WorkspaceFinder
was removed and also the internal ContentStreamFinder
.
Instead, the ContentRepository offers the API:
/**
* Returns the workspace with the given name, or NULL if it does not exist in this content repository
*/
public function findWorkspaceByName(WorkspaceName $workspaceName): ?Workspace;
/**
* Returns all workspaces of this content repository. To limit the set, {@see Workspaces::find()} and {@see Workspaces::filter()} can be used
* as well as {@see Workspaces::getBaseWorkspaces()} and {@see Workspaces::getDependantWorkspaces()}.
*/
public function findWorkspaces(): Workspaces;
/** @internal */
public function findContentStreamById(ContentStreamId $contentStreamId): ?ContentStream;
For full upgrade instructions regarding the removal of the deprecated WorkspaceFinder
please look into the last beta.
Also, as we decided with Beta10 to catch up the projections synchronously (without ->block()
),
the code base was finally cleaned up of these old async artefacts and a lot of thought in general has been put in wiring everything together.
4.) Reliable and tested change node type behaviour
We introduced a more comprehensive test suite for ChangeNodeType
and added the following features:
- default values are now added if the property is yet missing
- !!! obsolete properties are now removed
- missing tethered children are now added
- disallowed children are now properly removed (in DELETE strategy)
- already present tethered children will be adjusted in type if necessary
- all the above is now applied recursively for nested tethered declarations
- the change projection is now able to deal with these aggregate scoped changes (
NodeAggregateTypeWasChanged
,NodeAggregateNameWasChanged
)
Further a bug in NodeRemoval was fixed where only one child node was removed per removed parent
5.) Fixes regarding workspace status and base workspace changing
- BUGFIX 4508 mark dependands of live outdated after direct change
- FEATURE: Introduce
Workspace::hasPublishableChanges
- BUGFIX: Change base workspace
The workspace status (Workspace::$status
) is now calculated more reliable on querying directly.
Previously changes to live would not render dependant workspaces outdated.
Also, a minimal concept of changes inside a workspace was introduced as boolean: Workspace::hasPublishableChanges()
.
And changing the base workspace now works completely again and shows the content of the new base.
6.) New node serialization format for all places
With Beta 11 the node uri building was overhauled.
Now the Neos Ui was also adapted to use the new node serialisation format, getting rid of Neos\Neos\FrontendRouting\NodeAddress
.
And custom ui plugins and endpoints will only need to deal with this one format:
localhost:8081/neos/content?node={"contentRepositoryId":"default","workspaceName":"marchenry","dimensionSpacePoint":{"language":"en_US"},"aggregateId":"000b42ff-c9d3-4b5e-b6de-56d35832dc0e"}
!!! 7.) Overhaul node references writing
Reworks references so that multiple reference properties can be set via a single command and also references can be attached to CreateNodeAggregateWithNode
.
Most importantly, references are now also respected when copying nodes.
The API to set references changed a little and code must be adjusted accordingly.
Note that SetNodeReferences
does not require the $referenceName
field anymore, which is now encapsulated inside NodeReferencesForName
.
This is a simple example which covers all cases:
SetNodeReferences::create(
$node->workspaceName,
$node->aggregateId,
$node->originDimensionSpacePoint,
NodeReferencesToWrite::create(
// sets the 3 nodes as references
NodeReferencesForName::fromTargets(
ReferenceName::fromString('first-reference'),
NodeAggregateIds::fromArray(['node-aggregate-id-1', 'node-aggregate-id-2', 'node-aggregate-id-3'])
),
// unset previously set references (as we do NOT merge the values)
NodeReferencesForName::createEmpty(
ReferenceName::fromString('second-reference')
),
// create a simple node reference and additionally a reference with an additional property
NodeReferencesForName::fromReferences(
ReferenceName::fromString('third-reference'),
[
NodeReferenceToWrite::fromTarget(NodeAggregateId::fromString('node-aggregate-id-6')),
NodeReferenceToWrite::fromTargetAndProperties(NodeAggregateId::fromString('node-aggregate-id-5'), PropertyValuesToWrite::fromArray([
'propertyOnReference' => 'Hi im living on the edge ;)'
])),
])
)
)
)
!!! 8.) Remainder Removal of deprecated node access from beta 14
The FlowQuery accessors id()
nodeTypeName()
and label()
were removed.
And the helper Neos.Node.getNodeType()
was renamed and behaviour changed to be nullable.
Neos 8 (Removed) | Neos 9 Beta 13 (Removed) | With Beta 14 and above |
---|---|---|
node.identifier |
q(node).id() |
node.aggregateId |
node.nodeType.name |
q(node).nodeTypeName() |
node.nodeTypeName |
node.label |
q(node).label() |
Neos.Node.label(node) |
node.nodeType |
Neos.Node.getNodeType(node) |
Neos.Node.nodeType(node) |
For full upgrade instructions please look into the last beta.
Further a tracer was introduced to log if the Neos 8 Node field access was used.
To enable full strict mode set Neos.Fusion.deprecationTracer
to "EXCEPTION"
so it throws during rendering.
24-09-24 DEBUG The Node field "label" is deprecated in "${q(site).property('titleOverride') || site.label}"
24-09-24 DEBUG The Node field "label" is deprecated in "${item.label}"
24-09-24 DEBUG The Node field "identifier" is deprecated in "${node.identifier}"
Bugfixes
Neos Content Repository
Neos Neos
- BUGFIX: Remove workspace creation from
EditorContentStreamZookeeper
& Neos Ui Adjustments - BUGFIX: Fix admin workspace permissions for workspaces without metadata
- BUGFIX: Improve error of nearest content collection
- BUGFIX: Ensure workspace roles and metadata are pruned with the CR.
- BUGFIX: Prevent projection failure due to missing resource
Flow
Neos Ui
- BUGIFX: Show hidden state only for directly disabled nodes without inheritance
- BUGFIX: Fix hidden state evaluation
Dev only relevant
List of things
Neos
- TASK: Behat tests for workspace permissions
- TASK: Make content repository service internal concept and avoid use in Neos.Neos
- TASK: Throw
InvalidArgumentException
as\Throwable
is not caught … - BUGFIX: Avoid escaping errors within Gherkin
- TASK: Remove PerformanceMeasurementCommand
- TASK: Remove migrations in CR setup
- TASK: Fix mini cosmetic Todos
- TASK: Cosmetic tweak to WorkspaceService
Neos Ui