Copilot commented on code in PR #8351:
URL: https://github.com/apache/texera/pull/8351#discussion_r3997455685


##########
frontend/src/app/workspace/service/workflow-graph/model/workflow-action.service.ts:
##########
@@ -747,25 +770,49 @@ export class WorkflowActionService {
   }
 
   public setWorkflowSettings(workflowSettings: WorkflowSettings | undefined): 
void {
-    if (this.workflowSettings === workflowSettings) {
+    const newSettings = workflowSettings === undefined ? 
this.getDefaultSettings() : workflowSettings;
+    // Skip a redundant write: setting the same value would still cut a Yjs 
update and observer
+    // churn for every collaborator.
+    if (isEqual(this.getWorkflowSettings(), newSettings)) {
       return;
     }
-
-    const newSettings = workflowSettings === undefined ? 
this.getDefaultSettings() : workflowSettings;
-    this.workflowSettings = newSettings;
+    this.texeraGraph.sharedModel.contentMetaMap.set("settings", newSettings);
   }
 
   public getWorkflowSettings(): WorkflowSettings {
-    return this.workflowSettings;
+    return (
+      (this.texeraGraph.sharedModel.contentMetaMap.get("settings") as 
WorkflowSettings) ?? this.getDefaultSettings()
+    );
   }
 
   /**
-   * Load a definition without announcing an edit. Used while opening a 
workflow, so
-   * that merely reading one does not look like a change and trigger a save.
+   * Seed workflowSettings into the shared model while opening a workflow, 
mirroring
+   * hydrateFormBinding: `undefined` deletes the key rather than writing 
defaults, so opening a
+   * workflow that never saved settings does not overwrite a co-editor's live 
ones (getWorkflow-
+   * Settings defaults on an absent key). Called under the reloading flag.
+   */
+  public hydrateSettings(workflowSettings: WorkflowSettings | undefined): void 
{
+    const contentMeta = this.texeraGraph.sharedModel.contentMetaMap;
+    if (workflowSettings === undefined) {
+      contentMeta.delete("settings");
+    } else {
+      contentMeta.set("settings", workflowSettings);

Review Comment:
   This seed is written immediately after `setNewSharedModel()` creates and 
connects a fresh Yjs document, before the provider's initial sync can complete. 
If the fetched workflow is stale relative to an active collaborator, this 
creates a concurrent whole-value write and Yjs may select and broadcast the 
stale settings—the lost update this PR is intended to prevent. Wait for initial 
provider sync and seed only when the shared key is still absent, or otherwise 
make the synchronized shared value authoritative.
   
   This issue also appears on line 814 of the same file.



##########
frontend/src/app/workspace/service/workflow-graph/model/workflow-action.service.ts:
##########
@@ -136,12 +137,34 @@ export class WorkflowActionService {
     );
     this.sharedModelChangeHandler.setConfigService(this.config);
     this.workflowMetadata = DEFAULT_WORKFLOW;
-    this.workflowSettings = this.getDefaultSettings();
     
this.undoRedoService.setUndoManager(this.texeraGraph.sharedModel.undoManager);
 
+    // Watch the shared content map, re-attaching whenever the shared model is 
recreated
+    // (opening another workflow), the same way SharedModelChangeHandler 
re-attaches its
+    // graph observers. A formBinding change from a local edit or a co-editor 
is republished
+    // on formBindingChanged$ so the Form View re-renders and the existing 
autosave picks it
+    // up. The reload seed is skipped -- like the graph seed -- so opening a 
workflow is not
+    // announced as an edit and does not save on every open.
+    this.observeContentMeta();
+    this.texeraGraph.newYDocLoadedSubject.subscribe(() => 
this.observeContentMeta());
+
     this.handleJointElementDrag();
   }
 
+  private observeContentMeta(): void {
+    // Detach the observer from the previous shared model before attaching to 
the new one, so
+    // re-attaching on each opened workflow does not stack listeners on the 
same map.
+    this.observedContentMetaMap?.unobserve(this.contentMetaObserver!);
+    const contentMetaMap = this.texeraGraph.sharedModel.contentMetaMap;
+    this.contentMetaObserver = event => {
+      if (event.changes.keys.has("formBinding") && 
!this.jointGraphWrapper.getReloadingWorkflow()) {
+        this.formBindingChangeSubject.next(this.getFormBinding());
+      }

Review Comment:
   The observer ignores `settings` changes. A co-editor's update reaches this 
map, but `SettingsComponent` only refreshes its form from `workflowChanged()`, 
and that stream currently receives only `formBindingChanged$` for content 
metadata. The settings panel therefore continues displaying stale values until 
an unrelated workflow event occurs. Please publish settings-map changes through 
a settings event consumed by the panel (or merged into `workflowChanged()`) and 
cover a direct/remote map update in the test.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to