vega-framework 0.1.29__py3-none-any.whl → 0.1.30__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,360 @@
1
+ # Event Publishing Syntax Guide
2
+
3
+ Vega Events offers **three different syntaxes** for publishing events, from verbose to ultra-clean. Choose the one that best fits your use case!
4
+
5
+ ---
6
+
7
+ ## 📊 Syntax Comparison
8
+
9
+ ### ❌ Verbose Syntax (Not Recommended)
10
+
11
+ ```python
12
+ from vega.events import get_event_bus
13
+
14
+ # Create event
15
+ event = UserCreated(user_id="123", email="test@test.com", name="Test")
16
+
17
+ # Get bus and publish
18
+ bus = get_event_bus()
19
+ await bus.publish(event)
20
+ ```
21
+
22
+ **When to use**: Almost never. Only when you need a custom event bus.
23
+
24
+ ---
25
+
26
+ ### ✅ Simple Syntax (Recommended Default)
27
+
28
+ ```python
29
+ # Create event
30
+ event = UserCreated(user_id="123", email="test@test.com", name="Test")
31
+
32
+ # Publish
33
+ await event.publish()
34
+ ```
35
+
36
+ **When to use**:
37
+ - Default choice for most scenarios
38
+ - When you need to inspect/modify the event before publishing
39
+ - When publishing conditionally
40
+ - When you want explicit control
41
+
42
+ **Advantages**:
43
+ - Clean and intuitive
44
+ - No need to import `get_event_bus()`
45
+ - Event can be inspected before publishing
46
+ - Can add metadata before publishing
47
+
48
+ ---
49
+
50
+ ### 🌟 Ultra-Clean Syntax (Auto-Publish)
51
+
52
+ **Step 1: Enable auto-publish on event class**
53
+
54
+ ```python
55
+ from dataclasses import dataclass
56
+ from vega.events import Event
57
+
58
+ @dataclass(frozen=True)
59
+ class UserCreated(Event, auto_publish=True): # ← Enable auto-publish
60
+ user_id: str
61
+ email: str
62
+ name: str
63
+
64
+ def __post_init__(self):
65
+ super().__init__()
66
+ ```
67
+
68
+ **Step 2: Just await the constructor!**
69
+
70
+ ```python
71
+ # Event is automatically published when instantiated!
72
+ await UserCreated(user_id="123", email="test@test.com", name="Test")
73
+ ```
74
+
75
+ **When to use**:
76
+ - In workflows where the event should ALWAYS be published immediately
77
+ - For fire-and-forget events
78
+ - In Interactor/Mediator patterns (similar to how they work)
79
+ - When you want the cleanest possible syntax
80
+
81
+ **Advantages**:
82
+ - Cleanest syntax - just like Interactors!
83
+ - No `.publish()` call needed
84
+ - Perfect for event-driven workflows
85
+ - Enforces immediate publishing
86
+
87
+ **Limitations**:
88
+ - Cannot inspect/modify event before publishing
89
+ - Cannot publish conditionally (event is always published)
90
+ - Event instance is not accessible (returns coroutine)
91
+
92
+ ---
93
+
94
+ ## 🎯 Detailed Examples
95
+
96
+ ### Example 1: Simple Syntax with Conditional Publishing
97
+
98
+ ```python
99
+ from vega.events import Event
100
+ from dataclasses import dataclass
101
+
102
+ @dataclass(frozen=True)
103
+ class OrderPlaced(Event):
104
+ order_id: str
105
+ amount: float
106
+ customer_email: str
107
+
108
+ def __post_init__(self):
109
+ super().__init__()
110
+
111
+
112
+ async def place_order(order_id: str, amount: float, customer_email: str):
113
+ """Place an order and optionally publish event"""
114
+
115
+ # Create order...
116
+ order = save_order(order_id, amount, customer_email)
117
+
118
+ # Create event
119
+ event = OrderPlaced(
120
+ order_id=order.id,
121
+ amount=order.amount,
122
+ customer_email=order.customer_email
123
+ )
124
+
125
+ # Add metadata
126
+ event.add_metadata('source', 'web_app')
127
+ event.add_metadata('user_id', get_current_user_id())
128
+
129
+ # Publish conditionally
130
+ if order.amount > 100: # Only publish for large orders
131
+ await event.publish()
132
+
133
+ return order
134
+ ```
135
+
136
+ ### Example 2: Auto-Publish in Workflows
137
+
138
+ ```python
139
+ from vega.events import Event
140
+ from dataclasses import dataclass
141
+
142
+ # Enable auto-publish for workflow events
143
+ @dataclass(frozen=True)
144
+ class PaymentProcessed(Event, auto_publish=True):
145
+ payment_id: str
146
+ order_id: str
147
+ amount: float
148
+
149
+ def __post_init__(self):
150
+ super().__init__()
151
+
152
+ @dataclass(frozen=True)
153
+ class OrderShipped(Event, auto_publish=True):
154
+ order_id: str
155
+ tracking_number: str
156
+
157
+ def __post_init__(self):
158
+ super().__init__()
159
+
160
+
161
+ async def complete_order_workflow(order_id: str, amount: float):
162
+ """Complete order processing workflow"""
163
+
164
+ # Process payment - auto-publishes!
165
+ await PaymentProcessed(
166
+ payment_id=generate_payment_id(),
167
+ order_id=order_id,
168
+ amount=amount
169
+ )
170
+
171
+ # Ship order - auto-publishes!
172
+ await OrderShipped(
173
+ order_id=order_id,
174
+ tracking_number=generate_tracking_number()
175
+ )
176
+
177
+ # Clean, sequential workflow!
178
+ ```
179
+
180
+ ### Example 3: Mixed Approach
181
+
182
+ ```python
183
+ from vega.events import Event
184
+ from dataclasses import dataclass
185
+
186
+ # Manual publish for main events
187
+ @dataclass(frozen=True)
188
+ class UserRegistered(Event):
189
+ user_id: str
190
+ email: str
191
+
192
+ def __post_init__(self):
193
+ super().__init__()
194
+
195
+ # Auto-publish for side-effect events
196
+ @dataclass(frozen=True)
197
+ class WelcomeEmailSent(Event, auto_publish=True):
198
+ user_id: str
199
+ email: str
200
+
201
+ def __post_init__(self):
202
+ super().__init__()
203
+
204
+
205
+ async def register_user(email: str, password: str):
206
+ """Register new user"""
207
+
208
+ # Create user...
209
+ user = create_user(email, password)
210
+
211
+ # Main event - manual publish with metadata
212
+ event = UserRegistered(user_id=user.id, email=user.email)
213
+ event.add_metadata('registration_source', 'web')
214
+ await event.publish()
215
+
216
+ # Side-effect event - auto-publish
217
+ await WelcomeEmailSent(user_id=user.id, email=user.email)
218
+
219
+ return user
220
+ ```
221
+
222
+ ### Example 4: Integration with Interactors
223
+
224
+ ```python
225
+ from vega.patterns import Interactor
226
+ from vega.di import bind
227
+ from vega.events import Event
228
+ from dataclasses import dataclass
229
+
230
+ # Auto-publish for Interactor events
231
+ @dataclass(frozen=True)
232
+ class UserCreated(Event, auto_publish=True):
233
+ user_id: str
234
+ email: str
235
+ name: str
236
+
237
+ def __post_init__(self):
238
+ super().__init__()
239
+
240
+
241
+ class CreateUser(Interactor[User]):
242
+ """Create a new user"""
243
+
244
+ def __init__(self, name: str, email: str):
245
+ self.name = name
246
+ self.email = email
247
+
248
+ @bind
249
+ async def call(self, repository: UserRepository) -> User:
250
+ # Domain logic
251
+ user = User(name=self.name, email=self.email)
252
+ user = await repository.save(user)
253
+
254
+ # Publish event - auto-publishes!
255
+ await UserCreated(
256
+ user_id=user.id,
257
+ email=user.email,
258
+ name=user.name
259
+ )
260
+
261
+ return user
262
+
263
+
264
+ # Usage - both use similar syntax!
265
+ user = await CreateUser(name="John", email="john@example.com")
266
+ ```
267
+
268
+ ---
269
+
270
+ ## 🤔 Decision Guide
271
+
272
+ Use this flowchart to decide which syntax to use:
273
+
274
+ ```
275
+ Do you need a custom event bus?
276
+ ├─ YES → Use: bus.publish(event)
277
+ └─ NO
278
+
279
+ Do you need to modify the event before publishing?
280
+ ├─ YES → Use: event.publish()
281
+ └─ NO
282
+
283
+ Do you need conditional publishing?
284
+ ├─ YES → Use: event.publish()
285
+ └─ NO
286
+
287
+ Is this a workflow/always-publish scenario?
288
+ ├─ YES → Use: auto_publish=True
289
+ └─ NO → Use: event.publish() (default)
290
+ ```
291
+
292
+ ---
293
+
294
+ ## ⚡ Performance Notes
295
+
296
+ All three syntaxes have identical performance:
297
+ - Auto-publish uses metaclass (zero runtime overhead)
298
+ - `.publish()` calls the same underlying bus
299
+ - `bus.publish()` is the same method
300
+
301
+ **Choose based on code clarity, not performance!**
302
+
303
+ ---
304
+
305
+ ## 🎨 Best Practices
306
+
307
+ ### ✅ DO
308
+
309
+ ```python
310
+ # Use auto-publish for workflow events
311
+ @dataclass(frozen=True)
312
+ class StepCompleted(Event, auto_publish=True):
313
+ ...
314
+
315
+ # Use manual publish for events that need metadata
316
+ event = UserCreated(...)
317
+ event.add_metadata('source', 'api')
318
+ await event.publish()
319
+
320
+ # Use consistent style within a module
321
+ ```
322
+
323
+ ### ❌ DON'T
324
+
325
+ ```python
326
+ # Don't mix styles unnecessarily
327
+ await UserCreated(...) # auto-publish
328
+ await event.publish() # manual publish
329
+ # Pick one approach per event type!
330
+
331
+ # Don't use auto-publish if you need the event object
332
+ event = UserCreated(...) # Won't work with auto_publish=True!
333
+ # auto_publish returns a coroutine, not the event
334
+
335
+ # Don't use verbose syntax unless absolutely necessary
336
+ bus = get_event_bus()
337
+ await bus.publish(event) # Prefer: await event.publish()
338
+ ```
339
+
340
+ ---
341
+
342
+ ## 📚 Summary
343
+
344
+ | Syntax | Code | Use Case |
345
+ |--------|------|----------|
346
+ | **Verbose** | `await bus.publish(event)` | Custom event bus |
347
+ | **Simple** | `await event.publish()` | Default choice ✅ |
348
+ | **Auto-Publish** | `await EventName(...)` | Workflows, always-publish 🌟 |
349
+
350
+ **Recommendation**: Start with **Simple syntax** as default, use **Auto-Publish** for workflow events.
351
+
352
+ ---
353
+
354
+ ## 🔗 See Also
355
+
356
+ - [README.md](README.md) - Full event system documentation
357
+ - [EVENT_BUS_SUMMARY.md](../../EVENT_BUS_SUMMARY.md) - Implementation summary
358
+ - [Examples](../../examples/events/) - Working examples
359
+ - [auto_publish_example.py](../../examples/events/auto_publish_example.py) - Auto-publish demo
360
+ - [simple_syntax_example.py](../../examples/events/simple_syntax_example.py) - Simple syntax demo
@@ -0,0 +1,30 @@
1
+ """Event system for domain events and event-driven architecture"""
2
+ from vega.events.event import Event, PublishableEventMeta
3
+ from vega.events.bus import EventBus, get_event_bus, set_event_bus
4
+ from vega.events.decorators import subscribe, event_handler, trigger
5
+ from vega.events.middleware import (
6
+ EventMiddleware,
7
+ LoggingEventMiddleware,
8
+ MetricsEventMiddleware,
9
+ ValidationEventMiddleware,
10
+ EnrichmentEventMiddleware,
11
+ )
12
+
13
+ __all__ = [
14
+ # Core
15
+ 'Event',
16
+ 'PublishableEventMeta',
17
+ 'EventBus',
18
+ 'get_event_bus',
19
+ 'set_event_bus',
20
+ # Decorators
21
+ 'subscribe',
22
+ 'event_handler',
23
+ 'trigger',
24
+ # Middleware
25
+ 'EventMiddleware',
26
+ 'LoggingEventMiddleware',
27
+ 'MetricsEventMiddleware',
28
+ 'ValidationEventMiddleware',
29
+ 'EnrichmentEventMiddleware',
30
+ ]