-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathmain.py
More file actions
196 lines (144 loc) · 6.12 KB
/
main.py
File metadata and controls
196 lines (144 loc) · 6.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
"""
Hello World - Getting Started with Render Workflows
This is the simplest possible workflow example to help you understand the basics.
It demonstrates:
- How to define a task using the @app.task decorator
- How to call a task as a subtask using await
- How to orchestrate multiple subtask calls
No complex business logic - just simple number operations to show the patterns clearly.
"""
import logging
from render_sdk import Workflows
# Configure logging to see what's happening
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
# Initialize Workflows app
app = Workflows()
# ============================================================================
# BASIC TASK - The building block
# ============================================================================
@app.task
def double(x: int) -> int:
"""
A basic task that doubles a number.
This is the simplest possible task - it takes an input, does something,
and returns a result. Tasks are the building blocks of workflows.
Args:
x: The number to double
Returns:
The doubled number
"""
logger.info(f"[TASK] Doubling {x}")
result = x * 2
logger.info(f"[TASK] Result: {result}")
return result
# ============================================================================
# SUBTASK CALLING - Tasks calling other tasks
# ============================================================================
@app.task
async def add_doubled_numbers(*args: int) -> dict:
"""
Demonstrates calling a task as a subtask.
This task calls the 'double' task twice as a subtask using await.
This is the fundamental pattern in Render Workflows - tasks can call
other tasks to break down complex operations into simple, reusable pieces.
KEY PATTERN: Use 'await task_name(args)' to call a task as a subtask.
Args:
*args: Two numbers to process
Returns:
Dictionary with original numbers, doubled values, and their sum
"""
if len(args) != 2:
raise ValueError(f"Expected exactly 2 arguments, got {len(args)}")
a, b = args
logger.info(f"[WORKFLOW] Starting: add_doubled_numbers({a}, {b})")
# SUBTASK CALL #1: Call 'double' as a subtask
# The 'await' keyword tells Render to execute this as a subtask
logger.info(f"[WORKFLOW] Calling subtask: double({a})")
doubled_a = await double(a)
# SUBTASK CALL #2: Call 'double' as a subtask again
logger.info(f"[WORKFLOW] Calling subtask: double({b})")
doubled_b = await double(b)
# Now we have the results from both subtasks, let's combine them
total = doubled_a + doubled_b
result = {
"original_numbers": [a, b],
"doubled_numbers": [doubled_a, doubled_b],
"sum_of_doubled": total,
"explanation": f"{a} doubled is {doubled_a}, {b} doubled is {doubled_b}, sum is {total}"
}
logger.info(f"[WORKFLOW] Complete: {result}")
return result
# ============================================================================
# SUBTASK IN A LOOP - Processing multiple items
# ============================================================================
@app.task
async def process_numbers(*numbers: int) -> dict:
"""
Demonstrates calling a subtask in a loop.
This pattern is useful when you need to process multiple items,
and each item requires the same operation (calling the same subtask).
KEY PATTERN: Call subtasks in a loop to process lists/batches.
Args:
numbers: List of numbers to process
Returns:
Dictionary with original numbers and their doubled values
"""
numbers_list = list(numbers)
logger.info(f"[WORKFLOW] Starting: process_numbers({numbers_list})")
doubled_results = []
# Process each number by calling 'double' as a subtask
for i, num in enumerate(numbers_list, 1):
logger.info(f"[WORKFLOW] Processing item {i}/{len(numbers_list)}: {num}")
# SUBTASK CALL: Call 'double' as a subtask for each number
doubled = await double(num)
doubled_results.append(doubled)
result = {
"original_numbers": numbers_list,
"doubled_numbers": doubled_results,
"count": len(numbers_list),
"explanation": f"Processed {len(numbers_list)} numbers through the double subtask"
}
logger.info(f"[WORKFLOW] Complete: {result}")
return result
# ============================================================================
# MULTI-STEP WORKFLOW - Chaining multiple subtasks
# ============================================================================
@app.task
async def calculate_and_process(a: int, b: int, *more_numbers: int) -> dict:
"""
Demonstrates a multi-step workflow that chains multiple subtasks.
This is a more complex example showing how you can build workflows
that call multiple different subtasks in sequence, using the results
from one subtask as input to the next.
KEY PATTERN: Chain multiple subtask calls to create complex workflows.
Args:
a: First number
b: Second number
more_numbers: Additional numbers to process
Returns:
Dictionary with results from multiple workflow steps
"""
more_numbers_list = list(more_numbers)
logger.info("[WORKFLOW] Starting multi-step workflow")
# STEP 1: Add two doubled numbers
logger.info("[WORKFLOW] Step 1: Adding doubled numbers")
step1_result = await add_doubled_numbers(a, b)
# STEP 2: Process a list of numbers
logger.info("[WORKFLOW] Step 2: Processing number list")
step2_result = await process_numbers(*more_numbers_list)
# STEP 3: Combine the results
logger.info("[WORKFLOW] Step 3: Combining results")
final_result = {
"step1_sum": step1_result["sum_of_doubled"],
"step2_doubled": step2_result["doubled_numbers"],
"total_operations": 2 + len(more_numbers_list),
"summary": f"Added doubled {a} and {b}, then doubled {len(more_numbers_list)} more numbers"
}
logger.info("[WORKFLOW] Multi-step workflow complete")
return final_result
if __name__ == "__main__":
app.start()