-
Notifications
You must be signed in to change notification settings - Fork 0
Resource Cleanup
santiago edited this page Jan 29, 2026
·
1 revision
The framework provides built-in support for resource cleanup through the IDisposable pattern.
Implement IDisposable for services that need cleanup (database connections, file handles, network connections, etc.):
from azfunc_boot import IDisposable
class DatabaseConnection(IDisposable):
def __init__(self, connection_string: str):
self.connection = create_connection(connection_string)
async def dispose(self):
# Cleanup resources
await self.connection.close()
self.connection = NoneScoped services implementing IDisposable are automatically disposed when the scope ends:
# Register as scoped service
@register_service
def register_services(self):
self.container.add_scoped(
IDatabaseConnection,
lambda: DatabaseConnection(connection_string="...")
)
# In your controller
async def process_request(self, req: func.HttpRequest):
# Scope is created
db: IDatabaseConnection = self.container.get_service(IDatabaseConnection)
# Use the connection...
await db.execute_query("SELECT * FROM users")
# When method completes, scope ends
# dispose() is automatically called on dbImplement IDisposable for services that:
- Open database connections
- Create file handles
- Establish network connections
- Allocate unmanaged resources
- Need cleanup logic
from azfunc_boot import IDisposable
class DatabaseContext(IDisposable):
def __init__(self, connection_string: str):
self.connection = None
self.connection_string = connection_string
async def connect(self):
self.connection = await create_async_connection(self.connection_string)
async def execute_query(self, query: str):
if not self.connection:
await self.connect()
return await self.connection.execute(query)
async def dispose(self):
if self.connection:
await self.connection.close()
self.connection = None
self._logger.info("Database connection closed")from azfunc_boot import IDisposable
class FileProcessor(IDisposable):
def __init__(self, file_path: str):
self.file = open(file_path, 'r')
def read(self):
return self.file.read()
async def dispose(self):
if self.file:
self.file.close()
self.file = NoneWhen a scope ends, services are disposed in reverse order of creation:
- Last created service is disposed first
- First created service is disposed last
This ensures dependencies are disposed before the services that depend on them.
While automatic disposal is recommended, you can also manually dispose services:
# Get a scoped service
service = self.container.get_service(IService)
# Use it...
# Manually dispose (if needed)
if isinstance(service, IDisposable):
await service.dispose()However, this is usually not necessary as the framework handles disposal automatically.
-
Always implement
IDisposablefor resources: If your service uses resources that need cleanup, implementIDisposable - Use scoped lifetime: Services with resources should typically be registered as scoped
-
Idempotent disposal: Make
dispose()safe to call multiple times -
Async cleanup: Use
async def dispose()for async cleanup operations