iTwin / imodel-transformer

API for exporting an iModel's parts and also importing them into another iModel
MIT License
3 stars 2 forks source link

Can't directly detect relationship deletes in reverse sync #54

Closed MichaelBelousov closed 1 year ago

MichaelBelousov commented 1 year ago

The way we currently set the targetRelInstanceId json property on external source aspects during branch workflows loses the information on which relationship was transformed during reverse-synchronization of deletes. I think this one is easier to visualize:

In packages/transformer/src/IModelTransformer.ts, in IModelTransformer.initRelationshipProvenance we store provenance like:

Forward Synchronization Reverse Synchronization
forward reverse

Note that if created in a reverse-synchronization, the aspect $A$ placed on the relationship (technically on its source element) in the provenance-owning database ($B$ for Branch) does not have any links back to the relationship in the branch $R_b$. So if later $M$ deletes $R_m$, and we want to forward synchronize that deletion back into $B$, then we can't find $R_b$ directly.

Instead we probably have to find the source and target elements of $R_m$ and read the mapping of those into $B$ to find $R_b$.

Federation guid provenance doesn't have this issue.

forward sync graph dot code
  digraph ForwardSync {
    node [shape=plaintext];
    Rm [label=<R<SUB>m</SUB>>];
    Rb [label=<R<SUB>b</SUB>>];
    B [shape=box]
    M [shape=circle]
    M -> B [label="forward" color=red];
    M -> Rm [label="inserted"];
    B -> Rb
    Rm -> Rb [label="synced" style=dotted];
    Rb -> A;
    A -> Identifier;
    A -> relInstId;
    relInstId -> Rb
    Identifier -> Rm
    { rank=same; M B }
    { rank=same; Rm Rb }
  }
  
reverse sync graph dot code
  digraph BackwardSync {
    node [shape=plaintext];
    Rm [label=<R<SUB>m</SUB>>];
    Rb [label=<<R<SUB>b</SUB>>];
    B [shape=box]
    M [shape=circle]
    M -> B [label="reverse" color=red dir=back];
    M -> Rm;
    B -> Rb [label="inserted"];
    Rm -> Rb [label="synced" style=dotted dir=back];
    Rb -> A;
    A -> Identifier;
    A -> relInstId;
    relInstId -> Rm
    Identifier -> Rm
    { rank=same; B M }
    { rank=same; Rb Rm }
  }
  
MichaelBelousov commented 1 year ago

my intended solution is to deprecate the json property targetRelInstanceId and in lieu of it introduce provenanceRelInstanceId. Which will always point to the relationship in provenanceDb. We will handle the old case by finding the end elements of the relationship in the source, and then seeing if an equivalent relationship exists between the target's version of those elements.

MichaelBelousov commented 1 year ago

the solution for this is now implemented in the federation-guid-optimization branch