Skip to content

Commit 836aa61

Browse files
authored
add serverless docs (#329)
Co-authored-by: viseshrp <[email protected]>
1 parent e19f5f7 commit 836aa61

18 files changed

+2425
-336
lines changed

Makefile

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,10 @@ clean:
5252
test_clean:
5353
python test_cleanup.py
5454

55-
all: clean build install
55+
docs:
56+
$(MAKE) -C doc html
57+
58+
docs-clean:
59+
$(MAKE) -C doc clean
60+
61+
all: clean build install

doc/source/serverless/caveats.rst

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
Caveats
2+
=======
3+
4+
Multiprocessing / Multithreading Usage
5+
--------------------------------------
6+
7+
When using Serverless ADR in applications that involve multiple processes or threads,
8+
Serverless ADR modifies the Python process environment and dynamically loads
9+
required modules from the Ansys installation during setup. Because of this design,
10+
proper initialization and lifecycle management are critical when using Serverless ADR
11+
in applications involving multiple processes or threads.
12+
13+
Process-Level Initialization
14+
----------------------------
15+
16+
- The ``ADR.setup()`` method configures Serverless ADR for the **entire process**.
17+
- When your application uses multiprocessing (e.g., the ``multiprocessing`` module,
18+
Gunicorn workers, or other process-based concurrency), **each process must call**
19+
``ADR.setup()`` before accessing Serverless ADR features.
20+
- If ``setup()`` is not called in a new process, ADR APIs will fail or behave
21+
unpredictably due to missing environment configuration.
22+
23+
Example: Multiprocessing with Serverless ADR
24+
25+
.. code-block:: python
26+
27+
import multiprocessing
28+
from ansys.dynamicreporting.core.serverless import ADR
29+
30+
31+
def worker_task():
32+
adr = ADR.get_instance()
33+
if not adr.is_setup:
34+
adr.setup()
35+
# Proceed with Serverless ADR API calls here
36+
37+
38+
if __name__ == "__main__":
39+
adr = ADR(ansys_installation="/path/to/ansys", db_directory="/path/to/db")
40+
adr.setup()
41+
42+
# Spawn new processes
43+
processes = []
44+
for _ in range(4):
45+
p = multiprocessing.Process(target=worker_task)
46+
p.start()
47+
processes.append(p)
48+
49+
for p in processes:
50+
p.join()
51+
52+
Thread-Level Behavior
53+
---------------------
54+
55+
- Serverless ADR configuration applies process-wide and is shared by all threads.
56+
- It is unnecessary and discouraged to call ``ADR.setup()`` multiple times within the
57+
same process.
58+
- Ensure the main thread calls ``ADR.setup()`` **before spawning any threads** that
59+
will use Serverless ADR.
60+
- Calling ``setup()`` concurrently or repeatedly from multiple threads can cause
61+
race conditions or inconsistent environment state.
62+
63+
Example: Threading with Serverless ADR
64+
65+
.. code-block:: python
66+
67+
import threading
68+
from ansys.dynamicreporting.core.serverless import ADR
69+
70+
71+
def thread_task():
72+
adr = ADR.get_instance()
73+
# ADR is already setup in main thread, so just use it directly
74+
# Make ADR API calls here
75+
76+
77+
if __name__ == "__main__":
78+
adr = ADR(ansys_installation="/path/to/ansys", db_directory="/path/to/db")
79+
adr.setup() # Call once in main thread before starting other threads
80+
81+
threads = []
82+
for _ in range(4):
83+
t = threading.Thread(target=thread_task)
84+
t.start()
85+
threads.append(t)
86+
87+
for t in threads:
88+
t.join()
89+
90+
Common Pitfalls and Solutions
91+
-----------------------------
92+
93+
- **Error: "ADR has not been set up" in worker processes**
94+
95+
_Cause_: ``ADR.setup()`` was not called in the worker process.
96+
97+
_Solution_: Call ``adr.setup()`` early in each new process, as shown above.
98+
99+
- **Race conditions or inconsistent state due to multiple ``setup()`` calls**
100+
101+
_Cause_: Concurrent calls to ``setup()`` from multiple threads.
102+
103+
_Solution_: Call ``setup()`` only once in the main thread before spawning workers.
104+
105+
Summary and Best Practices
106+
--------------------------
107+
108+
- Always call ``ADR.setup()`` once at the application startup or entry point.
109+
- In multiprocessing scenarios, call ``setup()`` separately in each spawned process.
110+
- Avoid calling ``setup()`` multiple times or concurrently within the same process.
111+
- Share the ADR instance across threads within a process after setup completes.
112+
- If unsure whether setup is needed, check ``adr.is_setup`` before calling.
113+
114+
By following these guidelines, you ensure stable and consistent Serverless ADR usage
115+
in complex multi-threaded or multi-process environments.

0 commit comments

Comments
 (0)