Metadata-Version: 2.1
Name: thunderstrike
Version: 0.1.2
Summary: Python client for the thunderstrike key-value database (TLS 1.3, pipelined, batch operations)
Home-page: https://github.com/TheManhattanProject/thunderstrike-client
Author: SHORTSQUEEZE PRIVATE LIMITED
License: Proprietary
Keywords: thunderstrike,key-value,kv,database,client,tls
Project-URL: Source, https://github.com/TheManhattanProject/thunderstrike-client
Project-URL: Issues, https://github.com/TheManhattanProject/thunderstrike-client/issues
Project-URL: Server, https://hub.docker.com/r/sbansal793/thunderstrike
Requires-Python: >=3.8
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: Other/Proprietary License
Classifier: Operating System :: POSIX :: Linux
Classifier: Operating System :: Microsoft :: Windows
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Topic :: Database
Classifier: Topic :: Database :: Front-Ends
Description-Content-Type: text/markdown; charset=UTF-8

# thunderstrike

Python client for the [thunderstrike](https://hub.docker.com/r/sbansal793/thunderstrike)
key-value database: a pool of pipelined TLS 1.3 connections behind a
small blocking API.

The wheel carries the compiled client library. Nothing to compile on
install, and no dependencies beyond the standard library (it uses
`ctypes`).

## Install

```sh
pip install thunderstrike
```

Python 3.8 or newer, on Linux x86-64 / ARM64 (glibc 2.17 or newer) or
Windows x86-64. macOS wheels come in a later release.

## Quick start

The server speaks TLS 1.3 only. The client needs the CA certificate that
issued the server's certificate (`docker/tls/ca.crt` in the server's kit)
and a DNS name that certificate carries (`localhost` unless the server
was set up with other `THUNDERSTRIKE_TLS_NAMES`).

```python
from thunderstrike import Thunderstrike

with open("ca.crt", "rb") as f:
    ca = f.read()

with Thunderstrike("127.0.0.1:7380",
                   tls_server_name="localhost",
                   tls_ca_pem=ca) as db:
    db.set(b"user:1", b"ada")
    print(db.get(b"user:1"))   # b'ada'
    print(db.get(b"nope"))     # None
```

Give it one address. The client asks that server for the cluster layout
and connects to every core (core *c* listens on port 7380 + *c*), so
those ports must be reachable too.

`tls_server_name` is sent as SNI and checked against the certificate,
so it is the name the certificate was issued for, not necessarily the
host you dial. There is no way to turn verification off.

## Operations

Keys and values are `bytes`. A key is at most 65,535 bytes; an empty
value is refused.
Keys do not expire: a value stays until it is deleted or overwritten.

```python
db.set(b"k", b"v")
db.get(b"k")                 # b"v", or None when absent
db.get(b"k", b"fallback")    # a default for a miss
db.exists(b"k")              # True / False
db.append(b"k", b"-more")    # appends (creates if absent); returns the new length
db.delete(b"k")              # True if it was there
db.ping()

# Mapping-style access
db[b"k"] = b"v"
value = db[b"k"]             # raises NotFound on a miss
del db[b"k"]                 # raises NotFound on a miss
b"k" in db                   # exists()
```

### Batches

For more than one key, use the batch calls. They put every request on
the wire before waiting for any answer, so *n* keys cost one round trip
instead of *n*.

```python
db.mset({b"a": b"1", b"b": b"2"})           # or a list of (key, value) pairs
db.mget([b"a", b"b", b"missing"])            # [b"1", b"2", None]
db.mdelete([b"a", b"b", b"missing"])         # [True, True, False]
```

### Threads

One `Thunderstrike` instance is safe to share across threads, and
should be: it is a connection pool. The GIL is released during every
call, so a thread waiting on the server does not block the others. The
API is blocking; there is no asyncio interface in this release (run calls
in a thread pool from async code).

## Errors and retries

Every failure raises `ThunderstrikeError` (or a subclass) with:

- `code`: the numeric status (positive from the server, negative from
  the client).
- `retry_class`: whether sending the request again is sound.
- `detail`: the specific cause when there is one, e.g. the TLS reason.

| `retry_class` | meaning |
|---|---|
| `thunderstrike.RETRY_ALWAYS` | Busy: the server did not apply it. Retry anything after a short backoff. |
| `thunderstrike.RETRY_IF_IDEMPOTENT` | A lost connection or a timeout: the outcome is unknown. Repeat `get`, `set`, `exists` and `ping` only. |
| `thunderstrike.RETRY_NEVER` | Everything else. |

The client has already retried Busy answers (every operation but delete)
and dropped connections (idempotent operations) before it raises.

Subclasses: `NotFound`, `Timeout`, `Disconnected`, `Closed`, `Busy`,
`ServerOutOfMemory`, `StorageExhausted`, `ServerError`, `TlsError`.

```python
import thunderstrike

try:
    db.set(b"k", b"v")
except thunderstrike.Busy:
    ...  # not applied; safe to try again later
except thunderstrike.ThunderstrikeError as e:
    print(e.code, e.retry_class, e.detail)
```

## Configuration

All keyword-only, all optional except the TLS pair:

| option | meaning |
|---|---|
| `tls_server_name`, `tls_ca_pem` | TLS 1.3: the certificate's name and the CA (PEM, `bytes` or `str`). Give both. |
| `tls_client_cert_pem`, `tls_client_key_pem` | Client certificate (mTLS), for a server that requires one. |
| `request_timeout_ms` | Per-request deadline, covering retries. Default 60000; 0 disables it. |
| `connect_timeout_ms` | Connect and TLS handshake deadline. |
| `connections_per_endpoint` | TCP connections per server core. |
| `max_inflight` | Pipeline depth per connection. |
| `max_retries` | Retries for an idempotent request whose connection dropped. |
| `busy_retries`, `busy_backoff_ms=(min, max)`, `busy_retry_window_ms` | Busy retry policy. Defaults 4, (2, 200), 5000. |
| `max_response_bytes` | Largest response the client will accept. |
| `tcp_keepalive_ms`, `tcp_nodelay` | Socket options. |
| `min_io_threads`, `max_io_threads` | Bounds on the client's I/O threads. |

`db.stats()` returns pool counters (connections, requests, bytes,
reconnects). `db.endpoints()` is the number of server cores connected,
`db.shards()` the number of shards.

The library loads from inside the package. To use another build, set
`THUNDERSTRIKE_CLIENT_LIB` to its path.

## Links

- Source and issues: https://github.com/TheManhattanProject/thunderstrike-client
- Server image: https://hub.docker.com/r/sbansal793/thunderstrike
- Clients for other languages: see the repository README.

## License

Proprietary, free to use: see the `LICENSE` file shipped in the package.
You may build this library into your own applications and ship it as
part of them.

Copyright (c) 2026 SHORTSQUEEZE PRIVATE LIMITED.
