Metadata-Version: 2.4
Name: ticketing
Version: 0.0.2
Summary: Distributed ticket lock client
Author-email: Marker Seoul <j@saro.me>
Project-URL: Homepage, https://ticketing.saro.me
Project-URL: Repository, https://github.com/saro-lab/ticketing
Project-URL: Documentation, https://github.com/saro-lab/ticketing
Keywords: ticketing,distributed,lock,mutex,fencing,token
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# Ticketing - Distributed Ticket Lock Client

An asyncio client for a network distributed lock ("ticket") service. Acquire a
named lock with a wait budget and a lease, get a monotonic fencing token, run
your critical section, then release.

### Document
- [Ticketing Online](https://ticketing.saro.me)
- [Example](https://ticketing.saro.me/libs/pypi-saro-ticketing)

### Support Platform
- [Java, Kotlin](https://github.com/saro-lab/ticketing-maven)
- [Javascript, Typescript](https://github.com/saro-lab/ticketing-npm)
- [C#](https://github.com/saro-lab/ticketing-nuget)
- [Python](https://github.com/saro-lab/ticketing-pypi)
- [Go](https://github.com/saro-lab/ticketing-go)
- [Ruby](https://github.com/saro-lab/ticketing-ruby)
- [C/C++ (Vcpkg)](https://github.com/saro-lab/ticketing-vcpkg)

## Install

```shell
pip install ticketing
```

## Usage

```python
import asyncio
from saro_ticketing import TicketBroker


async def main():
    broker = TicketBroker.connect("127.0.0.1:5225", "127.0.0.1:5226")
    try:
        await broker.wait_ready(5)

        ticket = await broker.acquire("order-42", wait=5, lease=30)
        try:
            # ... critical section, guarded by ticket.token at the resource ...
            print("token:", ticket.token)
        finally:
            await ticket.release()
    finally:
        broker.close()


asyncio.run(main())
```

`wait` and `lease` accept either a number of seconds or a
`datetime.timedelta`. `wait=0` waits indefinitely; the server enforces the
wait, so giving up never strands a lock. The `lease` is the safety net that
frees the lock if this client dies without releasing.

A `Ticket` is also an async context manager, releasing on exit:

```python
async with await broker.acquire("order-42", wait=5, lease=30) as ticket:
    ...  # critical section
```

## Notes

- One address is held with two connections to the same node; two or more
  addresses form a cluster the broker fails over between.
- Everything runs on a single event loop, so the client keeps no locks of its
  own — a coroutine holds the loop across the read-modify-write of its internal
  state.
