Skip to content

Commit 99ab7e0

Browse files
committed
Add python IceDiscovery/replication demo
1 parent 67394b8 commit 99ab7e0

File tree

9 files changed

+264
-16
lines changed

9 files changed

+264
-16
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
*.pyc
2+
VisitorCenter
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# IceDiscovery Replication
2+
3+
This demo illustrates how to use the IceDiscovery plug-in with replicated servers.
4+
5+
We recommend running each program in a separate Python virtual environment.
6+
If you are new to Python virtual environments, see [Python Virtual Environments].
7+
8+
## Running the server
9+
10+
Navigate to the `server` or `server_asyncio` directory, depending on whether you want to run the synchronous or asynchronous server.
11+
12+
### 1. Create and activate a Python virtual environment
13+
14+
#### macOS and Linux
15+
16+
```bash
17+
python3 -m venv venv
18+
source venv/bin/activate
19+
```
20+
21+
#### Windows (PowerShell)
22+
23+
```powershell
24+
python -m venv venv
25+
venv\Scripts\activate
26+
```
27+
28+
### 2. Install program dependencies
29+
30+
```bash
31+
pip install -r requirements.txt
32+
```
33+
34+
### 3. Compile the Slice definitions
35+
36+
Use the Slice-to-Python compiler to generate Python code from the `Greeter.ice` file:
37+
38+
```bash
39+
slice2py ../slice/Greeter.ice
40+
```
41+
42+
### 4. Run the server
43+
44+
First, start two or more Server programs, each in its own terminal:
45+
46+
```bash
47+
python main.py --Ice.Trace.Locator
48+
```
49+
50+
> The command must be run from an active venv.
51+
52+
## Running the client
53+
54+
In a separate terminal, navigate to the `client` directory.
55+
56+
### 1. Create and activate a Python virtual environment
57+
58+
#### macOS and Linux
59+
60+
```bash
61+
python3 -m venv venv
62+
source venv/bin/activate
63+
```
64+
65+
#### Windows (PowerShell)
66+
67+
```powershell
68+
python -m venv venv
69+
venv\Scripts\activate
70+
```
71+
72+
### 2. Install program dependencies
73+
74+
```bash
75+
pip install -r requirements.txt
76+
```
77+
78+
### 3. Compile the Slice definitions
79+
80+
Use the Slice-to-Python compiler to generate Python code from the `Greeter.ice` file:
81+
82+
```bash
83+
slice2py ../slice/Greeter.ice
84+
```
85+
86+
### 4. Run the client
87+
88+
```bash
89+
python main.py --Ice.Trace.Locator
90+
```
91+
92+
> [!NOTE]
93+
> The `--Ice.Trace.Locator` command-line option is optional: it enables tracing (logging) for locator resolution and
94+
> helps you understand the locator logic implemented by the IceDiscovery plug-in.
95+
96+
[Python Virtual Environments]: https://docs.python.org/3/tutorial/venv.html
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#!/usr/bin/env python
2+
# Copyright (c) ZeroC, Inc.
3+
4+
import asyncio
5+
import getpass
6+
import sys
7+
8+
import Ice
9+
10+
# Slice module VisitorCenter in Greeter.ice maps to Python module VisitorCenter.
11+
import VisitorCenter
12+
13+
14+
async def main():
15+
# Configure the communicator to load the IceDiscovery plug-in during initialization. This plug-in installs a default
16+
# locator on the communicator.
17+
initData = Ice.InitializationData()
18+
initData.properties = Ice.createProperties(sys.argv)
19+
initData.properties.setProperty("Ice.Plugin.IceDiscovery", "1")
20+
21+
# Configure the Ice runtime to use asyncio.
22+
initData.eventLoopAdapter = Ice.asyncio.EventLoopAdapter(asyncio.get_running_loop())
23+
24+
# Create an Ice communicator. We'll use this communicator to create proxies, and manage outgoing connections.
25+
async with Ice.initialize(initData=initData) as communicator:
26+
# Create a proxy to the Greeter object hosted by the server. "greeter" is a stringified proxy with no
27+
# addressing information, also known as a well-known proxy. It's resolved by the default locator installed by
28+
# the IceDiscovery plug-in.
29+
greeter = VisitorCenter.GreeterPrx(communicator, "greeter")
30+
31+
# Send a request to the remote object and get the response.
32+
greeting = await greeter.greetAsync(getpass.getuser())
33+
print(greeting)
34+
35+
36+
if __name__ == "__main__":
37+
asyncio.run(main())
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Use ZeroC Nightly repository as the main index for pip.
2+
--index-url https://download.zeroc.com/nexus/repository/pypi-nightly/simple/
3+
4+
# Allow installing additional packages from PyPI main index if not found in the ZeroC repository.
5+
--extra-index-url https://pypi.org/simple/
6+
7+
# Allow installing pre-release versions (required for zeroc-ice nightly builds).
8+
--pre
9+
10+
# Add the zeroc-ice package (latest nightly version). This package includes the Slice to Python compiler (slice2py).
11+
zeroc-ice
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Copyright (c) ZeroC, Inc.
2+
3+
import Ice
4+
5+
# Slice module VisitorCenter in Greeter.ice maps to Python module VisitorCenter.
6+
import VisitorCenter
7+
8+
9+
class Chatbot(VisitorCenter.Greeter):
10+
"""
11+
Chatbot is an Ice servant that implements Slice interface Greeter.
12+
"""
13+
14+
def __init__(self, greeterName: str):
15+
"""
16+
Creates a new Chatbot instance.
17+
18+
Parameters
19+
----------
20+
greeterName : str
21+
The name of the new greeter.
22+
"""
23+
self._greeterName = greeterName
24+
25+
# Implements the method greet from the Greeter class generated by the Slice compiler.
26+
# This variant is the synchronous implementation.
27+
def greet(self, name: str, current: Ice.Current) -> str:
28+
print(f"Dispatching greet request {{ name = '{name}' }}")
29+
return f"Hello, {name}! I am {self._greeterName}. How can I help you today?"
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#!/usr/bin/env python
2+
# Copyright (c) ZeroC, Inc.
3+
4+
import sys
5+
import uuid
6+
7+
import chatbot
8+
import Ice
9+
10+
11+
def main():
12+
# Configure the communicator to load the IceDiscovery plug-in during initialization. This plug-in installs a default
13+
# locator on the communicator.
14+
initData = Ice.InitializationData()
15+
initData.properties = Ice.createProperties(sys.argv)
16+
initData.properties.setProperty("Ice.Plugin.IceDiscovery", "1")
17+
18+
greeter_uuid = str(uuid.uuid4())
19+
# Configure the object adapter GreeterAdapter. It must be an indirect object adapter (i.e., with an AdapterId
20+
# property); otherwise, the IceDiscovery plug-in can't make it discoverable by IceDiscovery clients.
21+
initData.properties.setProperty("GreeterAdapter.AdapterId", f"greeter-{greeter_uuid}")
22+
initData.properties.setProperty("GreeterAdapter.ReplicaGroupId", "greeterPool")
23+
24+
# Configure the GreeterAdapter to listen on TCP with an OS-assigned port. We don't need a fixed port since the
25+
# clients discover this object adapter.
26+
initData.properties.setProperty("GreeterAdapter.Endpoints", "tcp")
27+
28+
# Create an Ice communicator. We'll use this communicator to create an object adapter.
29+
with Ice.initialize(initData=initData) as communicator:
30+
# Create an object adapter that listens for incoming requests and dispatches them to servants.
31+
adapter = communicator.createObjectAdapter("GreeterAdapter")
32+
33+
# Register the Chatbot servant with the adapter.
34+
adapter.add(chatbot.Chatbot(greeter_uuid[0:4]), Ice.Identity(name="greeter"))
35+
36+
# Start dispatching requests. This method also registers the object adapter with the IceDiscovery plug-in.
37+
adapter.activate()
38+
print("Listening...")
39+
40+
try:
41+
# Wait until communicator.shutdown() is called, which never occurs in this demo.
42+
communicator.waitForShutdown()
43+
except KeyboardInterrupt:
44+
print("Caught Ctrl+C, exiting...")
45+
46+
47+
if __name__ == "__main__":
48+
main()
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Use ZeroC Nightly repository as the main index for pip.
2+
--index-url https://download.zeroc.com/nexus/repository/pypi-nightly/simple/
3+
4+
# Allow installing additional packages from PyPI main index if not found in the ZeroC repository.
5+
--extra-index-url https://pypi.org/simple/
6+
7+
# Allow installing pre-release versions (required for zeroc-ice nightly builds).
8+
--pre
9+
10+
# Add the zeroc-ice package (latest nightly version). This package includes the Slice to Python compiler (slice2py).
11+
zeroc-ice
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright (c) ZeroC, Inc.
2+
3+
module VisitorCenter
4+
{
5+
/// Represents a simple greeter.
6+
interface Greeter
7+
{
8+
/// Creates a personalized greeting.
9+
/// @param name The name of the person to greet.
10+
/// @return The greeting.
11+
string greet(string name);
12+
}
13+
}

python/README.md

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,20 @@
33
This folder contains example Ice applications written in Python. Each example is a simple client-server application that
44
demonstrates a specific feature or programming technique.
55

6-
| | |
7-
|-----------------------------------------------------|-------------------------------------------------------------------------------------------------------|
8-
| [Glacier2 callback](./Glacier2/callback/) | Shows how to write a Glacier2 client and implement callbacks in this client. |
9-
| [Glacier2 greeter](./Glacier2/greeter/) | Shows how to write a basic Glacier2 client. |
10-
| [Ice Bidir](./Ice/bidir/) | Shows how to send requests "the other way around", from the server to the client. |
11-
| [Ice Callback](./Ice/callback/) | Shows how to implement callbacks in a client application. |
12-
| [Ice Config](./Ice/config/) | Shows how to configure client and server applications using Ice configuration files. |
13-
| [Ice Context](./Ice/context/) | Shows how to set and retrieve request contexts. |
14-
| [Ice Custom Error](./Ice/customError/) | Shows how to define a new exception in Slice and return this exception from a Slice operation. |
15-
| [Ice Greeter](./Ice/greeter/) | Shows how to call and implement a canonical Greeter application with Ice. **Start with this demo!** |
16-
| [Ice Inheritance](./Ice/inheritance/) | Shows the power of interface inheritance in Slice. |
17-
| [Ice Invocation Timeout](./Ice/invocation_timeout/) | Shows how to use invocation timeouts |
18-
| [Ice Optional](./Ice/optional/) | Shows how to add a field to a Slice class without breaking interop with existing clients and servers. |
19-
| [IceDiscovery Greeter](./IceDiscovery/greeter/) | Shows how to configure the IceDiscovery plug-in. |
20-
| [IceGrid Greeter](./IceGrid/greeter) | Shows how to create a simple IceGrid deployment. |
21-
| [IceStorm Weather](./IceStorm/weather/) | Shows how to use IceStorm to create a simple pub-sub application. |
6+
| | |
7+
|---------------------------------------------------------|-------------------------------------------------------------------------------------------------------|
8+
| [Glacier2 callback](./Glacier2/callback/) | Shows how to write a Glacier2 client and implement callbacks in this client. |
9+
| [Glacier2 greeter](./Glacier2/greeter/) | Shows how to write a basic Glacier2 client. |
10+
| [Ice Bidir](./Ice/bidir/) | Shows how to send requests "the other way around", from the server to the client. |
11+
| [Ice Callback](./Ice/callback/) | Shows how to implement callbacks in a client application. |
12+
| [Ice Config](./Ice/config/) | Shows how to configure client and server applications using Ice configuration files. |
13+
| [Ice Context](./Ice/context/) | Shows how to set and retrieve request contexts. |
14+
| [Ice Custom Error](./Ice/customError/) | Shows how to define a new exception in Slice and return this exception from a Slice operation. |
15+
| [Ice Greeter](./Ice/greeter/) | Shows how to call and implement a canonical Greeter application with Ice. **Start with this demo!** |
16+
| [Ice Inheritance](./Ice/inheritance/) | Shows the power of interface inheritance in Slice. |
17+
| [Ice Invocation Timeout](./Ice/invocation_timeout/) | Shows how to use invocation timeouts |
18+
| [Ice Optional](./Ice/optional/) | Shows how to add a field to a Slice class without breaking interop with existing clients and servers. |
19+
| [IceDiscovery Greeter](./IceDiscovery/greeter/) | Shows how to configure the IceDiscovery plug-in. |
20+
| [IceDiscovery Replication](./IceDiscovery/Replication/) | Shows how to use the IceDiscovery plug-in with replicated servers. |
21+
| [IceGrid Greeter](./IceGrid/greeter) | Shows how to create a simple IceGrid deployment. |
22+
| [IceStorm Weather](./IceStorm/weather/) | Shows how to use IceStorm to create a simple pub-sub application. |

0 commit comments

Comments
 (0)