Skip to content

Commit f959d64

Browse files
committed
Add simulators
1 parent d0a7e06 commit f959d64

File tree

9 files changed

+667
-11
lines changed

9 files changed

+667
-11
lines changed

docs/features/heartbeats.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,8 @@ class MyActivity extends Activity
2424
}
2525
```
2626

27+
import HeartbeatSimulator from '@site/src/components/HeartbeatSimulator';
28+
29+
<HeartbeatSimulator />
30+
2731
In the above example, even though the activity would normally be terminated after running for 5 seconds, the periodic heartbeat allows it to keep running. If the activity does freeze or crash then the heartbeat will stop and the timeout will be triggered.

src/components/ConcurrencySimulator/index.js

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ export default function WorkflowSimulator({
4242
}) {
4343
const [isExpanded, setIsExpanded] = useState(false);
4444
const [isRunning, setIsRunning] = useState(false);
45+
const [allCompleted, setAllCompleted] = useState(false);
4546
const [activityStates, setActivityStates] = useState(
4647
activities.map(() => ({ status: ActivityStatus.PENDING, progress: 0 }))
4748
);
@@ -97,6 +98,7 @@ export default function WorkflowSimulator({
9798
animationRef.current = requestAnimationFrame(animate);
9899
} else {
99100
setIsRunning(false);
101+
setAllCompleted(true);
100102
}
101103
};
102104

@@ -110,23 +112,24 @@ export default function WorkflowSimulator({
110112

111113
const animate = (timestamp) => {
112114
const elapsed = timestamp - startTimeRef.current;
113-
let allCompleted = true;
115+
let allDone = true;
114116

115117
setActivityStates(prev => {
116118
return activities.map((activity, index) => {
117119
const progress = Math.min((elapsed / activity.duration) * 100, 100);
118-
if (progress < 100) allCompleted = false;
120+
if (progress < 100) allDone = false;
119121
return {
120122
status: progress >= 100 ? ActivityStatus.COMPLETED : ActivityStatus.RUNNING,
121123
progress: progress,
122124
};
123125
});
124126
});
125127

126-
if (!allCompleted) {
128+
if (!allDone) {
127129
animationRef.current = requestAnimationFrame(animate);
128130
} else {
129131
setIsRunning(false);
132+
setAllCompleted(true);
130133
}
131134
};
132135

@@ -263,6 +266,7 @@ export default function WorkflowSimulator({
263266
// Final update to mark everything complete
264267
setActivityStates(prev => prev.map(() => ({ status: ActivityStatus.COMPLETED, progress: 100 })));
265268
setIsRunning(false);
269+
setAllCompleted(true);
266270
}
267271
};
268272

@@ -336,8 +340,13 @@ export default function WorkflowSimulator({
336340
))}
337341
</div>
338342

339-
<div className={styles.modeIndicator}>
340-
Mode: <strong>{mode === 'series' ? 'Series (Sequential)' : mode === 'mix' ? 'Mix (Series + Parallel)' : 'Parallel (Concurrent)'}</strong>
343+
<div className={styles.statusBar}>
344+
<span className={`${styles.statusIndicator} ${isRunning ? styles.running : allCompleted ? styles.completed : styles.idle}`}>
345+
{isRunning ? '▶️ Running' : allCompleted ? '✅ Completed' : '⏸️ Ready'}
346+
</span>
347+
<span className={styles.modeIndicator}>
348+
Mode: <strong>{mode === 'series' ? 'Series' : mode === 'mix' ? 'Mix' : 'Parallel'}</strong>
349+
</span>
341350
</div>
342351
</div>
343352
)}

src/components/ConcurrencySimulator/styles.module.css

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -205,11 +205,50 @@
205205
min-height: 1em;
206206
}
207207

208-
.modeIndicator {
208+
/* Status bar */
209+
.statusBar {
210+
display: flex;
211+
justify-content: space-between;
212+
align-items: center;
209213
margin-top: 1rem;
210214
padding-top: 0.75rem;
211215
border-top: 1px solid var(--ifm-color-emphasis-200);
212-
font-size: 0.8rem;
216+
}
217+
218+
.statusIndicator {
219+
font-size: 0.85rem;
220+
font-weight: 500;
221+
padding: 0.25rem 0.75rem;
222+
border-radius: 4px;
223+
}
224+
225+
.statusIndicator.idle {
226+
background: var(--ifm-color-emphasis-200);
227+
color: var(--ifm-color-emphasis-700);
228+
}
229+
230+
.statusIndicator.running {
231+
background: #fef3c7;
232+
color: #92400e;
233+
}
234+
235+
.statusIndicator.completed {
236+
background: #dcfce7;
237+
color: #166534;
238+
}
239+
240+
[data-theme='dark'] .statusIndicator.running {
241+
background: #78350f;
242+
color: #fef3c7;
243+
}
244+
245+
[data-theme='dark'] .statusIndicator.completed {
246+
background: #14532d;
247+
color: #dcfce7;
248+
}
249+
250+
.modeIndicator {
251+
font-size: 0.85rem;
213252
color: var(--ifm-color-emphasis-600);
214253
}
215254

0 commit comments

Comments
 (0)