Skip to content

Split the DbLink table to allow link uniquess constraints on database level #2238

Open
@sphuber

Description

@sphuber

Currently, the fact that the DbNode and DbLink table are single tables makes it hard to implement the link uniqueness constraints on the database level. As a result we currently have the aiida.orm.utils.links.validate_link function, that performs these checks. However, ideally this is done on the database level.

To implement this, one needs to split the DbNode table into three separate tables:

  • DbWorfklowNode
  • DbCalculationNode
  • DbDataNode

The DbLink table can then be split into six tables, one for each link type:

  • DbCreate
  • DbReturn
  • DbCallCalc
  • DbCallWork
  • DbInputCalc
  • DbInputWork

Each of these link tables will have three columns source, target, label, denoting the source node, target node and the link label. The uniqueness constraints would then be as follows:

  • DbCreate
    • Unique('target')
    • Unique('source', 'label')
  • DbReturn
    • Unique('source', 'label')
  • DbCallCalc
    • Unique('target')
    • Unique('source', 'label') (optional)
  • DbCallWork
    • Unique('target')
    • Unique('source', 'label') (optional)
  • DbInputCalc
    • Unique('target', 'label')
  • DbInputWork
    • Unique('target', 'label')

This would also allow to reinsert the following piece of code that was removed from Node._add_dblink_from in commit that automatically generated links in a thread safe way, based on database constraints:


        if label is None:
            autolabel_idx = 1

            existing_from_autolabels = list(DbLink.objects.filter(
                output=self._dbnode,
                label__startswith="link_").values_list('label', flat=True))

            while "link_{}".format(autolabel_idx) in existing_from_autolabels:
                autolabel_idx += 1

            safety_counter = 0
            while True:
                safety_counter += 1
                if safety_counter > 100:
                    # Well, if you have more than 100 concurrent addings
                    # to the same node, you are clearly doing something wrong...
                    raise InternalError("Hey! We found more than 100 concurrent"
                                        " adds of links "
                                        "to the same nodes! Are you really doing that??")
                try:
                    self._do_create_link(src, "link_{}".format(autolabel_idx), link_type)
                    break
                except UniquenessError:
                    # Retry loop until you find a new loop
                    autolabel_idx += 1

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions