-
Notifications
You must be signed in to change notification settings - Fork 13
feat(spider-py): Add Data, Task, and TaskGraph to core.
#180
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 118 commits
d2ac198
cc8a097
7f68bdc
2394649
6ff3e33
7ae8a78
56502f9
6f6becf
a74523d
2345d22
77ee494
38b86c8
3698339
369e9f1
90aa5a2
1769c95
edaa834
7faac8f
f494a90
eb01bb2
ff2fe1c
d476e42
850126d
65841a0
8564fc2
a6e7d29
573b448
6ad72c3
ba7c6e5
209acb1
406b514
66892f5
80f0a10
3186a42
0925938
6936a9b
7407090
6a95b24
f29dcba
453f209
d1011c7
a7dc642
a7d92c2
1c6213b
0f13d07
14d6326
55a727a
c98fea1
ef64454
09ba8ad
4e7237e
1f944d0
68992fc
1127b22
4c51c91
56878b2
bb428c9
944bd5e
d75bc15
4b7eca2
8ddbda7
0d998ec
6004d64
bcab5db
a50d25a
fbebb96
0322bd5
2a08155
dd29c23
570cf2f
9b2a175
32afe0a
0b62f73
7384158
70ef90a
1aae0cb
2f9b4a0
4e080ac
b09515c
bad9675
e009ff4
f11a3b6
a0407a7
aa9a8de
3c7e794
ca4ec29
b4d6576
23f31cd
0167ac0
5a9cb76
f447614
a84de83
f94460f
2d1b6fc
5a35122
061d101
451a80e
de149ee
d332dbe
8c27b16
1b7ab77
95b98c8
e7b119c
8ffbd03
427dd6b
a9c9e57
854cd11
5565c9e
a9791e5
01dd0c6
c6ccce6
01c9c64
b86d47c
008c6fb
4d10f88
f6192a3
ea76464
9448189
be143a7
c4c035a
fa935d1
08b7965
b07c858
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,32 @@ | ||
| """Spider core package.""" | ||
|
|
||
| from .data import Data, DataId | ||
| from .task import ( | ||
| Task, | ||
| TaskId, | ||
| TaskInput, | ||
| TaskInputData, | ||
| TaskInputOutput, | ||
| TaskInputValue, | ||
| TaskOutput, | ||
| TaskOutputData, | ||
| TaskOutputValue, | ||
| TaskState, | ||
| ) | ||
| from .taskgraph import TaskGraph | ||
|
|
||
| __all__ = [ | ||
| "Data", | ||
| "DataId", | ||
| "Task", | ||
| "TaskGraph", | ||
| "TaskId", | ||
| "TaskInput", | ||
| "TaskInputData", | ||
| "TaskInputOutput", | ||
| "TaskInputValue", | ||
| "TaskOutput", | ||
| "TaskOutputData", | ||
| "TaskOutputValue", | ||
| "TaskState", | ||
| ] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| """Data module for Spider.""" | ||
|
|
||
| from dataclasses import dataclass | ||
| from uuid import UUID | ||
|
|
||
| DataId = UUID | ||
|
|
||
|
|
||
| @dataclass | ||
| class Data: | ||
| """Represents a data object.""" | ||
|
|
||
| id: DataId | ||
| value: bytes |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,50 @@ | ||
| """Task module for Spider.""" | ||
|
|
||
| from dataclasses import dataclass, field | ||
| from enum import IntEnum | ||
| from uuid import UUID, uuid4 | ||
|
|
||
| from spider_py.core.data import DataId | ||
|
|
||
| TaskId = UUID | ||
|
|
||
|
|
||
| @dataclass | ||
| class TaskInputOutput: | ||
| """Represents a task input that points to output of another task""" | ||
|
|
||
| task_id: TaskId | ||
| position: int | ||
|
|
||
|
|
||
| TaskInputValue = bytes | ||
| TaskInputData = DataId | ||
| TaskInput = TaskInputOutput | TaskInputValue | TaskInputData | ||
|
|
||
| TaskOutputValue = bytes | ||
| TaskOutputData = DataId | ||
| TaskOutput = TaskOutputValue | TaskOutputData | ||
|
|
||
|
|
||
| class TaskState(IntEnum): | ||
| """Represents state of a task""" | ||
|
sitaowang1998 marked this conversation as resolved.
Outdated
|
||
|
|
||
| Pending = 0 | ||
| Ready = 1 | ||
| Running = 2 | ||
| Succeeded = 3 | ||
| Failed = 4 | ||
| Cancelled = 5 | ||
|
|
||
|
|
||
| @dataclass | ||
| class Task: | ||
| """Represents a task in Spider.""" | ||
|
|
||
| task_id: TaskId = field(default_factory=uuid4) | ||
| function_name: str = "" | ||
| state: TaskState = TaskState.Pending | ||
| timeout: float = 0 | ||
| max_retries: int = 0 | ||
| task_inputs: list[TaskInput] = field(default_factory=list) | ||
| task_outputs: list[TaskOutput] = field(default_factory=list) | ||
|
Comment on lines
+44
to
+50
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Validate basic Task invariants (non-negative timeout and retries) Prevent obviously invalid state early. @dataclass
class Task:
@@
task_outputs: list[TaskOutput] = field(default_factory=list)
+
+ def __post_init__(self) -> None:
+ if self.timeout < 0:
+ raise ValueError("timeout must be non-negative")
+ if self.max_retries < 0:
+ raise ValueError("max_retries must be non-negative")🤖 Prompt for AI Agents |
||
|
sitaowang1998 marked this conversation as resolved.
|
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,56 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """TaskGraph module for Spider.""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from spider_py.core.task import Task, TaskId | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| class TaskGraph: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """Represents a task graph in Spider.""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def __init__(self) -> None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """Initializes an empty task graph.""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.tasks: dict[TaskId, Task] = {} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Dependency list consists of a list of tuples of | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # - parent task id | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # - child task id | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
sitaowang1998 marked this conversation as resolved.
Outdated
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.dependencies: list[tuple[TaskId, TaskId]] = [] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.input_tasks: set[TaskId] = set() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.output_tasks: set[TaskId] = set() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def add_task( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self, task: Task, parents: list[TaskId] | None = None, children: list[TaskId] | None = None | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) -> None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Adds a task to the graph. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| :param task: The task to add. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| :param parents: The parent ids of the task. Must be already in the task graph. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| :param children: The children ids of the task. Must be already in the task graph. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.tasks[task.task_id] = task | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if parents: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
sitaowang1998 marked this conversation as resolved.
Outdated
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for parent in parents: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.dependencies.append((parent, task.task_id)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.output_tasks.discard(parent) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.input_tasks.add(task.task_id) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if children: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
sitaowang1998 marked this conversation as resolved.
Outdated
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for child in children: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.dependencies.append((task.task_id, child)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.input_tasks.discard(child) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.output_tasks.add(task.task_id) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+19
to
+
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Enforce graph invariants and prevent silent overwrites Currently, add_task does not validate that parents/children exist nor that task_id is unique, despite the docstring implying this precondition. This can introduce dangling edges and allow accidental overwrites. Apply: def add_task(
self, task: Task, parents: list[TaskId] | None = None, children: list[TaskId] | None = None
) -> None:
@@
- self.tasks[task.task_id] = task
+ # Validate constraints before mutating state
+ if task.task_id in self.tasks:
+ raise ValueError(f"Task with id {task.task_id} already exists in the graph")
+ if parents:
+ for parent in parents:
+ if parent not in self.tasks:
+ raise ValueError(f"Parent task id {parent} is not present in the graph")
+ if children:
+ for child in children:
+ if child not in self.tasks:
+ raise ValueError(f"Child task id {child} is not present in the graph")
+
+ self.tasks[task.task_id] = task
if parents:
for parent in parents:
self.dependencies.append((parent, task.task_id))
self.output_tasks.discard(parent)
else:
self.input_tasks.add(task.task_id)
if children:
for child in children:
self.dependencies.append((task.task_id, child))
self.input_tasks.discard(child)
else:
self.output_tasks.add(task.task_id)📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def get_parents(self, task_id: TaskId) -> list[Task]: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Gets parent tasks of task. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| :param task_id: ID of the task. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| :return: List of parent tasks. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
sitaowang1998 marked this conversation as resolved.
Outdated
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return [self.tasks[parent] for (parent, child) in self.dependencies if child == task_id] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def get_children(self, task_id: TaskId) -> list[Task]: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Gets child tasks of task. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| :param task_id: ID of the task. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| :return: List of children tasks. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return [self.tasks[child] for (parent, child) in self.dependencies if parent == task_id] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.