Skip to content

Commit 64267a7

Browse files
committed
fix: Don't generate empty metadata change events in VertexTaskStore (#962)
For #751
1 parent 3468180 commit 64267a7

2 files changed

Lines changed: 53 additions & 1 deletion

File tree

src/a2a/contrib/tasks/vertex_task_store.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,12 @@ def _get_metadata_change_event(
116116
task: CompatTask,
117117
event_sequence_number: int,
118118
) -> vertexai_types.TaskEvent | None:
119-
if task.metadata != previous_task.metadata:
119+
# We generate metadata change events if the metadata was changed.
120+
# We don't generate events if the metadata was changed from
121+
# one empty value to another, e.g. {} to None.
122+
if task.metadata != previous_task.metadata and (
123+
task.metadata or previous_task.metadata
124+
):
120125
return vertexai_types.TaskEvent(
121126
event_data=vertexai_types.TaskEventData(
122127
metadata_change=vertexai_types.TaskMetadataChange(

tests/contrib/tasks/test_vertex_task_store.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,53 @@ async def test_metadata_field_mapping(
534534
assert retrieved_none.metadata == {}
535535

536536

537+
@pytest.mark.asyncio
538+
async def test_metadata_empty_transitions(
539+
vertex_store: VertexTaskStore,
540+
) -> None:
541+
"""Test that updating metadata between {} and None does not generate events."""
542+
task_id = 'task-metadata-empty-test'
543+
544+
# Step 1: Create task with metadata={}
545+
task = Task(
546+
id=task_id,
547+
context_id='session-meta-empty',
548+
status=TaskStatus(state=TaskState.submitted),
549+
kind='task',
550+
metadata={},
551+
)
552+
await vertex_store.save(task)
553+
554+
full_name = f'{vertex_store._agent_engine_resource_id}/a2aTasks/{task_id}'
555+
556+
# Get initial event sequence number
557+
stored_task_before = (
558+
await vertex_store._client.aio.agent_engines.a2a_tasks.get(full_name)
559+
)
560+
initial_seq = stored_task_before.next_event_sequence_number
561+
562+
# Step 2: Update metadata to None
563+
updated_task = task.model_copy(deep=True)
564+
updated_task.metadata = None
565+
await vertex_store.save(updated_task)
566+
567+
# Step 3: Update back to {}
568+
task_back = updated_task.model_copy(deep=True)
569+
task_back.metadata = {}
570+
await vertex_store.save(task_back)
571+
572+
# Verify that retrieved task still has {} (due to mapping)
573+
retrieved = await vertex_store.get(task_id)
574+
assert retrieved is not None
575+
assert retrieved.metadata == {}
576+
577+
# Verify that next_event_sequence_number did NOT increase (no events generated)
578+
stored_task_after = (
579+
await vertex_store._client.aio.agent_engines.a2a_tasks.get(full_name)
580+
)
581+
assert stored_task_after.next_event_sequence_number == initial_seq
582+
583+
537584
@pytest.mark.asyncio
538585
async def test_update_task_status_details(
539586
vertex_store: VertexTaskStore,

0 commit comments

Comments
 (0)