Description
Expected Behaviour
The batch resolver should return the resolved values for each item in the input list, regardless of the data structure being processed. This principle should hold true even when the resolver is passing a list(dictionary).
Current Behaviour
When passing a list of dictionaries as the output (with the order matching the input list), the batch resolver fails to resolve the output correctly and instead returns null.
Code snippet
#graph QL:
type Item {
id: ID!
name: String!
singleItem: SingleItem
}
type Sing
8000
leItem {
id: ID!
name: String!
}
input ItemFilter {
id: ID
name: String
}
type Query {
getItem(filter: ItemFilter): [Item] @aws_api_key
}
#Resolver
@router.batch_resolver(type_name="Item", field_name="singleItem", aggregate=True)
@tracer.capture_method
@cdk_gql.appsync_batch(2000) #Still need to use this to provide batch size
def query_getSingleItem(event: List[AppSyncResolverEvent]) ->List[SingleItem]:
# Get source IDs for DB lookup
logger.info(f"router 1:{router.current_event.field_name}")
item_ids = batch_util.get_required_ids(event_list = event, fieldname = "id")
logger.info(f"router 2:{router.current_event.field_name}")
# Clean up IDs
logger.debug(f"item_ids: {item_ids}")
unique_item_ids = set(item_ids)
if None in unique_item_ids:
unique_item_ids.remove(None)
unique_item_ids = list(unique_item_ids)
logger.debug(f"unique item_ids: {item_ids}")
# Get data from DB
single_items_dict = dao_item.get_single_items(unique_item_ids)
logger.debug(f"single_items_dict is : {single_items_dict}")
# creating output list
to_return = [single_items_dict.get(item_id) for item_id in item_ids]
logger.debug(f"to_return1: {to_return1}")
return to_return
Possible Solution
Since the resolver successfully handles list(list(dictionary)) (as verified), it should logically be able to resolve list(dictionary) as well. However, it fails to do so, suggesting that a minor adjustment in the resolver logic could be enough to fix the issue.
Steps to Reproduce
- Define the GraphQL Schema
Create a GraphQL schema where the Item type contains a single child object (singleItem) that expects a SingleItem dictionary.
type Item {
id: ID!
name: String!
singleItem: SingleItem
}
type SingleItem {
id: ID!
name: String!
}
input ItemFilter {
id: ID
name: String
}
type Query {
getItem(filter: ItemFilter): [Item] @aws_api_key
}
-
Implement the Batch Resolver
Use a batch resolver for the singleItem field in the Item type.
@router.batch_resolver(type_name="Item", field_name="singleItem", aggregate=True)
@tracer.capture_method
@cdk_gql.appsync_batch(2000) # Define batch size
def query_getSingleItem(event: List[AppSyncResolverEvent]) -> List[Any]:Resolver logic here
-
Execute the Query
Run the following GraphQL query to fetch Item details along with its singleItem child:
query MyQuery {
getItem {
id
name
singleItem {
id
name
}
}
} -
Observe the Output
The query unexpectedly returns null for singleItem, even though the resolver executes without errors.
Powertools for AWS Lambda (Python) version
latest
AWS Lambda function runtime
3.9
Packaging format used
PyPi
Debugging logs
2025-03-11T11:51:48.222Z
{
"level": "DEBUG",
"location": "query_getSingleItem:83",
"message": "unique item_ids: ['abc', 'def']",
"timestamp": "2025-03-11 11:51:48,221+0000",
"service": "App-Lambda",
"sampling_rate": "1",
"cold_start": false,
"function_name": "PreProd-US-PiVDCStack-GraphQLtestgraphqllambdaFF03-GPRwAJengh8X",
"function_memory_size": "128",
"function_arn": "arn:aws:lambda:ap-south-1:479714207670:function:PreProd-US-PiVDCStack-GraphQLtestgraphqllambdaFF03-GPRwAJengh8X",
"function_request_id": "4377fb67-a0b0-4e38-8500-4143c330518d",
"xray_trace_id": "1-67d023d4-05b4b3f029d74d1a2e2c73fc"
}
{"level":"DEBUG","location":"query_getSingleItem:83","message":"unique item_ids: ['abc', 'def']","timestamp":"2025-03-11 11:51:48,221+0000","service":"App-Lambda","sampling_rate":"1","cold_start":false,"function_name":"PreProd-US-PiVDCStack-GraphQLtestgraphqllambdaFF03-GPRwAJengh8X","function_memory_size":"128","function_arn":"arn:aws:lambda:ap-south-1:479714207670:function:PreProd-US-PiVDCStack-GraphQLtestgraphqllambdaFF03-GPRwAJengh8X","function_request_id":"4377fb67-a0b0-4e38-8500-4143c330518d","xray_trace_id":"1-67d023d4-05b4b3f029d74d1a2e2c73fc"}
2025-03-11T11:51:48.222Z
{
"level": "DEBUG",
"location": "query_getSingleItem:88",
"message": "single_items_dict is : {'abc': {'id': '135', 'name': 'SingleItem 1'}, 'def': {'id': '246', 'name': 'SingleItem 2'}}",
"timestamp": "2025-03-11 11:51:48,222+0000",
"service": "App-Lambda",
"sampling_rate": "1",
"cold_start": false,
"function_name": "PreProd-US-PiVDCStack-GraphQLtestgraphqllambdaFF03-GPRwAJengh8X",
"function_memory_size": "128",
"function_arn": "arn:aws:lambda:ap-south-1:479714207670:function:PreProd-US-PiVDCStack-GraphQLtestgraphqllambdaFF03-GPRwAJengh8X",
"function_request_id": "4377fb67-a0b0-4e38-8500-4143c330518d",
"xray_trace_id": "1-67d023d4-05b4b3f029d74d1a2e2c73fc"
}
{"level":"DEBUG","location":"query_getSingleItem:88","message":"single_items_dict is : {'abc': {'id': '135', 'name': 'SingleItem 1'}, 'def': {'id': '246', 'name': 'SingleItem 2'}}","timestamp":"2025-03-11 11:51:48,222+0000","service":"App-Lambda","sampling_rate":"1","cold_start":false,"function_name":"PreProd-US-PiVDCStack-GraphQLtestgraphqllambdaFF03-GPRwAJengh8X","function_memory_size":"128","function_arn":"arn:aws:lambda:ap-south-1:479714207670:function:PreProd-US-PiVDCStack-GraphQLtestgraphqllambdaFF03-GPRwAJengh8X","function_request_id":"4377fb67-a0b0-4e38-8500-4143c330518d","xray_trace_id":"1-67d023d4-05b4b3f029d74d1a2e2c73fc"}
2025-03-11T11:51:48.222Z
{
"level": "DEBUG",
"location": "query_getSingleItem:93",
"message": "to_return1: [{'id': '135', 'name': 'SingleItem 1'}, {'id': '246', 'name': 'SingleItem 2'}]",
"timestamp": "2025-03-11 11:51:48,222+0000",
"service": "App-Lambda",
"sampling_rate": "1",
"cold_start": false,
"function_name": "PreProd-US-PiVDCStack-GraphQLtestgraphqllambdaFF03-GPRwAJengh8X",
"function_memory_size": "128",
"function_arn": "arn:aws:lambda:ap-south-1:479714207670:function:PreProd-US-PiVDCStack-GraphQLtestgraphqllambdaFF03-GPRwAJengh8X",
"function_request_id": "4377fb67-a0b0-4e38-8500-4143c330518d",
"xray_trace_id": "1-67d023d4-05b4b3f029d74d1a2e2c73fc"
}
Metadata
Metadata
Assignees
Type
Projects
Status