Uploaded image for project: 'Fluid Infusion'
  1. Fluid Infusion
  2. FLUID-6194

Model relay will relay deletes even if transform is not invertible



    • Type: Bug
    • Status: Closed
    • Priority: Major
    • Resolution: Fixed
    • Affects Version/s: 2.0
    • Fix Version/s: 3.0
    • Component/s: Data Binder
    • Labels:


      The FLUID-5585 behaviour for relaying deletes through relays has been incorrectly implemented. In the case where the transform has no inverse, or the relay rule should otherwise not operate backwards, the deletion clearing will nonetheless be relayed back through the rule, trashing the model at the other end.

      The PCP channel work for GPII-2556 in https://github.com/GPII/universal/pull/549 included the following rule:

      // A mixin grade applied to the lifecycleManager's session by the pcpChannel
      fluid.defaults("gpii.flowManager.pcpChannel.sessionBinder", {
          modelRelay: {
              pcpChannel: {
                  source: { // Not "" because of FLUID-6192
                      segs: []
                  target: "{flowManager}.pcpChannel.model",
                  singleTransform: {
                      type: "gpii.flowManager.pcpChannel.sessionToPCP",
                      ontologyMetadata: "{ontologyHandler}.ontologyMetadata"

      No inverse is written for the sessionToPCP function so the relay should not operate backwards. However, when a DELETE is triggered at the PCP's end via

      gpii.flowManager.pcpChannel.sessionStop = function (pcpChannel) {
          pcpChannel.applier.change("", null, "DELETE");

      the following code in DataBinding.js is triggered:

          // TODO: This rather crummy function is the only site with a hard use of "path" as String
          fluid.transformToAdapter = function (transform, targetPath) {
              var basedTransform = {};
              basedTransform[targetPath] = transform; // TODO: Faulty with respect to escaping rules
              return function (trans, newValue, sourceSegs, targetSegs, changeRequest) {
                  if (changeRequest && changeRequest.type === "DELETE") {
                      trans.fireChangeRequest({type: "DELETE", path: targetPath}); // avoid mouse droppings in target document for FLUID-5585
                  // TODO: More efficient model that can only run invalidated portion of transform (need to access changeMap of source transaction)
                  fluid.model.transformWithRules(newValue, basedTransform, {finalApplier: trans});

      This exposes the fact that the generation of the "backward" adaptor is pretty clumsy in its ability to determine when a rule is invertible. It accepts any old rubbish from fluid.model.transform.invertConfiguration which doesn't usefully signal whether it has inverted anything or not.

                  if (sourcePath !== null) {
                      that.backwardHolder.model = fluid.model.transform.invertConfiguration(transform);
                      that.backwardAdapterImpl = fluid.transformToAdapter(that.backwardHolder.model, sourcePath);

      The reliance on "sourcePath" is a bit peculiar. Presumably this excludes "self-sufficient" transforms which source all material from within the transform from being inverted.




            antranig Antranig Basman
            antranig Antranig Basman
            0 Vote for this issue
            2 Start watching this issue