|
1 | 1 | from __future__ import annotations |
2 | 2 |
|
3 | 3 | import json |
| 4 | +import re |
4 | 5 | import threading |
5 | 6 | from functools import partial |
6 | 7 | from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer |
|
15 | 16 | _health_check_path = "/dbos-healthz" |
16 | 17 | _workflow_recovery_path = "/dbos-workflow-recovery" |
17 | 18 | _deactivate_path = "/deactivate" |
| 19 | +# /workflows/:workflow_id/cancel |
| 20 | +# /workflows/:workflow_id/resume |
| 21 | +# /workflows/:workflow_id/restart |
18 | 22 |
|
19 | 23 |
|
20 | 24 | class AdminServer: |
@@ -79,12 +83,51 @@ def do_POST(self) -> None: |
79 | 83 | self._end_headers() |
80 | 84 | self.wfile.write(json.dumps(workflow_ids).encode("utf-8")) |
81 | 85 | else: |
82 | | - self.send_response(404) |
83 | | - self._end_headers() |
| 86 | + |
| 87 | + restart_match = re.match( |
| 88 | + r"^/workflows/(?P<workflow_id>[^/]+)/restart$", self.path |
| 89 | + ) |
| 90 | + resume_match = re.match( |
| 91 | + r"^/workflows/(?P<workflow_id>[^/]+)/resume$", self.path |
| 92 | + ) |
| 93 | + cancel_match = re.match( |
| 94 | + r"^/workflows/(?P<workflow_id>[^/]+)/cancel$", self.path |
| 95 | + ) |
| 96 | + |
| 97 | + if restart_match: |
| 98 | + workflow_id = restart_match.group("workflow_id") |
| 99 | + self._handle_restart(workflow_id) |
| 100 | + elif resume_match: |
| 101 | + workflow_id = resume_match.group("workflow_id") |
| 102 | + self._handle_resume(workflow_id) |
| 103 | + elif cancel_match: |
| 104 | + workflow_id = cancel_match.group("workflow_id") |
| 105 | + self._handle_cancel(workflow_id) |
| 106 | + else: |
| 107 | + self.send_response(404) |
| 108 | + self._end_headers() |
84 | 109 |
|
85 | 110 | def log_message(self, format: str, *args: Any) -> None: |
86 | 111 | return # Disable admin server request logging |
87 | 112 |
|
| 113 | + def _handle_restart(self, workflow_id: str) -> None: |
| 114 | + self.dbos.restart_workflow(workflow_id) |
| 115 | + print("Restarting workflow", workflow_id) |
| 116 | + self.send_response(204) |
| 117 | + self._end_headers() |
| 118 | + |
| 119 | + def _handle_resume(self, workflow_id: str) -> None: |
| 120 | + print("Resuming workflow", workflow_id) |
| 121 | + self.dbos.resume_workflow(workflow_id) |
| 122 | + self.send_response(204) |
| 123 | + self._end_headers() |
| 124 | + |
| 125 | + def _handle_cancel(self, workflow_id: str) -> None: |
| 126 | + print("Cancelling workflow", workflow_id) |
| 127 | + self.dbos.cancel_workflow(workflow_id) |
| 128 | + self.send_response(204) |
| 129 | + self._end_headers() |
| 130 | + |
88 | 131 |
|
89 | 132 | # Be consistent with DBOS-TS response. |
90 | 133 | class PerfUtilization(TypedDict): |
|
0 commit comments