You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
# Authenticate (triggers Push-TAN on your smartphone)
305
-
print("Authenticating... Please approve Push-TAN on your device")
306
+
print("Authenticating...")
306
307
await client.authenticate()
307
308
print("✓ Authenticated!")
308
309
@@ -1004,6 +1005,164 @@ Tokens expire every ~10 minutes (599s). The client automatically refreshes 120 s
1004
1005
1005
1006
---
1006
1007
1008
+
## Persistent Client Usage
1009
+
1010
+
**The ComdirectClient should be kept alive (persistent) throughout your application's lifecycle for best functionality.**
1011
+
1012
+
### Why Keep the Client Alive?
1013
+
1014
+
The client has a **background token refresh task** that automatically refreshes tokens 120 seconds before they expire. This task runs as an asyncio background coroutine andis critical for maintaining uninterrupted access to the Comdirect API.
1015
+
1016
+
**If the client instance is destroyed:**
1017
+
1018
+
- The background refresh task is cancelled
1019
+
- Tokens will expire after ~10 minutes (599 seconds)
1020
+
- A new TAN approval will be required for your next session
1021
+
- This defeats the purpose of automatic token refresh
1022
+
1023
+
### Best Practice: Create Once, Reuse Everywhere
1024
+
1025
+
```python
1026
+
import asyncio
1027
+
from comdirect_client.client import ComdirectClient
1028
+
1029
+
# Global client instance - created once at application startup
1030
+
client: ComdirectClient |None=None
1031
+
1032
+
asyncdef init_client():
1033
+
"""Initialize the client once at startup."""
1034
+
global client
1035
+
client= ComdirectClient(
1036
+
client_id="your_client_id",
1037
+
client_secret="your_client_secret",
1038
+
username="your_username",
1039
+
password="your_password",
1040
+
token_storage_path="/path/to/tokens.json", # Persist across restarts
1041
+
)
1042
+
1043
+
# Authenticate once - requires TAN approval
1044
+
await client.authenticate()
1045
+
print("Client authenticated and ready!")
1046
+
1047
+
# The background refresh task is now running automatically
1048
+
# Tokens will be refreshed 120s before expiry
1049
+
1050
+
asyncdef get_balances():
1051
+
"""Use the persistent client for API calls."""
1052
+
ifnot client:
1053
+
raiseRuntimeError("Client not initialized")
1054
+
returnawait client.get_account_balances()
1055
+
1056
+
asyncdef get_transactions(account_id: str):
1057
+
"""Another API call using the same client instance."""
1058
+
ifnot client:
1059
+
raiseRuntimeError("Client not initialized")
1060
+
returnawait client.get_transactions(account_id)
1061
+
1062
+
asyncdef shutdown():
1063
+
"""Clean up when application shuts down."""
1064
+
if client:
1065
+
await client.close()
1066
+
```
1067
+
1068
+
### What Happens with Token Storage?
1069
+
1070
+
When you configure `token_storage_path`:
1071
+
1072
+
1. **First run**: Authenticate withTAN, tokens are saved to disk
1073
+
2. **Subsequent runs**: Tokens are loaded from disk on client creation
1074
+
3. **Background refresh starts automatically** when valid tokens are loaded
1075
+
4. **No new TAN approval needed**aslongas tokens haven't expired
1076
+
1077
+
```python
1078
+
# Application startup
1079
+
client= ComdirectClient(
1080
+
...,
1081
+
token_storage_path="/path/to/tokens.json",
1082
+
)
1083
+
1084
+
# If valid tokens exist in storage:
1085
+
# - Tokens are automatically loaded
1086
+
# - Refresh task starts immediately
1087
+
# - No authenticate() call needed!
1088
+
1089
+
if client.is_authenticated():
1090
+
print("Tokens restored from storage - ready to use!")
1091
+
balances=await client.get_account_balances()
1092
+
else:
1093
+
print("No valid tokens - TAN approval required")
1094
+
await client.authenticate()
1095
+
```
1096
+
1097
+
### Anti-Pattern: Creating New Client Per Request
1098
+
1099
+
**Do NOT do this**- it defeats the purpose of automatic token refresh:
1100
+
1101
+
```python
1102
+
# BAD: Client is destroyed after each request
1103
+
asyncdef get_balance_bad():
1104
+
asyncwith ComdirectClient(...) as client:
1105
+
await client.authenticate() # TAN approval needed
1106
+
returnawait client.get_account_balances()
1107
+
# Client destroyed here! Refresh task cancelled!
1108
+
1109
+
# After ~10 minutes, calling get_balance_bad() again requires new TAN approval
1110
+
```
1111
+
1112
+
### Framework Integration Examples
1113
+
1114
+
**FastAPI / Starlette:**
1115
+
1116
+
```python
1117
+
from fastapi import FastAPI
1118
+
from contextlib import asynccontextmanager
1119
+
from comdirect_client.client import ComdirectClient
0 commit comments