Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix python example #1866

Merged
merged 10 commits into from
Jul 9, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions examples/python/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
## Run
To run the example or any other Python application utilizing Valkey GLIDE, activate the virtual environment that created by the 'Build' stage:
```
cd examples/python
pip install -r requirements.txt
python3 client_example.py
python3 standalone_example.py
python3 cluster_example.py
```
90 changes: 0 additions & 90 deletions examples/python/client_example.py

This file was deleted.

125 changes: 125 additions & 0 deletions examples/python/cluster_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import asyncio
from typing import List, Tuple

from glide import (
AllNodes,
ClosingError,
GlideClusterClient,
GlideClusterClientConfiguration,
InfoSection,
Logger,
LogLevel,
NodeAddress,
RequestError,
)


async def create_client(
nodes_list: List[Tuple[str, int]] = [("localhost", 6379)]
) -> GlideClusterClient:
"""
Creates and returns a GlideClusterClient instance.

This function initializes a GlideClusterClient with the provided list of nodes.
In cluster mode, add the address of any node; the client will automatically
barshaul marked this conversation as resolved.
Show resolved Hide resolved
discover all nodes in the cluster.


Args:
nodes_list (List[Tuple[str, int]]): A list of tuples where each tuple
contains a host (str) and port (int). Defaults to [("localhost", 6379)].
barshaul marked this conversation as resolved.
Show resolved Hide resolved

Returns:
GlideClusterClient: An instance of GlideClusterClient connected to the specified nodes.
barshaul marked this conversation as resolved.
Show resolved Hide resolved
"""
addresses = [NodeAddress(host, port) for host, port in nodes_list]
# Check `GlideClusterClientConfiguration` for additional options.
config = GlideClusterClientConfiguration(
addresses=addresses,
client_name="test_cluster_client",
# Enable this field if the servers are configured with TLS.
# use_tls=True
)
return await GlideClusterClient.create(config)


async def app_logic(client: GlideClusterClient):
"""
Executes the main logic of the application, performing basic operations
such as SET, GET, PING, and INFO REPLICATION using the provided GlideClusterClient.

Args:
client (GlideClusterClient): An instance of GlideClusterClient.
"""
# Send SET and GET
set_response = await client.set("foo", "bar")
Logger.log(LogLevel.INFO, "app", f"Set response is = {set_response!r}")

get_response = await client.get("foo")
assert isinstance(get_response, bytes)
Logger.log(LogLevel.INFO, "app", f"Get response is = {get_response.decode()!r}")

# Send PING to all primaries (according to Redis's PING request_policy)
barshaul marked this conversation as resolved.
Show resolved Hide resolved
pong = await client.ping()
Logger.log(LogLevel.INFO, "app", f"PING response is = {pong!r}")

# Send INFO REPLICATION with routing option to all nodes
info_repl_resps = await client.info([InfoSection.REPLICATION], AllNodes())
Logger.log(
LogLevel.INFO,
"app",
f"INFO REPLICATION responses from all nodes are=\n{info_repl_resps!r}",
)


async def exec_app_logic():
"""
Executes the application logic with exception handling.
"""
while True:
try:
client = await create_client()
return await app_logic(client)
except asyncio.CancelledError:
barshaul marked this conversation as resolved.
Show resolved Hide resolved
raise
except ClosingError as e:
# If the error message contains "NOAUTH", raise the exception
# because it indicates a critical authentication issue.
if "NOAUTH" in str(e):
Logger.log(
LogLevel.ERROR,
"glide",
f"Authentication error encountered: {e}",
)
raise e
Logger.log(
LogLevel.WARN,
"glide",
f"Client has closed and needs to be re-created: {e}",
)
except RequestError as e:
Logger.log(LogLevel.ERROR, "glide", f"RequestError encountered: {e}")
raise e
except Exception as e:
Logger.log(LogLevel.ERROR, "glide", f"Unexpected error: {e}")
raise e
finally:
try:
await client.close()
eifrah-aws marked this conversation as resolved.
Show resolved Hide resolved
except Exception as e:
Logger.log(
LogLevel.WARN,
"glide",
f"Error encountered while closing the client: {e}",
)


def main():
Logger.set_logger_config(LogLevel.INFO)
barshaul marked this conversation as resolved.
Show resolved Hide resolved
# Optional - set the logger to write to a file
# Logger.set_logger_config(LogLevel.INFO, file)
asyncio.run(exec_app_logic())


if __name__ == "__main__":
main()
117 changes: 117 additions & 0 deletions examples/python/standalone_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import asyncio
from typing import List, Tuple

from glide import (
ClosingError,
GlideClient,
GlideClientConfiguration,
Logger,
LogLevel,
NodeAddress,
RequestError,
)


async def create_client(
nodes_list: List[Tuple[str, int]] = [("localhost", 6379)]
) -> GlideClient:
"""
Creates and returns a GlideClient instance.

This function initializes a GlideClient with the provided list of nodes.
The nodes_list can contain either only primary nodes or a mix of primary
barshaul marked this conversation as resolved.
Show resolved Hide resolved
and replica nodes. The GlideClient will use these nodes to connect to
the Redis cluster or standalone server.
barshaul marked this conversation as resolved.
Show resolved Hide resolved

Args:
nodes_list (List[Tuple[str, int]]): A list of tuples where each tuple
contains a host (str) and port (int). Defaults to [("localhost", 6379)].

Returns:
GlideClient: An instance of GlideClient connected to the specified nodes.
"""
addresses = []
for host, port in nodes_list:
addresses.append(NodeAddress(host, port))

# Check `GlideClientConfiguration` for additional options.
config = GlideClientConfiguration(
addresses,
# Enable this field if the servers are configured with TLS.
# use_tls=True
)
return await GlideClient.create(config)


async def app_logic(client: GlideClient):
"""
Executes the main logic of the application, performing basic operations
such as SET, GET, and PING using the provided GlideClient.

Args:
client (GlideClient): An instance of GlideClient.
"""
# Send SET and GET
set_response = await client.set("foo", "bar")
Logger.log(LogLevel.INFO, "app", f"Set response is = {set_response!r}")

get_response = await client.get("foo")
assert isinstance(get_response, bytes)
Logger.log(LogLevel.INFO, "app", f"Get response is = {get_response.decode()!r}")

# Send PING to the primary node
pong = await client.ping()
Logger.log(LogLevel.INFO, "app", f"PING response is = {pong!r}")


async def exec_app_logic():
"""
Executes the application logic with exception handling.
"""
while True:
try:
client = await create_client()
return await app_logic(client)
except asyncio.CancelledError:
raise
except ClosingError as e:
# If the error message contains "NOAUTH", raise the exception
# because it indicates a critical authentication issue.
if "NOAUTH" in str(e):
Logger.log(
LogLevel.ERROR,
"glide",
f"Authentication error encountered: {e}",
)
raise e
Logger.log(
LogLevel.WARN,
"glide",
f"Client has closed and needs to be re-created: {e}",
)
except RequestError as e:
Logger.log(LogLevel.ERROR, "glide", f"RequestError encountered: {e}")
raise e
except Exception as e:
Logger.log(LogLevel.ERROR, "glide", f"Unexpected error: {e}")
raise e
finally:
try:
await client.close()
except Exception as e:
Logger.log(
LogLevel.WARN,
"glide",
f"Encountered an error while closing the client: {e}",
)


def main():
Logger.set_logger_config(LogLevel.INFO)
barshaul marked this conversation as resolved.
Show resolved Hide resolved
# Optional - set the logger to write to a file
# Logger.set_logger_config(LogLevel.INFO, file)
asyncio.run(exec_app_logic())


if __name__ == "__main__":
main()
3 changes: 2 additions & 1 deletion python/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ Get response is bar
>>> asyncio.run(test_standalone_client())
Set response is OK
Get response is bar
```

For complete examples with error handling, please refer to the [cluster example](https://github.com/valkey-io/valkey-glide/blob/main/examples/python/cluster_example.py) and the [standalone example](https://github.com/valkey-io/valkey-glide/blob/main/examples/python/standalone_example.py).

## Documentation

Expand Down
Loading