# Changes
## 0.9.1
* Fix the persisted port being set to the *host* after any successful connection, which permanently broke reconnection for that install.
* `RwServerSender::add` derived the port with `server_ip.split(':').nth(1)`. Since `server_ip` is a full WebSocket URL (`ws://10.0.0.5:16250`) — the form `ScanManager` produces and callers store — the scheme's own colon matched first, so index 1 was `"//10.0.0.5"`, not `16250`.
* That value was then persisted alongside the IP, and `clear_server_ip` (whose whole purpose is to keep the port while blanking the IP) faithfully preserved it on every disconnect. From then on the stored connect info read `("", "//10.0.0.5")`, and each reconnect handed that garbage to `ScanManager::new` and the port-reserve path. Observed in the field as a client that connects once, drops, and then retries forever without ever reconnecting.
* The port is now taken from the last colon-separated segment and only accepted if it is a run of ASCII digits, so an address without a port stores `""` rather than the host. IPv6 literals (`ws://[::1]:16250`) and a trailing `/` are handled.
* `clear_server_ip` additionally drops a non-numeric port instead of preserving it, so records already written by an older build heal on the next disconnect rather than staying poisoned.
* Added `test_parse_port` and `test_clear_server_ip_drops_non_numeric_port`.
## 0.9.0
* **Breaking:** Decouple the client-side connection APIs from the host app's `db` handle.
* Added `connection_store::ConnectionStore` — a small trait covering exactly the state the library manages internally (client ID, last-known server connect info), plus `NativeDbConnectionStore`, a bundled implementation that is a behavior-preserving wrapper around the existing `Settings`-table logic (same keys, same serialization, same `spawn_blocking` handling of the redb fsync).
* `ServerSender::new`, `AtomicWebsocket::get_internal_client*`/`get_outer_client*`, `AtomicClient::internal_initialize`/`outer_initialize`/`regist_id`/`scan_and_connect`/`get_outer_connect`/`get_internal_connect`, and the free functions `get_outer_connect`/`get_internal_connect` now take `connection_store: Arc<dyn ConnectionStore>` instead of `db: DB`. Migration is a one-line wrap at each call site: `Arc::new(NativeDbConnectionStore::new(db.clone()))` built once, in place of `db.clone()`.
* Unaffected: `DB`, `Settings`, `save_key`, and the generic `get_setting_by_key`/`set_setting`/`remove_setting`/`get_id` helpers are unchanged — apps using them directly for their own settings, or reading/writing the `Settings` table directly for `atomic_websocket`'s own keys, need no changes. The server side (`AtomicServer`/`ClientSenders`) was already decoupled from `db` in 0.7.0 and is unaffected.
## 0.8.4
* Fix a race that allowed two reconnect attempts to both dial the server concurrently, leading to reconnect instability under flaky/loaded connections.
* `is_try_connect` was only set to `true` inside `handle_websocket`, i.e. *after* the handshake (`connect_async`) already succeeded. Between "a reconnect is decided" and "handshake succeeds" there was an unguarded window (bounded by `connect_timeout_seconds`, longer under real network stress) during which independent reconnect triggers — the periodic ping-loop checker, an app-level `get_internal_connect`/`get_outer_connect` call, or `ServerSender::send`'s exhausted-retry reconnect — could each start their own connection attempt. If two landed, `ServerSender::add()` drops the *previous* sender before installing the new one, so an earlier, healthy connection could get killed out from under itself the moment a duplicate arrived.
* `is_try_connect` is now claimed atomically via a `TryConnectGuard` right before the handshake starts (`get_internal_websocket`/`get_outer_websocket`, and the scan-found handoff paths), not after it succeeds. A concurrent trigger during the same window now correctly no-ops instead of also dialing. The guard resets itself on drop, so a failed/timed-out handshake can no longer leave `is_try_connect` stuck `true` either (previously only the success path reset it).
* Added a regression test (`test_concurrent_connect_triggers_dial_only_once`) that races two concurrent reconnect triggers and asserts only one connection reaches the server; reliably reproduces the duplicate-dial bug against the pre-fix code.
## 0.8.3
* Fix unbounded socket accumulation in the scan-discovery path (could exhaust the machine's ephemeral ports).
* Single-flight the scan via a new `is_scanning` guard. Previously `is_try_connect` only became true once a connection was established, so while `ScanManager` was still searching (forever, when no server exists) every repeated `get_internal_connect` / `scan_and_connect` call started another concurrent scan — each holding a subnet's worth of in-flight sockets.
* Bound the discovery scan with `run_with_timeout(scan_timeout_seconds)` instead of the unbounded `run()`; on timeout the client reports `Disconnected` so the caller's retry loop stays in charge.
* Added a single-flight regression test.
## 0.8.2
* Expose `scan_manager` (`ScanManager`) publicly again. 0.8.1 made `helpers` private, which removed `atomic_websocket::scan_manager::ScanManager` from the public API; Android clients pre-scan the LAN for the POS with it before the first connect. Additive re-export, no behavior change.
## 0.8.1
* Improve low-spec stability and make server discovery explicit for fixed-IP deployments.
* Run every native-db (redb) transaction on a blocking thread via `spawn_blocking`, so the synchronous `commit()` `fsync` never stalls a Tokio worker thread. On slow disks this previously drifted the ping loop timing and caused false disconnections / reconnection storms. The public `DB` type is unchanged (uses `blocking_lock()` internally).
* Connect directly to a known fixed server IP without depending on `get_ip_address()` / internet reachability — works on isolated LANs with no route to the outside. The local IP is now resolved only on the scan path.
* **Behavior change:** local subnet auto-scan is now opt-in. Added `ClientOptions::use_scan_discovery` (default `false`); when the server IP is unknown the client reports `Disconnected` and the app keeps running instead of scanning. Trigger discovery explicitly with the new `AtomicClient::scan_and_connect()` ("search" button), bounded by `ClientOptions::scan_timeout_seconds` (default 60). Added `ScanManager::run_with_timeout()` and matching builder setters.
* `test_client` now takes `<server_ip> <port> <client_id>` arguments and persists them to the database, and starts even when the server is unreachable. Fixed pre-existing compile errors in `test_client`/`test_server`.
* Replaced the unmaintained/archived `rustls-pemfile` (RUSTSEC-2025-0134) with the PEM parsing in `rustls-pki-types` (re-exported by `rustls`), removing a dependency. Only affects the `rustls` feature.
* Added stress/regression tests for runtime blocking (`tests/stress_blocking_test.rs`) and fixed-IP behavior (`tests/fixed_ip_test.rs`).
## 0.8.0
* Improve performance, connection stability and WebSocket upgrade with safer APIs.
## 0.7.5
* Remove send timeout to prevent false disconnection under backpressure
## 0.7.4
* Add spillover for dropped client send message
## 0.7.3
* Add spillover for dropped send message
## 0.7.2
* Add metrics, middleware, TLS support and refactor interior mutability.
## 0.7.1
* Improve connection stabiliation.
## 0.7.0
* Refactor code base, remove db dependency.
## 0.6.33
* Add send_all_in_list in clientSenders.
## 0.6.32
* Combine serverOption in clientSenders.
## 0.6.31
* Fixed proxy_ping with server.
## 0.6.30
* Fixed use_ping with false when connected first.
## 0.6.29
* Fixed use_ping for loop_checker.
## 0.6.28
* Fixed loop_checker for external connection.
## 0.6.27
* Add README.md and doc in files.
## 0.6.26
* Fixed get_ip_address for local wifi.
## 0.6.25
* Fixed remove release connect when connect failed.
## 0.6.24
* Fixed release connect when duplicated connect logic.
## 0.6.23
* Fixed release connect when error in connect logic.
## 0.6.22
* Fixed prevent retry connect when connected to server.
## 0.6.21
* Fixed prevent retry connect when connecting progress.
## 0.6.20
* Improve client connection stability when write received time with message from server.
## 0.6.19
* Improve client scan logic.
## 0.6.18
* Improve client keepalive connect when no server_ip.
## 0.6.17
* Improve client keepalive connect.
## 0.6.16
* Fixed prevent duplicate client reconnection from same IP
## 0.6.15
* Change dependency: Replace OpenSSL with Rustls
## 0.6.14
* Improve atomic type of db, refactoring types.
## 0.6.13
* Update dependencies.
## 0.6.12
* Update dependencies.
## 0.6.11
* Rollback to 0.6.6v.
## 0.6.10
* Remove for server_sender when process dropped.
## 0.6.9
* Fixed for server_sender when process dropped in try_connect condition.
## 0.6.8
* Fixed for server_sender when process dropped in loop checker.
## 0.6.7
* Add for server_sender when process dropped.
## 0.6.6
* Fixed for add server_ip.
## 0.6.5
* Improve scan ip using timeout(10s).
## 0.6.4
* Fixed for client_sender's handle message.
## 0.6.3
* Fixed for scan_manager when is_connected function.
## 0.6.2
* Fixed scan ip for internal client connect when connected server.
## 0.6.1
* Improve scan ip for internal client connect, change server handle message receiver from broadcast to mpsc.
## 0.6.0
* Improve scan ip for internal client connect, adjust backoff send, change message receiver from broadcast to mpsc.
## 0.5.8
* Fixed for client_sender's check_client_send_time.
## 0.5.7
* Remove for server_sender's get_server_ip, fixed get_data_schema.
## 0.5.6
* Fixed for server_sender's change_ip to remove_ip.
## 0.5.5
* Add for client_connector timeout option.
## 0.5.4
* Add for client_senders's send is return bool.
## 0.5.3
* Fixed for freeze client_sender when client_senders send fail process.
## 0.5.2
* Fixed for remove client when client_senders send fail.
## 0.5.1
* Add make_atomic_message and prevent call when server_ip found.
## 0.5.0
* Convert import message for any language.
## 0.4.5
* Add import binary from all message.
## 0.4.4
* Add import binary from text message.
## 0.4.3
* Fixed duplicated connect and infinite connection, improve logic.
## 0.4.2
* Add is_active for clientSender.
## 0.4.1
* Improve loop and db logic.
## 0.4.0
* Add client and server with senders
## 0.3.18
* Update dependencies.
## 0.3.17
* Add function is get_ip_address.
## 0.3.16
* Fixed for connect server_ip.
## 0.3.15
* Fixed for connect state condition to write received message times.
## 0.3.14
* Update dependencies.
## 0.3.13
* Fixed for is_avalid_server_ip condition.
## 0.3.12
* Add disconnect for client when duplicate connector.
## 0.3.11
* Change server message channel. 4 -> 1024
## 0.3.10
* Change communicate message to async.
## 0.3.9
* Add rinf debug option.
## 0.3.8
* Change server sender to improve response.
## 0.3.7
* Change refactor loop client, split test in client and server.
## 0.3.6
* Add for client ping delay using retry_seconds option.
## 0.3.5
* Fixed for client loopChecker when send message locking.
## 0.3.4
* Fixed for client loopChecker when deadlock.
## 0.3.3
* Fixed for client loopChecker when read and write.
## 0.3.2
* Add condition for is_valid_server_ip(calculate server_send_times).
## 0.3.1
* Add use_keep_ip option for client.
## 0.3.0
* Change for watch receiver to broadcast receiver!
## 0.2.7
* Fixed for client when received pong with connectState.
## 0.2.6
* Add retry_seconds option for client.(default: 30 seconds)
## 0.2.5
* Fixed for native_tls logger.
## 0.2.4
* Change for logging system. Thank for Jake Kwak!
And Fixed init receive handle_message error.
## 0.2.3
* Add for server proxy ping option.
## 0.2.2
* Fixed for server acceptor with spawn.
## 0.2.1
* Fixed for native_tls connector missing dependency.
## 0.2.0
* Add outer connect client.
## 0.1.10
* Fixed for default value in watch message handle.
## 0.1.9
* Add options for client and server. ( use_ping )
## 0.1.8
* Add clone for Settings struct, remove export serde in external.
## 0.1.7
* Add export external list.
async_trait,
nanoid,
serde,
tokio
## 0.1.6
* Add partialEqual for SenderStatus.
## 0.1.5
* Add get_connect for client.
## 0.1.4
* Add get_server_ip for ServerSender.
## 0.1.3
* Add export get_id.
## 0.1.2
* Reorder export list for client and server.
## 0.1.1
* Add re export for client and server.
## 0.1.0
* First init simple websocket.