@@ -44,7 +44,7 @@ It exposes:
4444* REST & Web-Socket endpoints (``http://localhost:8080 `` by default)
4545* Thread-safe synchronous façade for scripts / Jupyter
4646* Native async API for advanced integrations
47- * CLI utilities ``submit_local_job `` and ``submit_job_on_scheduler `` for shell / CI pipelines
47+ * CLI utilities ``submit_local_job ``, `` submit_batch_jobs ``, and ``submit_job_on_scheduler `` for shell / CI pipelines
4848
4949The **same backend code path ** is used regardless of front-end style; the difference is
5050**who owns the event loop ** and **how control is returned to the caller **.
@@ -176,6 +176,130 @@ Example—CLI (cluster)
176176 The command returns immediately after the job is **queued **; use the printed ID
177177with ``wait_until_done `` or monitor via the web UI.
178178
179+ CLI—``submit_batch_jobs ``
180+ ^^^^^^^^^^^^^^^^^^^^^^^^^^
181+ For bulk submissions, use ``submit_batch_jobs `` to automatically discover and submit
182+ multiple projects from a directory tree.
183+
184+ Synopsis
185+ """"""""
186+ .. code-block :: bash
187+
188+ $ python submit_batch_jobs.py --root-dir < DIRECTORY> [options]
189+
190+ Key features
191+ """"""""""""
192+ * **Automatic discovery **: Scans for all ``.aedb `` folders and ``.aedt `` files
193+ * **Smart pairing **: When both ``.aedb `` and ``.aedt `` exist, uses the ``.aedt `` file
194+ * **Asynchronous submission **: Submits jobs concurrently for faster processing
195+ * **Recursive scanning **: Optional recursive directory traversal
196+
197+ Options
198+ """""""
199+ .. list-table ::
200+ :widths: 30 15 55
201+ :header-rows: 1
202+
203+ * - Argument
204+ - Default
205+ - Description
206+ * - ``--root-dir ``
207+ - *(required) *
208+ - Root directory to scan for projects
209+ * - ``--host ``
210+ - ``localhost ``
211+ - Job manager host address
212+ * - ``--port ``
213+ - ``8080 ``
214+ - Job manager port
215+ * - ``--num-cores ``
216+ - ``8 ``
217+ - Number of cores to allocate per job
218+ * - ``--max-concurrent ``
219+ - ``5 ``
220+ - Maximum concurrent job submissions
221+ * - ``--delay-ms ``
222+ - ``100 ``
223+ - Delay in milliseconds between job submissions
224+ * - ``--recursive ``
225+ - ``False ``
226+ - Scan subdirectories recursively
227+ * - ``--verbose ``
228+ - ``False ``
229+ - Enable debug logging
230+
231+ Example—batch submission (local)
232+ """""""""""""""""""""""""""""""""
233+ .. code-block :: bash
234+
235+ # Submit all projects in a directory
236+ $ python submit_batch_jobs.py --root-dir " D:\Temp\test_jobs"
237+
238+ # Recursive scan with custom core count
239+ $ python submit_batch_jobs.py \
240+ --root-dir " D:\Projects\simulations" \
241+ --num-cores 16 \
242+ --recursive \
243+ --verbose
244+
245+ Example output
246+ """"""""""""""
247+ .. code-block :: text
248+
249+ 2025-11-07 10:30:15 - __main__ - INFO - Scanning D:\Temp\test_jobs for projects (recursive=False)
250+ 2025-11-07 10:30:15 - __main__ - INFO - Found AEDB folder: D:\Temp\test_jobs\project1.aedb
251+ 2025-11-07 10:30:15 - __main__ - INFO - Found AEDT file: D:\Temp\test_jobs\project2.aedt
252+ 2025-11-07 10:30:15 - __main__ - INFO - Using AEDB folder for project: D:\Temp\test_jobs\project1.aedb
253+ 2025-11-07 10:30:15 - __main__ - INFO - Using standalone AEDT file: D:\Temp\test_jobs\project2.aedt
254+ 2025-11-07 10:30:15 - __main__ - INFO - Found 2 project(s) to submit
255+ 2025-11-07 10:30:15 - __main__ - INFO - Starting batch submission of 2 project(s) to http://localhost:8080
256+ 2025-11-07 10:30:16 - __main__ - INFO - ✓ Successfully submitted: project1.aedb (status=200)
257+ 2025-11-07 10:30:16 - __main__ - INFO - ✓ Successfully submitted: project2.aedt (status=200)
258+ 2025-11-07 10:30:16 - __main__ - INFO - ============================================================
259+ 2025-11-07 10:30:16 - __main__ - INFO - Batch submission complete:
260+ 2025-11-07 10:30:16 - __main__ - INFO - Total projects: 2
261+ 2025-11-07 10:30:16 - __main__ - INFO - ✓ Successful: 2
262+ 2025-11-07 10:30:16 - __main__ - INFO - ✗ Failed: 0
263+ 2025-11-07 10:30:16 - __main__ - INFO - ============================================================
264+
265+ How it works
266+ """"""""""""
267+ 1. **Scanning phase **:
268+
269+ * Searches for all ``.aedb `` folders in the root directory
270+ * Searches for all ``.aedt `` files in the root directory
271+ * For each ``.aedb `` folder, checks if a corresponding ``.aedt `` file exists:
272+
273+ - If yes: Uses the ``.aedt `` file
274+ - If no: Uses the ``.aedb `` folder
275+
276+ * Standalone ``.aedt `` files (without corresponding ``.aedb ``) are also included
277+
278+ 2. **Submission phase **:
279+
280+ * Creates job configurations for each project
281+ * Submits jobs asynchronously to the job manager REST API
282+ * Limits concurrent submissions using a semaphore (default: 5)
283+ * Reports success/failure for each submission
284+
285+ 3. **Results **:
286+
287+ * Displays a summary with total, successful, and failed submissions
288+ * Logs detailed information about each submission
289+
290+ .. note ::
291+ The script does **not ** wait for jobs to complete, only for submission confirmation.
292+ Job execution happens asynchronously in the job manager service.
293+
294+ .. tip ::
295+ * Use ``--max-concurrent `` to limit load on the job manager service when submitting
296+ large batches.
297+ * Use ``--delay-ms `` to control the pause between submissions (default: 100ms).
298+ This ensures HTTP requests are fully sent before the next submission starts.
299+ * Set ``--delay-ms 0 `` to disable the delay if your network is very fast and reliable.
300+ * For very large batch submissions, consider increasing the timeout in the code if
301+ network latency is high.
302+
179303Programmatic—native asyncio
180304"""""""""""""""""""""""""""""
181305.. code-block :: python
0 commit comments