ipc-framework 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,211 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ File Sharing Client Example
4
+
5
+ This example demonstrates how to use the IPC framework for file sharing operations.
6
+ It shows request/response patterns and status monitoring.
7
+ """
8
+
9
+ import time
10
+ import random
11
+ import threading
12
+ from .. import FrameworkClient, Message, MessageType
13
+
14
+
15
+ class FileClient:
16
+ def __init__(self, client_name: str, host: str = "localhost", port: int = 8888):
17
+ self.client_name = client_name
18
+ self.client = FrameworkClient("file_share", host, port)
19
+ self.uploaded_files = []
20
+
21
+ def connect(self):
22
+ """Connect to the file sharing server"""
23
+ if self.client.connect():
24
+ print(f"File client '{self.client_name}' connected")
25
+
26
+ # Subscribe to status updates
27
+ self.client.subscribe("status", self.handle_status_update)
28
+ return True
29
+ else:
30
+ print("Failed to connect to server")
31
+ return False
32
+
33
+ def handle_status_update(self, message: Message):
34
+ """Handle file operation status updates"""
35
+ payload = message.payload
36
+ msg_type = payload.get('type', 'unknown')
37
+
38
+ if msg_type == 'upload_progress':
39
+ filename = payload.get('filename', 'unknown')
40
+ progress = payload.get('progress', 0)
41
+ status = payload.get('status', 'unknown')
42
+ print(f"[STATUS] Upload {filename}: {progress}% - {status}")
43
+
44
+ def upload_file(self, filename: str, size: int):
45
+ """Upload a file (simulated)"""
46
+ print(f"Uploading file: {filename} ({size} bytes)")
47
+
48
+ self.client.request("upload", {
49
+ 'filename': filename,
50
+ 'size': size,
51
+ 'client': self.client_name,
52
+ 'connection_id': self.client.connection_id
53
+ })
54
+
55
+ self.uploaded_files.append(filename)
56
+ print(f"Upload request sent for {filename}")
57
+
58
+ def download_file(self, filename: str) -> bool:
59
+ """Download a file and wait for response"""
60
+ print(f"Requesting download: {filename}")
61
+
62
+ response = self.client.send_request("download", {
63
+ 'filename': filename,
64
+ 'client': self.client_name,
65
+ 'connection_id': self.client.connection_id
66
+ }, timeout=5.0)
67
+
68
+ if response:
69
+ payload = response.payload
70
+ download_url = payload.get('download_url', 'N/A')
71
+ expires_at = payload.get('expires_at', 0)
72
+ expires_in = int(expires_at - time.time())
73
+
74
+ print(f"Download ready:")
75
+ print(f" File: {filename}")
76
+ print(f" URL: {download_url}")
77
+ print(f" Expires in: {expires_in} seconds")
78
+ return True
79
+ else:
80
+ print(f"Download request timed out for {filename}")
81
+ return False
82
+
83
+ def list_files(self):
84
+ """List uploaded files"""
85
+ if self.uploaded_files:
86
+ print("Uploaded files:")
87
+ for i, filename in enumerate(self.uploaded_files, 1):
88
+ print(f" {i}. {filename}")
89
+ else:
90
+ print("No files uploaded yet")
91
+
92
+ def disconnect(self):
93
+ """Disconnect from the server"""
94
+ self.client.disconnect()
95
+ print(f"File client '{self.client_name}' disconnected")
96
+
97
+
98
+ def simulate_file_operations():
99
+ """Simulate various file operations"""
100
+ # Create multiple clients
101
+ clients = []
102
+ for i in range(3):
103
+ client = FileClient(f"Client_{i+1}")
104
+ if client.connect():
105
+ clients.append(client)
106
+ time.sleep(0.5)
107
+
108
+ if not clients:
109
+ print("No clients could connect")
110
+ return
111
+
112
+ print(f"\n=== Starting file operations with {len(clients)} clients ===\n")
113
+
114
+ # Simulate file uploads
115
+ sample_files = [
116
+ ("document.pdf", 1024000),
117
+ ("image.jpg", 2048000),
118
+ ("video.mp4", 50000000),
119
+ ("data.csv", 512000),
120
+ ("code.zip", 1536000)
121
+ ]
122
+
123
+ # Each client uploads some files
124
+ for client in clients:
125
+ num_files = random.randint(1, 3)
126
+ selected_files = random.sample(sample_files, num_files)
127
+
128
+ for filename, size in selected_files:
129
+ client.upload_file(f"{client.client_name}_{filename}", size)
130
+ time.sleep(1)
131
+
132
+ time.sleep(2)
133
+ print("\n=== Upload phase completed ===\n")
134
+
135
+ # Simulate downloads
136
+ for client in clients:
137
+ print(f"\n--- {client.client_name} downloads ---")
138
+ client.list_files()
139
+
140
+ # Try to download some files
141
+ for other_client in clients:
142
+ if other_client != client and other_client.uploaded_files:
143
+ file_to_download = random.choice(other_client.uploaded_files)
144
+ success = client.download_file(file_to_download)
145
+ time.sleep(1)
146
+
147
+ print("\n=== File operations completed ===")
148
+
149
+ # Disconnect all clients
150
+ for client in clients:
151
+ client.disconnect()
152
+
153
+
154
+ def interactive_mode():
155
+ """Run in interactive mode"""
156
+ client_name = input("Enter client name: ").strip() or "InteractiveClient"
157
+ client = FileClient(client_name)
158
+
159
+ if not client.connect():
160
+ return
161
+
162
+ print("\n=== File Sharing Client ===")
163
+ print("Commands:")
164
+ print(" upload <filename> <size> - Upload a file")
165
+ print(" download <filename> - Download a file")
166
+ print(" list - List uploaded files")
167
+ print(" quit - Exit")
168
+
169
+ try:
170
+ while True:
171
+ command = input(f"\n[{client_name}] > ").strip().split()
172
+
173
+ if not command:
174
+ continue
175
+
176
+ cmd = command[0].lower()
177
+
178
+ if cmd == 'quit':
179
+ break
180
+ elif cmd == 'upload' and len(command) >= 3:
181
+ filename = command[1]
182
+ try:
183
+ size = int(command[2])
184
+ client.upload_file(filename, size)
185
+ except ValueError:
186
+ print("Invalid size. Please enter a number.")
187
+ elif cmd == 'download' and len(command) >= 2:
188
+ filename = command[1]
189
+ client.download_file(filename)
190
+ elif cmd == 'list':
191
+ client.list_files()
192
+ else:
193
+ print("Invalid command or missing arguments")
194
+
195
+ except KeyboardInterrupt:
196
+ pass
197
+ finally:
198
+ client.disconnect()
199
+
200
+
201
+ def main():
202
+ import sys
203
+
204
+ if len(sys.argv) > 1 and sys.argv[1] == 'sim':
205
+ simulate_file_operations()
206
+ else:
207
+ interactive_mode()
208
+
209
+
210
+ if __name__ == "__main__":
211
+ main()
@@ -0,0 +1,252 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Monitoring Client Example
4
+
5
+ This example demonstrates how to use the IPC framework for system monitoring.
6
+ It shows metrics reporting and alert subscription patterns.
7
+ """
8
+
9
+ import time
10
+ import random
11
+ import threading
12
+ from .. import FrameworkClient, Message, MessageType
13
+
14
+ try:
15
+ import psutil
16
+ HAS_PSUTIL = True
17
+ except ImportError:
18
+ HAS_PSUTIL = False
19
+
20
+
21
+ class MonitoringClient:
22
+ def __init__(self, client_name: str, host: str = "localhost", port: int = 8888):
23
+ self.client_name = client_name
24
+ self.client = FrameworkClient("monitoring", host, port)
25
+ self.running = False
26
+ self.metrics_thread = None
27
+
28
+ def connect(self):
29
+ """Connect to the monitoring server"""
30
+ if self.client.connect():
31
+ print(f"Monitoring client '{self.client_name}' connected")
32
+
33
+ # Subscribe to alerts
34
+ self.client.subscribe("alerts", self.handle_alert)
35
+ return True
36
+ else:
37
+ print("Failed to connect to server")
38
+ return False
39
+
40
+ def handle_alert(self, message: Message):
41
+ """Handle system alerts"""
42
+ payload = message.payload
43
+ alert_type = payload.get('type', 'unknown')
44
+
45
+ if alert_type == 'high_cpu_alert':
46
+ metric = payload.get('metric', 'unknown')
47
+ value = payload.get('value', 0)
48
+ threshold = payload.get('threshold', 0)
49
+ severity = payload.get('severity', 'info')
50
+
51
+ print(f"\n🚨 ALERT [{severity.upper()}]: {alert_type}")
52
+ print(f" Metric: {metric}")
53
+ print(f" Current: {value}%")
54
+ print(f" Threshold: {threshold}%")
55
+ print(f" Time: {time.strftime('%H:%M:%S')}")
56
+
57
+ def send_metric(self, metric_name: str, value: float):
58
+ """Send a metric to the monitoring system"""
59
+ self.client.notify("metrics", {
60
+ 'metric': metric_name,
61
+ 'value': value,
62
+ 'client': self.client_name,
63
+ 'timestamp': time.time()
64
+ })
65
+
66
+ def get_system_metrics(self) -> dict:
67
+ """Get current system metrics"""
68
+ if HAS_PSUTIL:
69
+ try:
70
+ return {
71
+ 'cpu_usage': psutil.cpu_percent(interval=1),
72
+ 'memory_usage': psutil.virtual_memory().percent,
73
+ 'disk_usage': psutil.disk_usage('/').percent,
74
+ 'load_average': psutil.getloadavg()[0] * 100, # 1-minute load average as percentage
75
+ }
76
+ except Exception:
77
+ pass
78
+
79
+ # Fallback with simulated metrics if psutil not available or fails
80
+ return {
81
+ 'cpu_usage': random.uniform(10, 95),
82
+ 'memory_usage': random.uniform(30, 80),
83
+ 'disk_usage': random.uniform(40, 70),
84
+ 'load_average': random.uniform(5, 50),
85
+ }
86
+
87
+ def start_monitoring(self, interval: float = 5.0):
88
+ """Start continuous monitoring"""
89
+ self.running = True
90
+
91
+ def monitor_loop():
92
+ while self.running:
93
+ try:
94
+ metrics = self.get_system_metrics()
95
+
96
+ for metric_name, value in metrics.items():
97
+ self.send_metric(metric_name, value)
98
+ print(f"[{self.client_name}] {metric_name}: {value:.1f}%")
99
+
100
+ print(f"[{self.client_name}] Metrics sent at {time.strftime('%H:%M:%S')}")
101
+ time.sleep(interval)
102
+
103
+ except Exception as e:
104
+ print(f"Error in monitoring loop: {e}")
105
+ time.sleep(interval)
106
+
107
+ self.metrics_thread = threading.Thread(target=monitor_loop, daemon=True)
108
+ self.metrics_thread.start()
109
+ print(f"Started monitoring with {interval}s interval")
110
+
111
+ def stop_monitoring(self):
112
+ """Stop monitoring"""
113
+ self.running = False
114
+ if self.metrics_thread and self.metrics_thread.is_alive():
115
+ self.metrics_thread.join(timeout=1.0)
116
+ print("Monitoring stopped")
117
+
118
+ def send_custom_metric(self, name: str, value: float):
119
+ """Send a custom metric"""
120
+ self.send_metric(name, value)
121
+ print(f"Custom metric sent: {name} = {value}")
122
+
123
+ def disconnect(self):
124
+ """Disconnect from the server"""
125
+ self.stop_monitoring()
126
+ self.client.disconnect()
127
+ print(f"Monitoring client '{self.client_name}' disconnected")
128
+
129
+
130
+ def simulate_monitoring():
131
+ """Simulate multiple monitoring clients"""
132
+ clients = []
133
+
134
+ # Create monitoring clients for different "servers"
135
+ server_names = ["web-server-1", "db-server", "api-gateway"]
136
+
137
+ for server_name in server_names:
138
+ client = MonitoringClient(server_name)
139
+ if client.connect():
140
+ clients.append(client)
141
+ # Start monitoring with different intervals
142
+ client.start_monitoring(interval=random.uniform(3, 7))
143
+ time.sleep(0.5)
144
+
145
+ if not clients:
146
+ print("No monitoring clients could connect")
147
+ return
148
+
149
+ print(f"\n=== Started monitoring {len(clients)} systems ===")
150
+ print("Monitoring will run for 30 seconds...")
151
+ print("Watch for alerts when CPU usage exceeds 80%")
152
+
153
+ try:
154
+ time.sleep(30)
155
+ except KeyboardInterrupt:
156
+ print("\nStopping simulation...")
157
+
158
+ # Stop all monitoring
159
+ for client in clients:
160
+ client.disconnect()
161
+
162
+ print("\n=== Monitoring simulation completed ===")
163
+
164
+
165
+ def interactive_mode():
166
+ """Run in interactive mode"""
167
+ client_name = input("Enter monitoring client name: ").strip() or "MonitoringClient"
168
+ client = MonitoringClient(client_name)
169
+
170
+ if not client.connect():
171
+ return
172
+
173
+ print("\n=== Monitoring Client ===")
174
+ print("Commands:")
175
+ print(" start [interval] - Start automatic monitoring (default 5s)")
176
+ print(" stop - Stop automatic monitoring")
177
+ print(" metric <name> <val> - Send custom metric")
178
+ print(" status - Show current system metrics")
179
+ print(" quit - Exit")
180
+
181
+ auto_monitoring = False
182
+
183
+ try:
184
+ while True:
185
+ if not auto_monitoring:
186
+ command = input(f"\n[{client_name}] > ").strip().split()
187
+ else:
188
+ # In auto monitoring mode, just wait for input with timeout
189
+ print(f"\n[{client_name}] (auto-monitoring) > ", end="", flush=True)
190
+ command = input().strip().split()
191
+
192
+ if not command:
193
+ continue
194
+
195
+ cmd = command[0].lower()
196
+
197
+ if cmd == 'quit':
198
+ break
199
+ elif cmd == 'start':
200
+ if not auto_monitoring:
201
+ interval = 5.0
202
+ if len(command) > 1:
203
+ try:
204
+ interval = float(command[1])
205
+ except ValueError:
206
+ print("Invalid interval, using 5 seconds")
207
+ client.start_monitoring(interval)
208
+ auto_monitoring = True
209
+ else:
210
+ print("Monitoring is already running. Use 'stop' first.")
211
+ elif cmd == 'stop':
212
+ if auto_monitoring:
213
+ client.stop_monitoring()
214
+ auto_monitoring = False
215
+ else:
216
+ print("Monitoring is not running")
217
+ elif cmd == 'metric' and len(command) >= 3:
218
+ try:
219
+ name = command[1]
220
+ value = float(command[2])
221
+ client.send_custom_metric(name, value)
222
+ except ValueError:
223
+ print("Invalid metric value")
224
+ elif cmd == 'status':
225
+ metrics = client.get_system_metrics()
226
+ print("Current system metrics:")
227
+ for name, value in metrics.items():
228
+ print(f" {name}: {value:.1f}%")
229
+ else:
230
+ print("Invalid command or missing arguments")
231
+
232
+ except KeyboardInterrupt:
233
+ pass
234
+ finally:
235
+ client.disconnect()
236
+
237
+
238
+ def main():
239
+ import sys
240
+
241
+ print("System Monitoring Client")
242
+ print("This example requires 'psutil' for real system metrics.")
243
+ print("If not available, simulated metrics will be used.\n")
244
+
245
+ if len(sys.argv) > 1 and sys.argv[1] == 'sim':
246
+ simulate_monitoring()
247
+ else:
248
+ interactive_mode()
249
+
250
+
251
+ if __name__ == "__main__":
252
+ main()
@@ -0,0 +1,43 @@
1
+ """
2
+ Custom exceptions for the IPC Framework
3
+ """
4
+
5
+
6
+ class IPCError(Exception):
7
+ """Base exception for IPC Framework"""
8
+ pass
9
+
10
+
11
+ class ConnectionError(IPCError):
12
+ """Raised when connection-related errors occur"""
13
+ pass
14
+
15
+
16
+ class RoutingError(IPCError):
17
+ """Raised when message routing fails"""
18
+ pass
19
+
20
+
21
+ class AuthenticationError(IPCError):
22
+ """Raised when authentication fails"""
23
+ pass
24
+
25
+
26
+ class ChannelError(IPCError):
27
+ """Raised when channel operations fail"""
28
+ pass
29
+
30
+
31
+ class ApplicationError(IPCError):
32
+ """Raised when application operations fail"""
33
+ pass
34
+
35
+
36
+ class SerializationError(IPCError):
37
+ """Raised when message serialization/deserialization fails"""
38
+ pass
39
+
40
+
41
+ class TimeoutError(IPCError):
42
+ """Raised when operations timeout"""
43
+ pass
ipc_framework/py.typed ADDED
@@ -0,0 +1,2 @@
1
+ # Marker file for PEP 561.
2
+ # The ipc_framework package supports type hints.