# Lockserver
[](https://github.com/benliao/lockserver/actions)
[](https://github.com/benliao/lockserver/actions)
[](https://crates.io/crates/lockserver)
[](https://crates.io/crates/lockserver)
[](LICENSE)
Lockserver is a distributed lock server for coordinating access to shared resources across multiple workers or processes. It provides an HTTP API and a Rust client library with ergonomic macros for easy distributed locking.
## Features
- Simple API for acquiring and releasing locks
- HTTP API only (no TCP service)
- Client library with ergonomic macros (`lock_scope!`)
- Blocking and non-blocking lock acquisition
- Ready for publishing to crates.io
## Usage
### Start the server
## Security: Shared Secret Authorization
All client requests must include a shared secret for authorization. The server and client must agree on the same secret, set via the `LOCKSERVER_SECRET` environment variable or `.env` file. The client sends this secret in the `X-LOCKSERVER-SECRET` HTTP header.
**Example .env:**
```
LOCKSERVER_SECRET=your-strong-secret
```
**Server:**
```
LOCKSERVER_SECRET=your-strong-secret
cargo run --release
```
**Client:**
```
LOCKSERVER_SECRET=your-strong-secret
```
Or pass the secret directly to the client constructor.
You can configure the bind IP and HTTP port using CLI arguments, environment variables, or a `.env` file (using dotenvy):
**CLI arguments (override env/.env):**
```sh
cargo run --release -- --bind 127.0.0.1 --port 9000
# or short form:
cargo run --release -- -b 127.0.0.1 -p 9000
```
**Environment variables or .env file:**
```
LOCKSERVER_BIND_IP=127.0.0.1
LOCKSERVER_PORT=9000
```
Then just run:
```sh
cargo run --release
```
### HTTP API (default port 8080)
- Acquire a lock:
`POST /acquire` with JSON `{ "resource": "myres", "owner": "worker1" }`
- Release a lock:
`POST /release` with JSON `{ "resource": "myres", "owner": "worker1" }`
Example using `curl` (with secret):
```sh
curl -X POST -H "Content-Type: application/json" -H "X-LOCKSERVER-SECRET: your-strong-secret" \
-d '{"resource":"myres","owner":"worker1"}' http://localhost:8080/acquire
curl -X POST -H "Content-Type: application/json" -H "X-LOCKSERVER-SECRET: your-strong-secret" \
-d '{"resource":"myres","owner":"worker1"}' http://localhost:8080/release
```
### Rust Client Library & Macro
Add to your `Cargo.toml`:
```toml
[dependencies]
lockserver = "0.1"
```
#### Client configuration
The client can load the server address and owner from environment variables or a `.env` file:
```
LOCKSERVER_ADDR=127.0.0.1:8080
LOCKSERVER_OWNER=worker1
```
Or pass them directly:
```rust
use lockserver::{LockserverClient, lock_scope};
// Loads from env/.env if None (including secret)
let client = LockserverClient::new_with_env(None::<String>, None::<String>, None::<String>);
lock_scope!(&client, "resource", {
// critical section
});
// Override address, owner, or secret:
let client = LockserverClient::new_with_env(
Some("192.168.1.10:9000"),
Some("myworker"),
Some("your-strong-secret")
);
// Non-blocking mode:
if let Ok(()) = client.acquire_with_mode("resource", lockserver::LockMode::NonBlocking) {
let _guard = lockserver::LockGuard::new(&client, "resource");
// critical section
}
```
For more advanced usage, see the integration tests in `tests/lock_scope_macro.rs`.
## License
Licensed under the [MIT License](LICENSE).