Skip to content

Latest commit

 

History

History
196 lines (138 loc) · 6.5 KB

File metadata and controls

196 lines (138 loc) · 6.5 KB
sidebarTitle Python

Python Client SDK

Installing Python client SDK

pip install oxia

PyDoc documentation is available at https://oxia-db.github.io/oxia-client-python/latest

Client API

Initializing the client

To use the Oxia client, you need to create a client instance. Once created, a client instance will be valid until it's explicitly closed, and it can be used from different threads.

import oxia
client = oxia.Client("localhost:6648")

When creating the client it is possible to pass several options, such as:

client = oxia.Client("localhost:6648",
                     namespace="my-namespace",
                     client_identifier="my-client-identity",
)

Available Client constructor options:

Option Type Description Default
namespace str Oxia namespace to use. "default"
session_timeout_ms int Session timeout for ephemeral records, in milliseconds. 30000
client_identifier str Stable client identity attached to ephemeral records. Random UUID
request_timeout_ms int Deadline for each unary RPC. Long-lived streams are unbounded. 30000
authentication oxia.defs.Authentication Credentials attached as gRPC metadata. See oxia.auth.TokenAuthentication. None

For the full parameter list see the Client constructor docs.

Writing records

# Write a record to Oxia with the specified key and value, and with the expectation
# that the record does not already exist.
key, version1 = client.put("my-key", "value-1",
                           expected_version_id=oxia.EXPECTED_RECORD_DOES_NOT_EXIST)

# Write a record with the expectation that it has not changed since the previous write.
# If there was any change, the operation will fail.
key, version2 = client.put("my-key", "value-2",
                           expected_version_id=version1.version_id())

# Ephemeral record: deleted automatically when the client session ends.
client.put("/workers/worker-1", b"host:port", ephemeral=True)

# Atomic sequence key: server appends a monotonic suffix; requires a partition key.
key, version = client.put("/events/", b"event-data",
                          sequence_keys_deltas=[1],
                          partition_key="/events/")

# Attach a secondary index entry at write time.
client.put("/offset/12345", b"...",
           secondary_indexes={"partition": "p-17"})

put() options:

Option Description
partition_key Route to a specific shard (co-locate related keys).
expected_version_id Conditional write; use oxia.EXPECTED_RECORD_DOES_NOT_EXIST to assert absence.
ephemeral Bind the record to the client session — see ephemerals.
sequence_keys_deltas Server-assigned monotonic suffixes — see sequence keys.
secondary_indexes {index_name: secondary_key} — see secondary indexes.

Full reference: put() method docs.

Reading records

Reading the value of a record:

key, value, version = client.get("my-key")

# Metadata-only read (skips the value payload).
key, _, version = client.get("my-key", include_value=False)

# Range-style Get: returns the closest key ≤ the lookup key.
from oxia import ComparisonType
key, value, version = client.get("/users/50",
                                 comparison_type=ComparisonType.FLOOR)

get() options:

Option Description
comparison_type EQUAL (default), FLOOR, CEILING, LOWER, HIGHER. Non-equal modes scan all shards unless partition_key is set.
include_value Set to False for a metadata-only read.
partition_key Route to a specific shard.
use_index Look up via a named secondary index.

Full reference: get() method docs.

Deleting records

Delete a single record by key. Supports conditional deletes using version-based expectations.

# Unconditional delete
client.delete("my-key")

# Conditional delete: only succeed if the version matches
client.delete("my-key", expected_version_id=version.version_id())

All the options for the delete operation are available in the delete() method docs.

Deleting a range of records

Delete all records whose keys fall within [min, max):

client.delete_range("/users/", "/users//")

Without partition_key, the call fans out to every shard. Pass partition_key to scope the delete to a single shard.

Listing keys

List keys in [min, max) without fetching values:

keys = client.list("/users/", "/users//")
for key in keys:
    print(key)

# Narrow to a single shard via partition_key, or query a secondary index via use_index.
keys = client.list("/users/", "/users//", partition_key="/users/")
keys = client.list("", "\xff", use_index="email")

Scanning records

Scan records in a key range, returning keys and values:

for key, value, version in client.range_scan("/users/", "/users//"):
    print(f"key: {key}, value: {value}, version: {version}")

# With a secondary index.
for key, value, version in client.range_scan(
        "", "\xff", use_index="email"):
    print(key)

list() and range_scan() both accept partition_key and use_index.

Sessions and ephemerals

Sessions are managed transparently: the first put(..., ephemeral=True) creates a per-shard session, the client SDK heartbeats it, and ephemerals are cleaned up when the client closes or the session expires. See ephemerals for the lifecycle details.

Notifications and sequence updates

Both streams are exposed as plain Python iterators:

# Change feed for the namespace.
for notification in client.get_notifications():
    print(notification)

# Updates for a specific sequence prefix.
for key in client.get_sequence_updates("/events/", partition_key="/events/"):
    print(f"New sequence key: {key}")

See notifications and sequence keys for semantics.

For the complete reference see the PyDoc reference.