mirror of
https://github.com/blw1138/Zordon.git
synced 2026-06-09 13:39:24 -05:00
Jobs API cleanup
This commit is contained in:
@@ -109,9 +109,9 @@ curl -X POST http://localhost:8080/api/add_job \
|
||||
- **UI**: View job status, progress, logs, and worker availability in real-time.
|
||||
- **API Endpoints**:
|
||||
- `GET /api/jobs`: List all jobs
|
||||
- `GET /api/job/<job_id>`: Get job details
|
||||
- `POST /api/job/<job_id>/cancel`: Cancel a job
|
||||
- `POST /api/job/<job_id>/delete`: Delete a job
|
||||
- `GET /api/jobs/<job_id>`: Get job details
|
||||
- `POST /api/jobs/<job_id>/cancel`: Cancel a job
|
||||
- `POST /api/jobs/<job_id>/delete`: Delete a job
|
||||
- `GET /api/status`: Get server and queue status
|
||||
- `GET /api/engines`: List engine information
|
||||
|
||||
|
||||
+12
-12
@@ -48,7 +48,7 @@ Known callers:
|
||||
- `RenderServerProxy.get_all_jobs()`
|
||||
- `src/ui/main_window.py`
|
||||
|
||||
### `GET /api/jobs_long_poll`
|
||||
### `GET /api/jobs/long_poll`
|
||||
|
||||
Long-polls the job list until the supplied cache token changes or 30 seconds
|
||||
elapse.
|
||||
@@ -68,7 +68,7 @@ Known callers:
|
||||
|
||||
- `RenderServerProxy.get_all_jobs()` through the background cache updater.
|
||||
|
||||
### `GET /api/jobs/<status_val>`
|
||||
### `GET /api/jobs/status/<status_val>`
|
||||
|
||||
Returns jobs matching a render status.
|
||||
|
||||
@@ -86,7 +86,7 @@ Responses:
|
||||
Review note: this route is not currently wrapped by `RenderServerProxy` and no
|
||||
in-repo callers were found.
|
||||
|
||||
### `GET /api/job/<job_id>`
|
||||
### `GET /api/jobs/<job_id>`
|
||||
|
||||
Returns one job as JSON.
|
||||
|
||||
@@ -98,7 +98,7 @@ Known callers:
|
||||
- `src/distributed_job_manager.py`
|
||||
- `tests/job_creation_tests.py`
|
||||
|
||||
### `GET /api/job/<job_id>/logs`
|
||||
### `GET /api/jobs/<job_id>/logs`
|
||||
|
||||
Returns the job log file as `text/plain`.
|
||||
|
||||
@@ -106,7 +106,7 @@ Known callers:
|
||||
|
||||
- `src/ui/main_window.py` opens this URL directly.
|
||||
|
||||
### `GET /api/job/<job_id>/file_list`
|
||||
### `GET /api/jobs/<job_id>/files`
|
||||
|
||||
Returns a list of output filenames for the job.
|
||||
|
||||
@@ -115,7 +115,7 @@ Known callers:
|
||||
- `RenderServerProxy.get_job_files_list()`
|
||||
- `src/utilities/server_helper.py`
|
||||
|
||||
### `GET /api/job/<job_id>/download`
|
||||
### `GET /api/jobs/<job_id>/download`
|
||||
|
||||
Downloads one output file.
|
||||
|
||||
@@ -136,7 +136,7 @@ Known callers:
|
||||
- `RenderServerProxy.download_job_file()`
|
||||
- `src/utilities/server_helper.py`
|
||||
|
||||
### `GET /api/job/<job_id>/download_all`
|
||||
### `GET /api/jobs/<job_id>/download_all`
|
||||
|
||||
Creates a temporary zip of the job output directory and downloads it.
|
||||
|
||||
@@ -146,7 +146,7 @@ Known callers:
|
||||
- `src/ui/main_window.py`
|
||||
- `src/utilities/server_helper.py`
|
||||
|
||||
### `GET /api/job/<job_id>/thumbnail`
|
||||
### `GET /api/jobs/<job_id>/thumbnail`
|
||||
|
||||
Returns a generated preview image or video for a job.
|
||||
|
||||
@@ -207,7 +207,7 @@ Known callers:
|
||||
- `src/distributed_job_manager.py`
|
||||
- `tests/job_creation_tests.py`
|
||||
|
||||
### `POST /api/job/<job_id>/cancel`
|
||||
### `POST /api/jobs/<job_id>/cancel`
|
||||
|
||||
Cancels a job.
|
||||
|
||||
@@ -224,7 +224,7 @@ Known callers:
|
||||
- `src/ui/main_window.py`
|
||||
- `src/distributed_job_manager.py`
|
||||
|
||||
### `POST /api/job/<job_id>/delete`
|
||||
### `POST /api/jobs/<job_id>/delete`
|
||||
|
||||
Deletes a job, stops it first, deletes previews, and removes owned upload/output
|
||||
directories when safe.
|
||||
@@ -240,7 +240,7 @@ Known callers:
|
||||
- `RenderServerProxy.delete_job()`
|
||||
- `src/ui/main_window.py`
|
||||
|
||||
### `POST /api/job/<job_id>/send_subjob_update_notification`
|
||||
### `POST /api/jobs/<job_id>/subjob_update`
|
||||
|
||||
Notifies a parent job that a child/subjob changed state.
|
||||
|
||||
@@ -498,7 +498,7 @@ Likely redundant or overlapping routes:
|
||||
used internally by `/api/full_status`.
|
||||
Routes with no in-repo callers found:
|
||||
|
||||
- `GET /api/jobs/<status_val>`
|
||||
- `GET /api/jobs/status/<status_val>`
|
||||
- `GET /api/presets`
|
||||
- `GET /api/disk_benchmark`
|
||||
- `GET /api/engines/<engine_name>/args`
|
||||
|
||||
+12
-12
@@ -288,7 +288,7 @@
|
||||
</article>
|
||||
|
||||
<article class="endpoint">
|
||||
<div class="endpoint-header"><span class="method get">GET</span><span class="path">/api/jobs_long_poll</span></div>
|
||||
<div class="endpoint-header"><span class="method get">GET</span><span class="path">/api/jobs/long_poll</span></div>
|
||||
<p>Long-polls the job list until the supplied cache token changes or 30 seconds elapse.</p>
|
||||
<table>
|
||||
<tr><th>Query Parameter</th><th>Required</th><th>Description</th></tr>
|
||||
@@ -298,30 +298,30 @@
|
||||
</article>
|
||||
|
||||
<article class="endpoint">
|
||||
<div class="endpoint-header"><span class="method get">GET</span><span class="path">/api/jobs/<status_val></span></div>
|
||||
<div class="endpoint-header"><span class="method get">GET</span><span class="path">/api/jobs/status/<status_val></span></div>
|
||||
<p>Returns jobs matching a render status converted by <code>string_to_status()</code>.</p>
|
||||
<div class="note">No <code>RenderServerProxy</code> wrapper or in-repo caller was found.</div>
|
||||
</article>
|
||||
|
||||
<article class="endpoint">
|
||||
<div class="endpoint-header"><span class="method get">GET</span><span class="path">/api/job/<job_id></span></div>
|
||||
<div class="endpoint-header"><span class="method get">GET</span><span class="path">/api/jobs/<job_id></span></div>
|
||||
<p>Returns one job as JSON.</p>
|
||||
<p>Known callers include <code>RenderServerProxy.get_job_info()</code>, <code>add_job.py</code>, <code>src/ui/main_window.py</code>, <code>src/distributed_job_manager.py</code>, and <code>tests/job_creation_tests.py</code>.</p>
|
||||
</article>
|
||||
|
||||
<article class="endpoint">
|
||||
<div class="endpoint-header"><span class="method get">GET</span><span class="path">/api/job/<job_id>/logs</span></div>
|
||||
<div class="endpoint-header"><span class="method get">GET</span><span class="path">/api/jobs/<job_id>/logs</span></div>
|
||||
<p>Returns the job log file as <code>text/plain</code>. The main window opens this URL directly.</p>
|
||||
</article>
|
||||
|
||||
<article class="endpoint">
|
||||
<div class="endpoint-header"><span class="method get">GET</span><span class="path">/api/job/<job_id>/file_list</span></div>
|
||||
<div class="endpoint-header"><span class="method get">GET</span><span class="path">/api/jobs/<job_id>/files</span></div>
|
||||
<p>Returns a list of output filenames for the job.</p>
|
||||
<p>Known callers: <code>RenderServerProxy.get_job_files_list()</code> and <code>src/utilities/server_helper.py</code>.</p>
|
||||
</article>
|
||||
|
||||
<article class="endpoint">
|
||||
<div class="endpoint-header"><span class="method get">GET</span><span class="path">/api/job/<job_id>/download</span></div>
|
||||
<div class="endpoint-header"><span class="method get">GET</span><span class="path">/api/jobs/<job_id>/download</span></div>
|
||||
<p>Downloads one output file.</p>
|
||||
<table>
|
||||
<tr><th>Query Parameter</th><th>Required</th><th>Description</th></tr>
|
||||
@@ -331,13 +331,13 @@
|
||||
</article>
|
||||
|
||||
<article class="endpoint">
|
||||
<div class="endpoint-header"><span class="method get">GET</span><span class="path">/api/job/<job_id>/download_all</span></div>
|
||||
<div class="endpoint-header"><span class="method get">GET</span><span class="path">/api/jobs/<job_id>/download_all</span></div>
|
||||
<p>Creates a temporary zip of the job output directory and downloads it.</p>
|
||||
<p>Known callers: <code>RenderServerProxy.download_all_job_files()</code>, <code>src/ui/main_window.py</code>, and <code>src/utilities/server_helper.py</code>.</p>
|
||||
</article>
|
||||
|
||||
<article class="endpoint">
|
||||
<div class="endpoint-header"><span class="method get">GET</span><span class="path">/api/job/<job_id>/thumbnail</span></div>
|
||||
<div class="endpoint-header"><span class="method get">GET</span><span class="path">/api/jobs/<job_id>/thumbnail</span></div>
|
||||
<p>Returns a generated preview image or video for a job.</p>
|
||||
<table>
|
||||
<tr><th>Query Parameter</th><th>Required</th><th>Description</th></tr>
|
||||
@@ -369,7 +369,7 @@
|
||||
</article>
|
||||
|
||||
<article class="endpoint">
|
||||
<div class="endpoint-header"><span class="method post">POST</span><span class="path">/api/job/<job_id>/cancel</span></div>
|
||||
<div class="endpoint-header"><span class="method post">POST</span><span class="path">/api/jobs/<job_id>/cancel</span></div>
|
||||
<p>Cancels a job. Requires a truthy <code>confirm</code> query parameter.</p>
|
||||
<table>
|
||||
<tr><th>Query Parameter</th><th>Required</th><th>Description</th></tr>
|
||||
@@ -379,7 +379,7 @@
|
||||
</article>
|
||||
|
||||
<article class="endpoint">
|
||||
<div class="endpoint-header"><span class="method post">POST</span><span class="path">/api/job/<job_id>/delete</span></div>
|
||||
<div class="endpoint-header"><span class="method post">POST</span><span class="path">/api/jobs/<job_id>/delete</span></div>
|
||||
<p>Deletes a job, stops it first, deletes previews, and removes owned upload/output directories when safe.</p>
|
||||
<table>
|
||||
<tr><th>Query Parameter</th><th>Required</th><th>Description</th></tr>
|
||||
@@ -388,7 +388,7 @@
|
||||
</article>
|
||||
|
||||
<article class="endpoint">
|
||||
<div class="endpoint-header"><span class="method post">POST</span><span class="path">/api/job/<job_id>/send_subjob_update_notification</span></div>
|
||||
<div class="endpoint-header"><span class="method post">POST</span><span class="path">/api/jobs/<job_id>/subjob_update</span></div>
|
||||
<p>Notifies a parent job that a child/subjob changed state. The request body is the JSON representation of the subjob.</p>
|
||||
</article>
|
||||
</section>
|
||||
@@ -571,7 +571,7 @@
|
||||
<div class="panel" style="margin-top: 14px;">
|
||||
<h3>Routes With No In-Repo Callers Found</h3>
|
||||
<ul>
|
||||
<li><code>GET /api/jobs/<status_val></code></li>
|
||||
<li><code>GET /api/jobs/status/<status_val></code></li>
|
||||
<li><code>GET /api/presets</code></li>
|
||||
<li><code>GET /api/disk_benchmark</code></li>
|
||||
<li><code>GET /api/engines/<engine_name>/args</code></li>
|
||||
|
||||
+13
-13
@@ -84,7 +84,7 @@ def jobs_json() -> Dict[str, Any]:
|
||||
return {'jobs': all_jobs, 'token': job_cache_token}
|
||||
|
||||
|
||||
@server.get('/api/jobs_long_poll')
|
||||
@server.get('/api/jobs/long_poll')
|
||||
def long_polling_jobs():
|
||||
hash_token = request.args.get('token', None)
|
||||
start_time = time.time()
|
||||
@@ -98,7 +98,7 @@ def long_polling_jobs():
|
||||
time.sleep(1)
|
||||
|
||||
|
||||
@server.get('/api/jobs/<status_val>')
|
||||
@server.get('/api/jobs/status/<status_val>')
|
||||
def filtered_jobs_json(status_val):
|
||||
state = string_to_status(status_val)
|
||||
jobs = [x.json() for x in RenderQueue.jobs_with_status(state)]
|
||||
@@ -112,7 +112,7 @@ def filtered_jobs_json(status_val):
|
||||
# Job Details / File Handling
|
||||
# --------------------------------------------
|
||||
|
||||
@server.get('/api/job/<job_id>')
|
||||
@server.get('/api/jobs/<job_id>')
|
||||
def get_job_details(job_id):
|
||||
"""Retrieves the details of a requested job in JSON format
|
||||
|
||||
@@ -125,7 +125,7 @@ def get_job_details(job_id):
|
||||
return RenderQueue.job_with_id(job_id).json()
|
||||
|
||||
|
||||
@server.get('/api/job/<job_id>/logs')
|
||||
@server.get('/api/jobs/<job_id>/logs')
|
||||
def get_job_logs(job_id):
|
||||
"""Retrieves the log file for a specific render job.
|
||||
|
||||
@@ -144,12 +144,12 @@ def get_job_logs(job_id):
|
||||
return Response(log_data, mimetype='text/plain')
|
||||
|
||||
|
||||
@server.get('/api/job/<job_id>/file_list')
|
||||
def get_file_list(job_id):
|
||||
return [Path(p).name for p in RenderQueue.job_with_id(job_id).file_list()]
|
||||
@server.get('/api/jobs/<job_id>/files')
|
||||
def get_job_files(job_id):
|
||||
return [Path(p).name for p in RenderQueue.job_with_id(job_id).file_list()]
|
||||
|
||||
|
||||
@server.route('/api/job/<job_id>/download')
|
||||
@server.route('/api/jobs/<job_id>/download')
|
||||
def download_requested_file(job_id):
|
||||
requested_filename = request.args.get("filename")
|
||||
if not requested_filename:
|
||||
@@ -165,7 +165,7 @@ def download_requested_file(job_id):
|
||||
return f"File '{requested_filename}' not found", 404
|
||||
|
||||
|
||||
@server.route('/api/job/<job_id>/download_all')
|
||||
@server.route('/api/jobs/<job_id>/download_all')
|
||||
def download_all_files(job_id):
|
||||
zip_filename = None
|
||||
|
||||
@@ -307,7 +307,7 @@ def add_job_handler():
|
||||
return 'unknown error', 500
|
||||
|
||||
|
||||
@server.post('/api/job/<job_id>/cancel')
|
||||
@server.post('/api/jobs/<job_id>/cancel')
|
||||
def cancel_job(job_id):
|
||||
if not request.args.get('confirm', False):
|
||||
return 'Confirmation required to cancel job', 400
|
||||
@@ -321,7 +321,7 @@ def cancel_job(job_id):
|
||||
return "Unknown error", 500
|
||||
|
||||
|
||||
@server.post('/api/job/<job_id>/delete')
|
||||
@server.post('/api/jobs/<job_id>/delete')
|
||||
def delete_job(job_id):
|
||||
try:
|
||||
if not request.args.get("confirm", False):
|
||||
@@ -543,14 +543,14 @@ def delete_engine_download():
|
||||
def heartbeat():
|
||||
return datetime.now().isoformat(), 200
|
||||
|
||||
@server.post('/api/job/<job_id>/send_subjob_update_notification')
|
||||
@server.post('/api/jobs/<job_id>/subjob_update')
|
||||
def subjob_update_notification(job_id):
|
||||
subjob_details = request.json
|
||||
DistributedJobManager.handle_subjob_update_notification(RenderQueue.job_with_id(job_id), subjob_data=subjob_details)
|
||||
return Response(status=200)
|
||||
|
||||
|
||||
@server.route('/api/job/<job_id>/thumbnail')
|
||||
@server.route('/api/jobs/<job_id>/thumbnail')
|
||||
def job_thumbnail(job_id):
|
||||
|
||||
try:
|
||||
|
||||
@@ -139,7 +139,7 @@ class RenderServerProxy:
|
||||
if self.__offline_flags: # if we're offline, don't bother with the long poll
|
||||
ignore_token = True
|
||||
|
||||
url = f'jobs_long_poll?token={self.__jobs_cache_token}' if (self.__jobs_cache_token and
|
||||
url = f'jobs/long_poll?token={self.__jobs_cache_token}' if (self.__jobs_cache_token and
|
||||
not ignore_token) else 'jobs'
|
||||
status_result = self.request_data(url, timeout=timeout)
|
||||
if status_result is not None:
|
||||
@@ -181,10 +181,10 @@ class RenderServerProxy:
|
||||
# --------------------------------------------
|
||||
|
||||
def get_job_info(self, job_id, timeout=5):
|
||||
return self.request_data(f'job/{job_id}', timeout=timeout)
|
||||
return self.request_data(f'jobs/{job_id}', timeout=timeout)
|
||||
|
||||
def get_job_files_list(self, job_id):
|
||||
return self.request_data(f"job/{job_id}/file_list")
|
||||
return self.request_data(f'jobs/{job_id}/files')
|
||||
|
||||
# --------------------------------------------
|
||||
# Job Lifecycle:
|
||||
@@ -230,10 +230,10 @@ class RenderServerProxy:
|
||||
return response
|
||||
|
||||
def cancel_job(self, job_id, confirm=False):
|
||||
return self._post(f'job/{job_id}/cancel', params={'confirm': confirm})
|
||||
return self._post(f'jobs/{job_id}/cancel', params={'confirm': confirm})
|
||||
|
||||
def delete_job(self, job_id, confirm=False):
|
||||
return self._post(f'job/{job_id}/delete', params={'confirm': confirm})
|
||||
return self._post(f'jobs/{job_id}/delete', params={'confirm': confirm})
|
||||
|
||||
def send_subjob_update_notification(self, parent_id, subjob):
|
||||
"""
|
||||
@@ -246,7 +246,7 @@ class RenderServerProxy:
|
||||
Returns:
|
||||
Response: The response from the server.
|
||||
"""
|
||||
return requests.post(f'http://{self.hostname}:{self.port}/api/job/{parent_id}/send_subjob_update_notification',
|
||||
return requests.post(f'http://{self.hostname}:{self.port}/api/jobs/{parent_id}/subjob_update',
|
||||
json=subjob.json())
|
||||
|
||||
# --------------------------------------------
|
||||
@@ -312,11 +312,11 @@ class RenderServerProxy:
|
||||
# --------------------------------------------
|
||||
|
||||
def download_all_job_files(self, job_id, save_path):
|
||||
url = f"http://{self.hostname}:{self.port}/api/job/{job_id}/download_all"
|
||||
url = f'http://{self.hostname}:{self.port}/api/jobs/{job_id}/download_all'
|
||||
return self.__download_file_from_url(url, output_filepath=save_path)
|
||||
|
||||
def download_job_file(self, job_id, job_filename, save_path):
|
||||
url = f"http://{self.hostname}:{self.port}/api/job/{job_id}/download?filename={job_filename}"
|
||||
url = f'http://{self.hostname}:{self.port}/api/jobs/{job_id}/download?filename={job_filename}'
|
||||
return self.__download_file_from_url(url, output_filepath=save_path)
|
||||
|
||||
@staticmethod
|
||||
|
||||
@@ -334,7 +334,7 @@ class MainWindow(QMainWindow):
|
||||
default_image_path = "error.png"
|
||||
before_fetch_hostname = self.current_server_proxy.hostname
|
||||
|
||||
response = self.current_server_proxy.request(f'job/{job_id}/thumbnail?size=big')
|
||||
response = self.current_server_proxy.request(f'jobs/{job_id}/thumbnail?size=big')
|
||||
if response.ok:
|
||||
try:
|
||||
with io.BytesIO(response.content) as image_data_stream:
|
||||
@@ -547,7 +547,8 @@ class MainWindow(QMainWindow):
|
||||
"""
|
||||
selected_job_ids = self.selected_job_ids()
|
||||
if selected_job_ids:
|
||||
url = f'http://{self.current_server_proxy.hostname}:{self.current_server_proxy.port}/api/job/{selected_job_ids[0]}/logs'
|
||||
url = (f'http://{self.current_server_proxy.hostname}:{self.current_server_proxy.port}'
|
||||
f'/api/jobs/{selected_job_ids[0]}/logs')
|
||||
self.log_viewer_window = LogViewer(url)
|
||||
self.log_viewer_window.show()
|
||||
|
||||
@@ -616,8 +617,8 @@ class MainWindow(QMainWindow):
|
||||
return
|
||||
|
||||
import webbrowser
|
||||
download_url = (f"http://{self.current_server_proxy.hostname}:{self.current_server_proxy.port}"
|
||||
f"/api/job/{job_ids[0]}/download_all")
|
||||
download_url = (f'http://{self.current_server_proxy.hostname}:{self.current_server_proxy.port}'
|
||||
f'/api/jobs/{job_ids[0]}/download_all')
|
||||
webbrowser.open(download_url)
|
||||
|
||||
def open_files(self, event):
|
||||
|
||||
Reference in New Issue
Block a user