Events API
dcc_mcp_core.EventBus
EventBus
Thread-safe publish/subscribe event bus backed by DashMap.
Constructor
python
from dcc_mcp_core import EventBus
bus = EventBus()Methods
| Method | Returns | Description |
|---|---|---|
subscribe(event_name, callback) | int | Subscribe a callable. Returns subscriber ID |
unsubscribe(event_name, subscriber_id) | bool | Unsubscribe by ID. Returns True if found |
publish(event_name, **kwargs) | — | Call all subscribers with kwargs |
Dunder Methods
| Method | Description |
|---|---|
__repr__ | EventBus(subscriptions=N) |
Behavior
- Subscribers receive keyword arguments from
publish(event_name, **kwargs) - Exceptions in subscribers are logged via
tracingbut do not propagate - Callbacks are collected before invocation to avoid DashMap deadlocks
- Multiple subscribers per event are supported
- Subscriber IDs are monotonically increasing (starting at 1)
Example
python
bus = EventBus()
def on_action(action_name=None, **kwargs):
print(f"Action: {action_name}")
sid = bus.subscribe("action.executed", on_action)
bus.publish("action.executed", action_name="create_sphere")
bus.unsubscribe("action.executed", sid)ToolRecorder
Records per-tool execution time and success/failure counters. Use this to collect performance telemetry for any tools your code executes.
Constructor
python
from dcc_mcp_core import ToolRecorder
recorder = ToolRecorder("my-service")| Parameter | Type | Description |
|---|---|---|
scope | str | Logical name for this recorder instance (e.g. service or module name) |
Methods
| Method | Returns | Description |
|---|---|---|
start(action_name, dcc_name) | RecordingGuard | Start timing a tool; returns a RAII guard |
metrics(action_name) | ToolMetrics | None | Aggregated metrics for a specific action; None if no data |
all_metrics() | list[ToolMetrics] | Aggregated metrics for all recorded actions |
reset() | None | Clear all in-memory statistics |
Example
python
from dcc_mcp_core import ToolRecorder
recorder = ToolRecorder("maya-skill-server")
# Manual guard usage
guard = recorder.start("create_sphere", "maya")
try:
# ... do work ...
guard.finish(success=True)
except Exception:
guard.finish(success=False)
raise
# Context manager usage (success=True if no exception)
with recorder.start("delete_mesh", "maya"):
pass # work here
# Query metrics
m = recorder.metrics("create_sphere")
if m:
print(f"calls={m.invocation_count}, success_rate={m.success_rate():.2%}")
print(f"avg={m.avg_duration_ms:.1f}ms p95={m.p95_duration_ms:.1f}ms")RecordingGuard
RAII guard returned by ToolRecorder.start(). Automatically records the duration and outcome.
Methods
| Method | Returns | Description |
|---|---|---|
finish(success) | None | Commit the recording with the given success flag |
__enter__ | RecordingGuard | Context manager entry |
__exit__ | None | Context manager exit (success=True when no exception was raised) |
ToolMetrics
Read-only snapshot of per-tool performance metrics. Obtained from ToolRecorder.metrics() or ToolRecorder.all_metrics().
Properties
| Property | Type | Description |
|---|---|---|
action_name | str | Action this metric belongs to |
invocation_count | int | Total number of calls recorded |
success_count | int | Number of successful calls |
failure_count | int | Number of failed calls |
avg_duration_ms | float | Mean execution time in milliseconds |
p95_duration_ms | float | 95th-percentile execution time in milliseconds |
p99_duration_ms | float | 99th-percentile execution time in milliseconds |
Methods
| Method | Returns | Description |
|---|---|---|
success_rate() | float | Success ratio in [0.0, 1.0] |
Example
python
recorder = ToolRecorder("server")
for _ in range(10):
with recorder.start("ping", "maya"):
pass
all_m = recorder.all_metrics()
for m in all_m:
print(
f"{m.action_name}: "
f"{m.invocation_count} calls, "
f"{m.success_rate():.0%} success, "
f"avg {m.avg_duration_ms:.1f}ms"
)