bartoszkobylinski opened a new issue, #3742:
URL: https://github.com/apache/iggy/issues/3742
### Description
The Python binding's `IggyClient` accepts only a connection string, so **no
client
configuration can be set from Python** — in particular neither reconnection
nor auto-login.
On `master`, `foreign/python/src/client.rs`:
```rust
#[new]
#[pyo3(signature = (conn=None))]
fn new(conn: Option<String>) -> PyResult<Self>
let client = IggyClientBuilder::new()
.with_tcp()
.with_server_address(conn.unwrap_or("127.0.0.1:8090".to_string()))
.build()
```
The generated stub confirms the surface: the only exported types are
`AutoCommit`,
`AutoCommitAfter`, `AutoCommitWhen`, `IggyClient`, `IggyConsumer`,
`PollingStrategy`,
`ReceiveMessage`, `SendMessage`, `StreamDetails`, `TopicDetails`. There is
no config or
builder type.
### Why this matters — the SDK's own session recovery becomes unreachable
from Python
`#2880` added `Unauthenticated`, `Disconnected`, `EmptyResponse` and
`StaleClient` to the
reconnect match in `send_raw_with_response`, so the client reconnects **and
replays the
stored login**. That recovery is gated on the client having `reconnection`
enabled and an
`AutoLogin` credential to replay — and `#3651` documents the other half:
> *"`login_user` / `logout_user` … never touch the state. The only writer of
the session
> values is `connect()`'s auto-login block, so a manual `connect()` +
`login_user()` flow
> stays at `Connected`"*
A Python user has **only** the manual `connect()` + `login_user()` flow
available. So the
combination is: no auto-login to replay, and a flow that does not own
session state. The
practical result is that a session lost shortly after login is not recovered
— it surfaces as
`Unauthenticated` on the *next* call, and the application must handle it by
hand.
### Observed impact
A long-running Python consumer on a restart loop, against `iggy-server`
0.8.0 over TCP
loopback. `login_user()` returned successfully; the very next call raised:
```
File ".../core/iggy_bus.py", line 229, in ensure_topology
if await self._client.get_stream(self._stream) is None:
RuntimeError: Unauthenticated
```
Ten seconds later the same startup failed differently, then succeeded on the
third attempt
and ran for ~2h48m:
```
File ".../core/iggy_bus.py", line 206, in connect
await self._client.login_user(...)
RuntimeError: Disconnected
```
Both are errors `#2880` already classifies as reconnectable — but with no
reconnection/
auto-login configurable from Python, they terminate the process instead,
leaving restart
supervision (systemd) as the only recovery.
### Workaround a Python caller has to hand-roll today
Because `login_user()` returning is not sufficient evidence of an
authenticated session, we
now re-verify it explicitly and re-login on failure — effectively
reimplementing `auto_login`
plus reconnection in Python:
```python
for attempt in range(MAX_ATTEMPTS):
try:
await client.connect()
await client.login_user(username, password)
await client.get_stream(stream) # probe: raises Unauthenticated if
the session is dead
except Exception:
await sleep_with_backoff(attempt) # then retry the whole
connect+login
else:
break
```
### Parity — other foreign SDKs already expose this
- Go: `foreign/go/client/tcp/tcp_core.go` — `autoLogin AutoLogin`
- C#: `foreign/csharp/Iggy_SDK/Configuration/AutoLoginSettings.cs`
Python is the outlier.
### Suggested direction
Everything needed already exists on the Rust side; this is about exposing it:
- `core/common/src/types/configuration/tcp_config/tcp_client_config.rs` —
`TcpClientConfig`
- `.../tcp_client_config_builder.rs` — `with_auto_sign_in(AutoLogin)`
- `.../tcp_client_reconnection_config.rs` — `TcpClientReconnectionConfig`
- `core/common/src/types/configuration/auth_config/auto_login.rs` —
`AutoLogin`
- `core/sdk/src/clients/client_builder.rs` —
`IggyClientBuilder::with_auto_sign_in`
Minimal version: optional keyword arguments on `IggyClient(...)` for
reconnection settings
and auto-login credentials, passed through to `IggyClientBuilder`. Fuller
version: expose a
config/builder object mirroring `TcpClientConfigBuilder`, which would also
give the Python
SDK somewhere to hang the QUIC/HTTP/WebSocket options from `#2835`.
Happy to open a PR if a maintainer indicates the preferred shape (kwargs vs.
exposed builder).
### Affected area / component
Python SDK (`foreign/python`)
### Related
- `#3651` — SDK client state conflates transport and session dimensions
(explains why the
manual `connect()` + `login_user()` flow does not own session state).
Related, not a
duplicate: that issue is about the state enum being unreliable; this one
is about the
configuration surface being absent in Python.
- `#2880` — added the reconnect-and-replay-login behavior that this config
would unlock.
- `#1453` — `with_auto_sign_in` for the Rust builders.
- `#2835` — Python SDK transports; a config object would be the natural home
for those too.
### Versions
Server `0.8.0` (DockerHub `apache/iggy:0.8.0`), `apache-iggy` 0.8.0 (PyPI
wheel, cp312,
manylinux), Python 3.12.13, TCP on loopback. Python constructor and builder
call quoted above
were read on `master`, so the gap is present there too.
### Scope note
This issue is deliberately limited to the **missing configuration surface in
the Python
binding**. Whether a session can still be lost immediately after a
successful `login_user()`
*even with* auto-login and reconnection enabled is a separate Rust/server
question that we
have not isolated, and it is not claimed here.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]