Coverage for src / dataknobs_bots / registry / backend.py: 57%
30 statements
« prev ^ index » next coverage.py v7.13.0, created at 2025-12-16 10:13 -0700
« prev ^ index » next coverage.py v7.13.0, created at 2025-12-16 10:13 -0700
1"""Registry backend protocol for pluggable storage."""
3from __future__ import annotations
5from typing import TYPE_CHECKING, Any, Protocol, runtime_checkable
7if TYPE_CHECKING:
8 from .models import Registration
11@runtime_checkable
12class RegistryBackend(Protocol):
13 """Protocol for bot registry storage backends.
15 Implementations store bot configurations with metadata.
16 The backend is responsible for persistence; the BotRegistry
17 handles caching and bot instantiation.
19 This protocol defines the interface for storage backends:
20 - InMemoryBackend: Simple dict storage (default, good for tests)
21 - PostgreSQLBackend: Database persistence (future/external)
22 - RedisBackend: Distributed caching (future/external)
24 All methods are async to support both sync and async backends.
26 Example:
27 ```python
28 class MyCustomBackend:
29 async def initialize(self) -> None:
30 # Setup database connection
31 ...
33 async def register(self, bot_id: str, config: dict, status: str = "active"):
34 # Store in database
35 ...
37 # ... implement other methods
38 ```
39 """
41 async def initialize(self) -> None:
42 """Initialize the backend (create tables, connections, etc.).
44 Called before the backend is used. Should be idempotent.
45 """
46 ...
48 async def close(self) -> None:
49 """Close the backend (release connections, etc.).
51 Called when the registry is shutting down.
52 """
53 ...
55 async def register(
56 self,
57 bot_id: str,
58 config: dict[str, Any],
59 status: str = "active",
60 ) -> Registration:
61 """Register a bot or update existing registration.
63 If a registration with the same bot_id exists, it should be updated
64 (config replaced, status updated, updated_at set to now).
66 Args:
67 bot_id: Unique bot identifier
68 config: Bot configuration dictionary (should be portable)
69 status: Registration status (default: active)
71 Returns:
72 Registration object with metadata
73 """
74 ...
76 async def get(self, bot_id: str) -> Registration | None:
77 """Get registration by ID.
79 Should update last_accessed_at timestamp on access.
81 Args:
82 bot_id: Bot identifier
84 Returns:
85 Registration if found, None otherwise
86 """
87 ...
89 async def get_config(self, bot_id: str) -> dict[str, Any] | None:
90 """Get just the config for a bot.
92 Convenience method that returns only the config dict.
93 Should also update last_accessed_at.
95 Args:
96 bot_id: Bot identifier
98 Returns:
99 Config dict if found, None otherwise
100 """
101 ...
103 async def exists(self, bot_id: str) -> bool:
104 """Check if an active registration exists.
106 Args:
107 bot_id: Bot identifier
109 Returns:
110 True if registration exists and is active
111 """
112 ...
114 async def unregister(self, bot_id: str) -> bool:
115 """Hard delete a registration.
117 Permanently removes the registration from storage.
119 Args:
120 bot_id: Bot identifier
122 Returns:
123 True if deleted, False if not found
124 """
125 ...
127 async def deactivate(self, bot_id: str) -> bool:
128 """Soft delete (set status to inactive).
130 Marks the registration as inactive without deleting.
131 Inactive registrations should not be returned by exists()
132 or list_active().
134 Args:
135 bot_id: Bot identifier
137 Returns:
138 True if deactivated, False if not found
139 """
140 ...
142 async def list_active(self) -> list[Registration]:
143 """List all active registrations.
145 Returns:
146 List of active Registration objects
147 """
148 ...
150 async def list_all(self) -> list[Registration]:
151 """List all registrations including inactive.
153 Returns:
154 List of all Registration objects
155 """
156 ...
158 async def list_ids(self) -> list[str]:
159 """List active bot IDs only.
161 More efficient than list_active() when only IDs are needed.
163 Returns:
164 List of active bot IDs
165 """
166 ...
168 async def count(self) -> int:
169 """Count active registrations.
171 Returns:
172 Number of active registrations
173 """
174 ...
176 async def clear(self) -> None:
177 """Clear all registrations.
179 Primarily useful for testing.
180 """
181 ...