@@ -6,7 +6,7 @@ DataJoint uses global state (`dj.config`, `dj.conn()`) that is not thread-safe.
66
77## Solution
88
9- Add ` thread_safe ` mode that blocks global state access and requires explicit connection configuration .
9+ Add ` thread_safe ` mode that makes global config read-only and requires explicit connections with mutable connection-scoped settings .
1010
1111## API
1212
@@ -25,7 +25,7 @@ export DJ_THREAD_SAFE=true
2525
2626### Connection.from_config()
2727
28- Creates a connection with explicit configuration. Works in both ` thread_safe=True ` and ` thread_safe=False ` modes.
28+ Creates a connection with explicit configuration. Works in both modes.
2929
3030``` python
3131conn = dj.Connection.from_config(
@@ -43,61 +43,54 @@ schema = dj.Schema("my_schema", connection=conn)
4343- ` user ` (required): Database username
4444- ` password ` (required): Database password
4545- ` port ` : Database port (default: 3306)
46- - Any other setting from ` dj.config ` (e.g., ` safemode ` , ` display_limit ` , ` stores ` )
46+ - Any other setting (e.g., ` safemode ` , ` display_limit ` , ` stores ` )
4747
48- ** Config creation:** Uses the same ` Config ` class as global ` dj.config ` . Each connection gets its own ` Config ` instance via ` conn.config ` .
49-
50- ** Read-only after connection:** Database connection settings become read-only after connection is established:
51- - ` host ` , ` port ` , ` user ` , ` password ` , ` use_tls ` , ` backend `
52-
53- ** Mutable settings:** All other settings remain mutable per-connection:
54- - ` safemode ` , ` display_limit ` , ` stores ` , etc.
48+ ** Config creation:** Copies global ` dj.config ` , then applies kwargs. Creates ` conn.config ` which is always mutable.
5549
5650``` python
5751conn = dj.Connection.from_config(host = " localhost" , user = " u" , password = " p" )
58- conn.config.safemode # True (default)
59- conn.config.display_limit # 12 (default)
60-
61- conn.config.safemode = False # OK: modify for this connection
62- conn.config.host = " other" # Error: read-only after connection
52+ conn.config.safemode = False # Always OK: conn.config is mutable
53+ conn.config.display_limit = 25 # Always OK
6354```
6455
6556## Behavior
6657
6758| Operation | ` thread_safe=False ` | ` thread_safe=True ` |
6859| -----------| --------------------| --------------------|
69- | ` dj.config.X ` | Works | Raises ` ThreadSafetyError ` |
60+ | ` dj.config ` read | Works | Works (read-only) |
61+ | ` dj.config ` write | Works | Raises ` ThreadSafetyError ` |
7062| ` dj.conn() ` | Works | Raises ` ThreadSafetyError ` |
7163| ` dj.Schema("name") ` | Works | Raises ` ThreadSafetyError ` |
7264| ` Connection.from_config() ` | Works | Works |
65+ | ` conn.config ` read/write | Works | Works |
7366| ` Schema(..., connection=conn) ` | Works | Works |
7467
7568## Read-Only Settings
7669
77- - ` thread_safe ` : Read -only after global config initialization (set via env var or config file only)
78- - ` host ` , ` port ` , ` user ` , ` password ` , ` use_tls ` , ` backend ` : Read-only on ` conn.config ` after connection is established
70+ - ` thread_safe ` : Always read -only after initialization (set via env var or config file only)
71+ - All of ` dj.config ` : Read-only when ` thread_safe=True `
7972
8073## Implementation
8174
82751 . Add ` thread_safe: bool = False ` field to ` Config ` with ` DJ_THREAD_SAFE ` env alias
83- 2 . Make ` thread_safe ` read-only after ` Config ` initialization
84- 3 . Add guards to ` Config.__getattr__ ` , ` Config.__setattr__ ` , ` Config.__getitem__ ` , ` Config.__setitem__ `
76+ 2 . Make ` thread_safe ` always read-only after initialization
77+ 3 . When ` thread_safe=True ` , make all ` dj.config ` writes raise ` ThreadSafetyError `
85784 . Add guard to ` dj.conn() `
86795 . Add guard to ` Schema.__init__ ` when ` connection=None `
87806 . Add ` Connection.from_config() ` class method that:
88- - Accepts all connection params and settings as kwargs
89- - Creates a new ` Config ` instance for ` conn.config `
90- - Marks connection settings as read-only after connection
81+ - Copies global ` dj.config `
82+ - Applies kwargs overrides
83+ - Creates mutable ` conn.config `
91847 . Add ` ThreadSafetyError ` exception
9285
9386## Exceptions
9487
9588``` python
9689class ThreadSafetyError (DataJointError ):
97- """ Raised when accessing global state in thread-safe mode."""
90+ """ Raised when modifying global state in thread-safe mode."""
9891```
9992
10093Error messages:
101- - Config access : ` "Global config is inaccessible in thread-safe mode. Use Connection.from_config() with explicit configuration ." `
102- - ` dj.conn() ` : ` "dj.conn() is disabled in thread-safe mode. Use Connection.from_config() with explicit configuration ." `
103- - Schema without connection: ` "Schema requires explicit connection in thread-safe mode. Use Schema(..., connection=conn). " `
94+ - Config write : ` "Global config is read-only in thread-safe mode. Use conn.config for connection-scoped settings ." `
95+ - ` dj.conn() ` : ` "dj.conn() is disabled in thread-safe mode. Use Connection.from_config()." `
96+ - Schema without connection: ` "Schema requires explicit connection in thread-safe mode." `
0 commit comments