1212
1313
1414class _Unset :
15- """Sentinel distinguishing "field omitted" from "field explicitly set to null"
16- in a PATCH-style update, so an explicit null can clear a column while an
17- omitted field is left untouched."""
15+ """Sentinel: PATCH field omitted (untouched) vs. explicitly null (cleared)."""
1816
1917
2018UNSET : Any = _Unset ()
@@ -106,11 +104,8 @@ async def update_mutable_fields_on_task(
106104 merge_params : dict [str , Any ] | None = None ,
107105 current_state : str | None | _Unset = UNSET ,
108106 ) -> TaskEntity :
109- """Update mutable fields on a task entity. This is used by our API since not all fields should be mutable.
110-
111- ``current_state`` uses the UNSET sentinel so an explicit null clears the
112- column while an omitted field leaves it untouched. ``task_metadata`` keeps
113- its legacy semantics (``None`` means "not supplied").
107+ """Update mutable fields on a task. ``current_state`` uses the UNSET sentinel
108+ (explicit null clears, omitted leaves it); ``task_metadata`` None means "not supplied".
114109 """
115110
116111 if not id and not name :
@@ -134,21 +129,15 @@ async def update_mutable_fields_on_task(
134129 ):
135130 return task_entity
136131
137- # `merge_params` is a separate atomic JSONB shallow-merge so concurrent
138- # callers don't overwrite each other's fields. Run it first so the
139- # refreshed entity it returns becomes the value we return if no scalar
140- # field updates follow.
132+ # Atomic JSONB shallow-merge; run first so its refreshed entity is the fallback return.
141133 if merge_params :
142134 merged = await self .task_service .merge_task_params (
143135 task_entity .id , merge_params
144136 )
145137 if merged is not None :
146138 task_entity = merged
147139
148- # Apply task_metadata/current_state via a single column-scoped atomic
149- # update — one task_updated publish, and (unlike a whole-row merge) no
150- # risk of clobbering a concurrently changed status/params. current_state
151- # rides that publish, powering reactive delivery to stream consumers.
140+ # Single column-scoped write → one task_updated publish, no whole-row clobber.
152141 fields : dict [str , Any ] = {}
153142 if task_metadata is not None :
154143 fields ["task_metadata" ] = task_metadata
@@ -159,11 +148,7 @@ async def update_mutable_fields_on_task(
159148 task_entity .id , fields
160149 )
161150 if updated is None :
162- # The row vanished between the initial read and the write. No live
163- # hard-delete path reaches here today (delete is a soft status
164- # update, already guarded above), so this is defensive — but raise
165- # rather than return stale data, matching the not-found contract
166- # above and the sibling terminal-transition methods.
151+ # Row vanished mid-flight (defensive; no live hard-delete path). Raise, don't return stale.
167152 raise ItemDoesNotExist (f"Task { id or name } not found" )
168153 task_entity = updated
169154
0 commit comments