orchestrator-core icon indicating copy to clipboard operation
orchestrator-core copied to clipboard

[Bug]: allPbNames in the GQL tree of product fails to return output

Open pboers1988 opened this issue 8 months ago • 2 comments

Contact Details

No response

What happened?

  products(first: $first, after: $after, sortBy: $sortBy, query: $query) {
    page {
      productId
      name
      description
      tag
      createdAt
      productType
      status
      productBlocks {
        name
      }
      fixedInputs {
        name
        value
      }
      endDate
      allPbNames
    }
    pageInfo {
      endCursor
      hasNextPage
      hasPreviousPage
      startCursor
      totalItems
      sortFields
      filterFields
    }
  }
}
 with the variables

{
  "first": 15,
  "after": 0,
  "sortBy": {
    "field": "name",
    "order": "ASC"
  }
}
{
  "data": null,
  "errors": [
    {
      "message": "Internal Server Error",
      "locations": [
        {
          "line": 19,
          "column": 7
        }
      ],
      "path": [
        "products",
        "page",
        1,
        "allPbNames"
      ],
      "extensions": {
        "error_type": "internal_error"
      }
    }
  ]
}

Version

3.2.0

What python version are you seeing the problem on?

All

Relevant log output


Tasks

  • [ ] Prevent the recursion error
  • [ ] Deduplicate names by using set()
  • [ ] Rename allPbNames to allProductBlockNames

pboers1988 avatar Apr 09 '25 11:04 pboers1988

Example traceback from surf orchestrator. This is most likely because of a recursive Product domain model.

Traceback (most recent call last):
  File "/usr/local/lib/python3.13/site-packages/graphql/execution/execute.py", line 530, in await_result
    return_type, field_nodes, info, path, await result
                                          ^^^^^^^^^^^^
  File "/usr/local/lib/python3.13/site-packages/strawberry/schema/schema_converter.py", line 754, in _async_resolver
    return await await_maybe(
           ^^^^^^^^^^^^^^^^^^
    ...<5 lines>...
    )
    ^
  File "/usr/local/lib/python3.13/site-packages/strawberry/utils/await_maybe.py", line 13, in await_maybe
    return await value
           ^^^^^^^^^^^
  File "/usr/local/lib/python3.13/site-packages/orchestrator/graphql/schemas/product.py", line 66, in all_pb_names
    names: list[str] = list(get_all_pb_names(model.product_blocks))
                       ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.13/site-packages/orchestrator/graphql/schemas/product.py", line 64, in get_all_pb_names
    yield from get_all_pb_names(product_block.depends_on)
  File "/usr/local/lib/python3.13/site-packages/orchestrator/graphql/schemas/product.py", line 64, in get_all_pb_names
    yield from get_all_pb_names(product_block.depends_on)
  File "/usr/local/lib/python3.13/site-packages/orchestrator/graphql/schemas/product.py", line 64, in get_all_pb_names
    yield from get_all_pb_names(product_block.depends_on)
  [Previous line repeated 980 more times]
  File "/usr/local/lib/python3.13/site-packages/orchestrator/graphql/schemas/product.py", line 60, in get_all_pb_names
    for product_block in product_blocks:
                         ^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.13/site-packages/sqlalchemy/ext/associationproxy.py", line 1507, in __iter__
    for member in self.col:
                  ^^^^^^^^
  File "/usr/local/lib/python3.13/site-packages/sqlalchemy/ext/associationproxy.py", line 1382, in <lambda>
    col = property(lambda self: self.lazy_collection())
                                ~~~~~~~~~~~~~~~~~~~~^^
  File "/usr/local/lib/python3.13/site-packages/sqlalchemy/ext/associationproxy.py", line 1316, in __call__
    return getattr(self.parent, self.target)  # type: ignore[no-any-return]
RecursionError: maximum recursion depth exceeded

Mark90 avatar Apr 09 '25 14:04 Mark90

For a product with no recursive product blocks, the allPbNames query works fine.

query MyQuery {
  products(filterBy: {field: "product_type", value: "Port"}) {
    page {
      description
      allPbNames
    }
  }
}
  "data": {
    "products": {
      "page": [
        {
          "description": "Service Port 1G",
          "allPbNames": [
            "Node",
            "SN8 Service Port"
          ]
        },

But for a product with recursive product blocks, you'll get the above error.

There is a fixture test/unit_tests/fixtures/products/product_blocks/product_block_one_nested.py which has recursive product block relations; this should be usable to reproduce the problem in a testcase.

Mark90 avatar Apr 09 '25 14:04 Mark90