Improve entity "sync configs"#72145
Conversation
| * @param {import('@wordpress/sync').ObjectData} record | ||
| * @return {import('@wordpress/sync').ObjectData} The initial data | ||
| */ | ||
| getInitialObjectData: ( record ) => record, |
There was a problem hiding this comment.
I don't really understand this one, isn't this a duplicate of syncProperties
There was a problem hiding this comment.
You're right, it is partially duplicative! I will update the description to remove the reference to excluded properties.
However, this function is necessary to compute derived properties for the initial load of the persisted entity record (SyncProvider#bootstrap). There is currently only one such example: blocks (derived from content, which is not synced).
Using this example, blocks are not part of the entity record and are not created when the entity is loaded into the store. Instead, core-data provides a hook that parses blocks from content. The block editor uses this hook and then (eventually, maybe) ships back the property as entity record edits.
However, we need to compute and load blocks (once) as part of the bootstrapping process. This ensures that we can correctly reconcile the entity with other peers and / or a persisted CRDT doc.
There was a problem hiding this comment.
However, this function is necessary to compute derived properties for the initial load of the persisted entity record (SyncProvider#bootstrap). There is currently only one such example: blocks (derived from content, which is not synced).
This is not just a problem for "sync", the absence of "blocks" on initial fetch is a problem for the whole core-data abstraction. I basically think that we don't have good support/behavior in core data for what we call "transient properties". I had tried to fixed that in the past and add more awareness for these to the framework (see #57500)
I think instead of getInitialObjectData, we should try to bring the idea of #57500 back to life again (having a get/set config for each transient property) at the entities config level but instead of changing how core-data work with these entirely, take a more iterative approach (only use it for sync for now). WDYT?
There was a problem hiding this comment.
The concept makes sense and I agree it's sorely needed. I can work it into the PR.
take a more iterative approach (only use it for sync for now).
My interpretation:
transientEditsproperties can betrue(current implementation) or an object with areadfunction property.- The
readfunction is called by thecore-dataresolver inside the experimental sync flag to materialize the transient properties on the record before passing it to the sync provider. - We will forego a
writefunction property for now.I wonder ifI think I talked myself out of this. :)persistor some other verb would be more appropriate. Awriteverb implies it is the opposite ofreadand should/would be called on each entity record edit. But transient properties are not "de-materialized" until the record is persisted.readis also performed once on entity fetch, so they are in fact opposites.
There was a problem hiding this comment.
Let's keep it contained for now and only call these "read/write" where you'd have previously used getInitialObjectData. I think there are other parts of core-data that could benefit from it but we should probably leave that separate as it could be a lot of work to make it right :)
There was a problem hiding this comment.
Implemented in 3cef376, with a test in 805e9b2.
I'll confirm @ingeniumed is credited with props for the initial resolver tests.
| * @param {import('@wordpress/sync').ObjectData} record | ||
| * @return {import('@wordpress/sync').ObjectID} The entity's ID | ||
| */ | ||
| getObjectId: ( { id } ) => id, |
There was a problem hiding this comment.
This is a duplicate of the key property of the entity config, so I don't think it's needed.
There was a problem hiding this comment.
Not sure I follow. The entity config defines the properties of an entity type and is shared across all instances of that entity. Most entity configs do not have a key property, including this one.
The "object ID" (as used by the sync provider) is equivalent to the entity record's ID, which is not known until it is loaded into the core-data store via getEntityRecord. This function allows the sync provider to extract the record ID from the entity record it is given. (This function is also not new, it exists in trunk as getSyncObjectId.)
We could instead have core-data actions and resolvers pass in the "object type" (entity kind/name) and "object ID" (record ID). I was following the existing pattern because I thought there was a desire for the entity config to centralize and control sync behavior, including identifiers. Happy to make the change, just let me know.
(I am borrowing the quoted terms from the initial implementation—we can definitely change them as well!)
There was a problem hiding this comment.
I thought there was a desire for the entity config to centralize and control sync behavior
Yes, this is the right approach but I think the original implementation was flawed as well in the sense that this configuration already exists in the "entity's config". core-data (without sync) need to know what it's the primary key of each record. It assumes it's id by default unless a key property is specified on the entity config object. In other words, this function is just a duplicate configuration that we can get rid of. (and just pass the full entity config, or augment the "syncConfig" automatically with the "key" property defined in the entity config)
There was a problem hiding this comment.
Got it, I'll rework. Thanks for the guidance!
| * | ||
| * @type {import('@wordpress/sync').ObjectType} | ||
| */ | ||
| objectType: `postType/${ postType.slug }`, |
There was a problem hiding this comment.
What is this exactly, can't we just use kind/name of the current entity instead?
There was a problem hiding this comment.
Yes, see above. This property exists in trunk as syncObjectType and is just carried forward. We could instead require kind / name to be passed in each time a sync provider method is called. Let me know and I'll happily update the code.
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message. To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
|
Size Change: +55 B (0%) Total Size: 2.07 MB
ℹ️ View Unchanged
|
|
Flaky tests detected in 811b0a1. 🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/18354093315
|
youknowriad
left a comment
There was a problem hiding this comment.
This is cool, I like where this is going.
|
@youknowriad The Core Backport action is failing. I believe this is due to this change to a PHPUnit test case. However, that unit test does not exist in WP Core. Is it ok to add the |
I'm not even sure why that change is required for unit tests to pass, but it is. I am guessing it has something to do with changing the |
This reverts commit 1804c11.
|
@youknowriad Nevermind, I realized that this PHP unit test requires a full |
* Add sync/src/config.ts and convert entrypoint to TypeScript * Remove sync configs for __unstableBase and postType * Update entity sync configs for clarity and utility * Update SyncProvider calling code * Update dependencies test case * Add "supports" map to declare future sync feature support * Remove enabled flag in favor of syncConfig presence * Update getInitialObjectData description * Fix reference to syncConfig.objectType * Pass in object type and object ID instead of computing them * transient * Add tests for resolvers * Clean up and fix resolver tests * Add test for transient property materialization * Remove getInitialObjectData * Fix block serialization call --------- Co-authored-by: chriszarate <czarate@git.wordpress.org> Co-authored-by: ingeniumed <ingeniumed@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org>
What?
Improve the types and shape of the entity "sync configs" to prepare for future improvements to the SyncProvider.
Why?
This lays the groundwork for:
SyncProviderHow?
syncConfigproperty.applyChangesToDoc=>applyChangesToCRDTDocfromCRDTDoc=>getChangesFromCRDTDocgetInitialObjectData. This allows entities to compute and sync derivative properties likeblocks(derived fromcontent).supportssub-property for future declaration of sync feature support.For now, many of the implementations remain simple (e.g.,
defaultApplyChangesToCRDTDoc) but will expand and improve in future PRs.Testing Instructions
Note: This provider uses requests to
admin-ajax.phpfor signaling and the initial connection is delayed.Testing Instructions for Keyboard
No UI changes in this pull request.
Screenshots or screencast
pr-1.mov