Skip to content

Commit 098d5d9

Browse files
snopokeclaude
andcommitted
feat: support setting task ID on creation
Adds a `task_id` argument to create_task/Task.create, letting callers assign a UUID or shortened UUID. The ID is passed through to the server, which validates uniqueness. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent c35df8a commit 098d5d9

7 files changed

Lines changed: 66 additions & 12 deletions

File tree

taskbadger.yaml

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,11 @@ components:
685685
PatchedTaskRequest:
686686
type: object
687687
properties:
688+
id:
689+
type: string
690+
minLength: 1
691+
description: Task ID. May be set on creation to a UUID or shortened UUID;
692+
it must be unique and is immutable thereafter. If omitted, an ID is generated.
688693
name:
689694
type: string
690695
minLength: 1
@@ -778,8 +783,8 @@ components:
778783
properties:
779784
id:
780785
type: string
781-
readOnly: true
782-
description: Task ID
786+
description: Task ID. May be set on creation to a UUID or shortened UUID;
787+
it must be unique and is immutable thereafter. If omitted, an ID is generated.
783788
organization:
784789
type: string
785790
readOnly: true
@@ -873,7 +878,6 @@ components:
873878
to 'value'.
874879
required:
875880
- created
876-
- id
877881
- name
878882
- organization
879883
- project
@@ -884,6 +888,11 @@ components:
884888
TaskRequest:
885889
type: object
886890
properties:
891+
id:
892+
type: string
893+
minLength: 1
894+
description: Task ID. May be set on creation to a UUID or shortened UUID;
895+
it must be unique and is immutable thereafter. If omitted, an ID is generated.
887896
name:
888897
type: string
889898
minLength: 1

taskbadger/internal/models/patched_task_request.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
class PatchedTaskRequest:
2323
"""
2424
Attributes:
25+
id (str | Unset): Task ID. May be set on creation to a UUID or shortened UUID; it must be unique and is
26+
immutable thereafter. If omitted, an ID is generated.
2527
name (str | Unset): Name of the task
2628
queue (str | Unset): Queue the task is from
2729
status (StatusEnum | Unset): * `pending` - pending
@@ -48,6 +50,7 @@ class PatchedTaskRequest:
4850
tags (PatchedTaskRequestTags | Unset): Tags for the task represented as a mapping from 'namespace' to 'value'.
4951
"""
5052

53+
id: str | Unset = UNSET
5154
name: str | Unset = UNSET
5255
queue: str | Unset = UNSET
5356
status: StatusEnum | Unset = StatusEnum.PENDING
@@ -65,6 +68,8 @@ class PatchedTaskRequest:
6568
def to_dict(self) -> dict[str, Any]:
6669
from ..models.patched_task_request_tags import PatchedTaskRequestTags
6770

71+
id = self.id
72+
6873
name = self.name
6974

7075
queue = self.queue
@@ -124,6 +129,8 @@ def to_dict(self) -> dict[str, Any]:
124129
field_dict: dict[str, Any] = {}
125130
field_dict.update(self.additional_properties)
126131
field_dict.update({})
132+
if id is not UNSET:
133+
field_dict["id"] = id
127134
if name is not UNSET:
128135
field_dict["name"] = name
129136
if queue is not UNSET:
@@ -156,6 +163,8 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
156163
from ..models.patched_task_request_tags import PatchedTaskRequestTags
157164

158165
d = dict(src_dict)
166+
id = d.pop("id", UNSET)
167+
159168
name = d.pop("name", UNSET)
160169

161170
queue = d.pop("queue", UNSET)
@@ -249,6 +258,7 @@ def _parse_stale_timeout(data: object) -> int | None | Unset:
249258
tags = PatchedTaskRequestTags.from_dict(_tags)
250259

251260
patched_task_request = cls(
261+
id=id,
252262
name=name,
253263
queue=queue,
254264
status=status,

taskbadger/internal/models/task.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
class Task:
2323
"""
2424
Attributes:
25-
id (str): Task ID
2625
organization (str):
2726
project (str):
2827
name (str): Name of the task
@@ -31,6 +30,8 @@ class Task:
3130
updated (datetime.datetime):
3231
url (str):
3332
public_url (str):
33+
id (str | Unset): Task ID. May be set on creation to a UUID or shortened UUID; it must be unique and is
34+
immutable thereafter. If omitted, an ID is generated.
3435
queue (str | Unset): Queue the task is from
3536
status (StatusEnum | Unset): * `pending` - pending
3637
* `pre_processing` - pre_processing
@@ -56,7 +57,6 @@ class Task:
5657
tags (TaskTags | Unset): Tags for the task represented as a mapping from 'namespace' to 'value'.
5758
"""
5859

59-
id: str
6060
organization: str
6161
project: str
6262
name: str
@@ -65,6 +65,7 @@ class Task:
6565
updated: datetime.datetime
6666
url: str
6767
public_url: str
68+
id: str | Unset = UNSET
6869
queue: str | Unset = UNSET
6970
status: StatusEnum | Unset = StatusEnum.PENDING
7071
value: int | None | Unset = UNSET
@@ -81,8 +82,6 @@ class Task:
8182
def to_dict(self) -> dict[str, Any]:
8283
from ..models.task_tags import TaskTags
8384

84-
id = self.id
85-
8685
organization = self.organization
8786

8887
project = self.project
@@ -100,6 +99,8 @@ def to_dict(self) -> dict[str, Any]:
10099

101100
public_url = self.public_url
102101

102+
id = self.id
103+
103104
queue = self.queue
104105

105106
status: str | Unset = UNSET
@@ -158,7 +159,6 @@ def to_dict(self) -> dict[str, Any]:
158159
field_dict.update(self.additional_properties)
159160
field_dict.update(
160161
{
161-
"id": id,
162162
"organization": organization,
163163
"project": project,
164164
"name": name,
@@ -169,6 +169,8 @@ def to_dict(self) -> dict[str, Any]:
169169
"public_url": public_url,
170170
}
171171
)
172+
if id is not UNSET:
173+
field_dict["id"] = id
172174
if queue is not UNSET:
173175
field_dict["queue"] = queue
174176
if status is not UNSET:
@@ -199,8 +201,6 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
199201
from ..models.task_tags import TaskTags
200202

201203
d = dict(src_dict)
202-
id = d.pop("id")
203-
204204
organization = d.pop("organization")
205205

206206
project = d.pop("project")
@@ -222,6 +222,8 @@ def _parse_value_percent(data: object) -> int | None:
222222

223223
public_url = d.pop("public_url")
224224

225+
id = d.pop("id", UNSET)
226+
225227
queue = d.pop("queue", UNSET)
226228

227229
_status = d.pop("status", UNSET)
@@ -313,7 +315,6 @@ def _parse_stale_timeout(data: object) -> int | None | Unset:
313315
tags = TaskTags.from_dict(_tags)
314316

315317
task = cls(
316-
id=id,
317318
organization=organization,
318319
project=project,
319320
name=name,
@@ -322,6 +323,7 @@ def _parse_stale_timeout(data: object) -> int | None | Unset:
322323
updated=updated,
323324
url=url,
324325
public_url=public_url,
326+
id=id,
325327
queue=queue,
326328
status=status,
327329
value=value,

taskbadger/internal/models/task_request.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ class TaskRequest:
2323
"""
2424
Attributes:
2525
name (str): Name of the task
26+
id (str | Unset): Task ID. May be set on creation to a UUID or shortened UUID; it must be unique and is
27+
immutable thereafter. If omitted, an ID is generated.
2628
queue (str | Unset): Queue the task is from
2729
status (StatusEnum | Unset): * `pending` - pending
2830
* `pre_processing` - pre_processing
@@ -49,6 +51,7 @@ class TaskRequest:
4951
"""
5052

5153
name: str
54+
id: str | Unset = UNSET
5255
queue: str | Unset = UNSET
5356
status: StatusEnum | Unset = StatusEnum.PENDING
5457
value: int | None | Unset = UNSET
@@ -67,6 +70,8 @@ def to_dict(self) -> dict[str, Any]:
6770

6871
name = self.name
6972

73+
id = self.id
74+
7075
queue = self.queue
7176

7277
status: str | Unset = UNSET
@@ -128,6 +133,8 @@ def to_dict(self) -> dict[str, Any]:
128133
"name": name,
129134
}
130135
)
136+
if id is not UNSET:
137+
field_dict["id"] = id
131138
if queue is not UNSET:
132139
field_dict["queue"] = queue
133140
if status is not UNSET:
@@ -160,6 +167,8 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
160167
d = dict(src_dict)
161168
name = d.pop("name")
162169

170+
id = d.pop("id", UNSET)
171+
163172
queue = d.pop("queue", UNSET)
164173

165174
_status = d.pop("status", UNSET)
@@ -252,6 +261,7 @@ def _parse_stale_timeout(data: object) -> int | None | Unset:
252261

253262
task_request = cls(
254263
name=name,
264+
id=id,
255265
queue=queue,
256266
status=status,
257267
value=value,

taskbadger/sdk.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ def create_task(
152152
monitor_id: str = None,
153153
tags: dict[str, str] = None,
154154
queue: str = None,
155+
task_id: str = None,
155156
) -> "Task":
156157
"""Create a Task.
157158
@@ -167,6 +168,8 @@ def create_task(
167168
monitor_id: ID of the monitor to associate this task with.
168169
tags: Dictionary of namespace -> value tags.
169170
queue: Name of the queue the task is from.
171+
task_id: ID to assign to the task. May be a UUID or shortened UUID; it must be
172+
unique and is immutable. If omitted, an ID is generated by the server.
170173
171174
Returns:
172175
Task: The created Task object.
@@ -175,6 +178,8 @@ def create_task(
175178
"name": name,
176179
"status": status,
177180
}
181+
if task_id is not None:
182+
task_dict["id"] = task_id
178183
if queue is not None:
179184
task_dict["queue"] = queue
180185
if value is not None:
@@ -335,6 +340,7 @@ def create(
335340
monitor_id: str = None,
336341
tags: dict[str, str] = None,
337342
queue: str = None,
343+
task_id: str = None,
338344
) -> "Task":
339345
"""Create a new task
340346
@@ -352,6 +358,7 @@ def create(
352358
monitor_id=monitor_id,
353359
tags=tags,
354360
queue=queue,
361+
task_id=task_id,
355362
)
356363

357364
def __init__(self, task):

tests/test_sdk.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,22 @@ def test_create_with_queue(settings, patched_create):
114114
)
115115

116116

117+
def test_create_with_task_id(settings, patched_create):
118+
api_task = task_for_test()
119+
patched_create.return_value = Response(HTTPStatus.OK, b"", {}, api_task)
120+
121+
task_id = "b3f8c1e2-1234-4a5b-8c9d-0e1f2a3b4c5d"
122+
Task.create(name="task name", task_id=task_id)
123+
124+
request = TaskRequest(name="task name", status=StatusEnum.PENDING, id=task_id)
125+
patched_create.assert_called_with(
126+
client=mock.ANY,
127+
organization_slug="org",
128+
project_slug="project",
129+
body=request,
130+
)
131+
132+
117133
def test_update_queue(settings, patched_update):
118134
api_task = task_for_test()
119135
task = Task(api_task)

tests/utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ def task_for_test(**kwargs):
1515
kwargs["created"] = datetime.datetime.now(datetime.timezone.utc)
1616
kwargs["updated"] = datetime.datetime.now(datetime.timezone.utc)
1717
return TaskInternal(
18-
task_id,
1918
"org",
2019
"project",
2120
"task_name",
21+
id=task_id,
2222
**kwargs,
2323
)

0 commit comments

Comments
 (0)